bootstrap.H 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // -*- mode: c++; coding: utf-8 -*-
  2. /// @file bootstrap.H
  3. /// @brief Before all other ra:: includes.
  4. // (c) Daniel Llorens - 2013-2015, 2017, 2019
  5. // This library is free software; you can redistribute it and/or modify it under
  6. // the terms of the GNU General Public License as published by the Free
  7. // Software Foundation; either version 3 of the License, or (at your option) any
  8. // later version.
  9. #pragma once
  10. #include <sys/types.h> // ssize_t
  11. #include "ra/tuple-list.H"
  12. #include "ra/tuple-dynamic.H"
  13. #if defined(RA_CHECK_BOUNDS) && RA_CHECK_BOUNDS==0
  14. #define CHECK_BOUNDS( cond )
  15. #else
  16. #define CHECK_BOUNDS( cond ) RA_ASSERT( cond )
  17. #endif
  18. namespace ra {
  19. constexpr int VERSION = 10; // to force or prevent upgrades on dependents
  20. constexpr int LAST_ISSUE = 46; // numbered as [ra··] t/o the code. 08-10 are free.
  21. constexpr int LAST_MAN = 116; // numbered as [ma··] t/o the manual and examples/tests
  22. static_assert(sizeof(int)>=4, "bad assumption on int");
  23. using rank_t = int;
  24. using dim_t = ssize_t;
  25. constexpr dim_t DIM_ANY = -1099999444;
  26. constexpr dim_t DIM_BAD = -1099999888;
  27. constexpr rank_t RANK_ANY = -1099999444;
  28. constexpr rank_t RANK_BAD = -1099999888;
  29. constexpr dim_t dim_prod(dim_t const a, dim_t const b)
  30. {
  31. return (a==DIM_ANY) ? DIM_ANY : ((b==DIM_ANY) ? DIM_ANY : a*b);
  32. }
  33. constexpr rank_t rank_sum(rank_t const a, rank_t const b)
  34. {
  35. return (a==RANK_ANY) ? RANK_ANY : ((b==RANK_ANY) ? RANK_ANY : a+b);
  36. }
  37. constexpr rank_t rank_diff(rank_t const a, rank_t const b)
  38. {
  39. return (a==RANK_ANY) ? RANK_ANY : ((b==RANK_ANY) ? RANK_ANY : a-b);
  40. }
  41. constexpr bool inside(dim_t const i, dim_t const b)
  42. {
  43. return i>=0 && i<b;
  44. }
  45. constexpr bool inside(dim_t const i, dim_t const a, dim_t const b)
  46. {
  47. return i>=a && i<b;
  48. }
  49. // used in array constructors to mean ‘don't initalize’.
  50. enum none_t { none };
  51. // used in array constructors to mean ‘don't instantiate’
  52. struct no_arg {};
  53. // Order of decl issues.
  54. template <class C> struct Scalar; // for type predicates
  55. template <class T, rank_t RANK=RANK_ANY> struct View; // for cell_iterator
  56. template <class V, class Enable=void> struct ra_traits_def;
  57. template <class S> struct default_strides_ {};
  58. template <class tend> struct default_strides_<std::tuple<tend>> { using type = mp::int_list<1>; };
  59. template <> struct default_strides_<std::tuple<>> { using type = mp::int_list<>; };
  60. template <class t0, class t1, class ... ti>
  61. struct default_strides_<std::tuple<t0, t1, ti ...>>
  62. {
  63. using rest = typename default_strides_<std::tuple<t1, ti ...>>::type;
  64. static int const stride0 = t1::value * mp::first<rest>::value;
  65. using type = mp::cons<mp::int_t<stride0>, rest>;
  66. };
  67. template <class S> using default_strides = typename default_strides_<S>::type;
  68. template <int n> struct dots_t
  69. {
  70. static_assert(n>=0);
  71. constexpr static rank_t rank_s() { return n; }
  72. };
  73. template <int n> constexpr dots_t<n> dots = dots_t<n>();
  74. constexpr auto all = dots<1>;
  75. template <int n> struct insert_t
  76. {
  77. static_assert(n>=0);
  78. constexpr static rank_t rank_s() { return n; }
  79. };
  80. template <int n=1> constexpr insert_t<n> insert = insert_t<n>();
  81. // Used by cell_iterator / cell_iterator_small.
  82. template <class C>
  83. struct CellFlat
  84. {
  85. C c;
  86. constexpr void operator+=(dim_t const s) { c.p += s; }
  87. constexpr C & operator*() { return c; }
  88. };
  89. // Common to View / SmallBase.
  90. template <int cell_rank, class A> inline constexpr auto
  91. iter(A && a) { return std::forward<A>(a).template iter<cell_rank>(); }
  92. // Defined in wrank.H but used in big.H (selectors, etc).
  93. template <class A, class ... I> inline constexpr auto from(A && a, I && ... i);
  94. // Extended by operators.H and repeated in global.H.
  95. // TODO All users be int, then this take int.
  96. constexpr inline bool any(bool const x) { return x; }
  97. constexpr inline bool every(bool const x) { return x; }
  98. constexpr inline bool odd(unsigned int N) { return N & 1; }
  99. // This logically belongs in ra/small.H, but it's here so that we can return ra:: types from shape().
  100. // ---------------------
  101. // nested braces for Small initializers
  102. // ---------------------
  103. // The general SmallArray has 4 constructors,
  104. // 1. The empty constructor.
  105. // 2. The scalar constructor. This is needed when T isn't registered as ra::scalar, which I don't think should be required purely for container use.
  106. // 3. The ravel constructor.
  107. // 4. The nested constructor.
  108. // When SmallArray has rank 1, or the first dimension is empty, or the shape is [1] or [], several of the constructors above become ambiguous. We solve this by defining the constructor arguments to variants of no_arg.
  109. template <class T, class sizes, class Enable=void>
  110. struct nested_tuple;
  111. // ambiguity with empty constructor and scalar constructor.
  112. // if size(0) is 0, then prefer the empty constructor.
  113. // if size(0) is 1...
  114. template <class sizes> constexpr bool no_nested = (mp::first<sizes>::value<1);
  115. template <> constexpr bool no_nested<mp::nil> = true;
  116. template <> constexpr bool no_nested<mp::int_list<1>> = true;
  117. template <class T, class sizes>
  118. using nested_arg = std::conditional_t<no_nested<sizes>,
  119. std::tuple<no_arg>, // match the template for SmallArray.
  120. typename nested_tuple<T, sizes>::list>;
  121. // ambiguity with scalar constructors (for rank 0) and nested_tuple (for rank 1).
  122. template <class sizes> constexpr bool no_ravel = ((mp::len<sizes> <=1) || (mp::apply<mp::prod, sizes>::value <= 1));
  123. template <class T, class sizes>
  124. using ravel_arg = std::conditional_t<no_ravel<sizes>,
  125. std::tuple<no_arg, no_arg>, // match the template for SmallArray.
  126. mp::makelist<mp::apply<mp::prod, sizes>::value, T>>;
  127. template <class T, class sizes, class strides = default_strides<sizes>> struct SmallView; // for cell_iterator_small
  128. template <class T, class sizes, class strides = default_strides<sizes>,
  129. class nested_arg_ = nested_arg<T, sizes>, class ravel_arg_ = ravel_arg<T, sizes>>
  130. struct SmallArray;
  131. template <class T, dim_t ... sizes> using Small = SmallArray<T, mp::int_list<sizes ...>>;
  132. template <class T>
  133. struct nested_tuple<T, mp::nil>
  134. {
  135. using sub = no_arg;
  136. using list = std::tuple<no_arg>; // match the template for SmallArray.
  137. };
  138. template <class T, int S0>
  139. struct nested_tuple<T, mp::int_list<S0>>
  140. {
  141. using sub = T;
  142. using list = mp::makelist<S0, T>;
  143. };
  144. template <class T, int S0, int S1, int ... S>
  145. struct nested_tuple<T, mp::int_list<S0, S1, S ...>>
  146. {
  147. using sub = Small<T, S1, S ...>;
  148. using list = mp::makelist<S0, sub>;
  149. };
  150. } // namespace ra
  151. #undef CHECK_BOUNDS