bootstrap.hh 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. // -*- mode: c++; coding: utf-8 -*-
  2. /// @file bootstrap.hh
  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/tuples.hh"
  12. namespace ra {
  13. constexpr int VERSION = 12; // to force or prevent upgrades on dependents
  14. static_assert(sizeof(int)>=4, "bad assumption on int");
  15. using rank_t = int;
  16. using dim_t = ssize_t;
  17. constexpr dim_t DIM_ANY = -1099999444;
  18. constexpr dim_t DIM_BAD = -1099999888;
  19. constexpr rank_t RANK_ANY = -1099999444;
  20. constexpr rank_t RANK_BAD = -1099999888;
  21. static_assert(std::is_signed_v<rank_t> && std::is_signed_v<dim_t>, "bad dim types");
  22. constexpr dim_t dim_prod(dim_t const a, dim_t const b)
  23. {
  24. return (a==DIM_ANY) ? DIM_ANY : ((b==DIM_ANY) ? DIM_ANY : a*b);
  25. }
  26. constexpr rank_t rank_sum(rank_t const a, rank_t const b)
  27. {
  28. return (a==RANK_ANY) ? RANK_ANY : ((b==RANK_ANY) ? RANK_ANY : a+b);
  29. }
  30. constexpr rank_t rank_diff(rank_t const a, rank_t const b)
  31. {
  32. return (a==RANK_ANY) ? RANK_ANY : ((b==RANK_ANY) ? RANK_ANY : a-b);
  33. }
  34. constexpr bool inside(dim_t const i, dim_t const b)
  35. {
  36. return i>=0 && i<b;
  37. }
  38. constexpr bool inside(dim_t const i, dim_t const a, dim_t const b)
  39. {
  40. return i>=a && i<b;
  41. }
  42. // ---------------------
  43. // concepts (WIP)
  44. // ---------------------
  45. template <class P, class S>
  46. concept RaFlat = requires (P p, S d)
  47. {
  48. { *p };
  49. { p += d };
  50. };
  51. template <class A>
  52. concept RaIterator = requires (A a, rank_t k, dim_t d, rank_t i, rank_t j)
  53. {
  54. { a.rank() } -> std::convertible_to<rank_t>;
  55. { a.size(k) } -> std::same_as<dim_t>;
  56. { a.adv(k, d) } -> std::same_as<void>;
  57. { a.stride(k) };
  58. { a.keep_stride(d, i, j) } -> std::same_as<bool>;
  59. { a.flat() } -> RaFlat<decltype(a.stride(k))>;
  60. };
  61. template <class A>
  62. concept RaView = requires (A a, rank_t i)
  63. {
  64. { a.rank() } -> std::convertible_to<rank_t>;
  65. { a.size(i) } -> std::same_as<dim_t>;
  66. { a.stride(i) } -> std::same_as<dim_t>;
  67. { a.data() } -> std::random_access_iterator;
  68. };
  69. // ---------------------
  70. // other types, forward decl
  71. // ---------------------
  72. enum none_t { none }; // used in array constructors to mean ‘don't initalize’.
  73. struct no_arg {}; // used in array constructors to mean ‘don't instantiate’
  74. // Order of decl issues.
  75. template <class C> struct Scalar; // for type predicates
  76. template <std::random_access_iterator P, rank_t RANK=RANK_ANY> struct View; // for cell_iterator. // FIXME [ra27]
  77. template <class V> struct ra_traits_def;
  78. template <class S> struct default_strides_ {};
  79. template <class tend> struct default_strides_<std::tuple<tend>> { using type = mp::int_list<1>; };
  80. template <> struct default_strides_<std::tuple<>> { using type = mp::int_list<>; };
  81. template <class t0, class t1, class ... ti>
  82. struct default_strides_<std::tuple<t0, t1, ti ...>>
  83. {
  84. using rest = typename default_strides_<std::tuple<t1, ti ...>>::type;
  85. static int const stride0 = t1::value * mp::first<rest>::value;
  86. using type = mp::cons<mp::int_t<stride0>, rest>;
  87. };
  88. template <class S> using default_strides = typename default_strides_<S>::type;
  89. template <int n> struct dots_t
  90. {
  91. static_assert(n>=0);
  92. constexpr static rank_t rank_s() { return n; }
  93. };
  94. template <int n> constexpr dots_t<n> dots = dots_t<n>();
  95. constexpr auto all = dots<1>;
  96. template <int n> struct insert_t
  97. {
  98. static_assert(n>=0);
  99. constexpr static rank_t rank_s() { return n; }
  100. };
  101. template <int n=1> constexpr insert_t<n> insert = insert_t<n>();
  102. // Used by cell_iterator / cell_iterator_small.
  103. template <class C>
  104. struct CellFlat
  105. {
  106. C c;
  107. constexpr void operator+=(dim_t const s) { c.p += s; }
  108. constexpr C & operator*() { return c; }
  109. };
  110. // Common to View / SmallBase.
  111. template <int cell_rank, class A> inline constexpr auto
  112. iter(A && a) { return std::forward<A>(a).template iter<cell_rank>(); }
  113. // Defined in wrank.hh but used in big.hh (selectors, etc).
  114. template <class A, class ... I> inline constexpr auto from(A && a, I && ... i);
  115. // Extended by operators.hh and repeated in global.hh.
  116. // TODO All users be int, then this take int.
  117. inline constexpr bool any(bool const x) { return x; }
  118. inline constexpr bool every(bool const x) { return x; }
  119. inline constexpr bool odd(unsigned int N) { return N & 1; }
  120. // This logically belongs in ra/small.hh, but it's here so that we can return ra:: types from shape().
  121. // ---------------------
  122. // nested braces for Small initializers
  123. // ---------------------
  124. // The general SmallArray has 4 constructors,
  125. // 1. The empty constructor.
  126. // 2. The scalar constructor. This is needed when T isn't registered as ra::scalar, which isn't required purely for container use.
  127. // 3. The ravel constructor.
  128. // 4. The nested constructor.
  129. // 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.
  130. template <class T, class sizes>
  131. struct nested_tuple;
  132. // ambiguity with empty constructor and scalar constructor.
  133. // if size(0) is 0, then prefer the empty constructor.
  134. // if size(0) is 1...
  135. template <class sizes> constexpr bool no_nested = (mp::first<sizes>::value<1);
  136. template <> constexpr bool no_nested<mp::nil> = true;
  137. template <> constexpr bool no_nested<mp::int_list<1>> = true;
  138. template <class T, class sizes>
  139. using nested_arg = std::conditional_t<no_nested<sizes>,
  140. std::tuple<no_arg>, // match the template for SmallArray.
  141. typename nested_tuple<T, sizes>::list>;
  142. // ambiguity with scalar constructors (for rank 0) and nested_tuple (for rank 1).
  143. template <class sizes> constexpr bool no_ravel = ((mp::len<sizes> <=1) || (mp::apply<mp::prod, sizes>::value <= 1));
  144. template <class T, class sizes>
  145. using ravel_arg = std::conditional_t<no_ravel<sizes>,
  146. std::tuple<no_arg, no_arg>, // match the template for SmallArray.
  147. mp::makelist<mp::apply<mp::prod, sizes>::value, T>>;
  148. template <class T, class sizes, class strides = default_strides<sizes>> struct SmallView; // for cell_iterator_small
  149. template <class T, class sizes, class strides = default_strides<sizes>,
  150. class nested_arg_ = nested_arg<T, sizes>, class ravel_arg_ = ravel_arg<T, sizes>>
  151. struct SmallArray;
  152. template <class T, dim_t ... sizes> using Small = SmallArray<T, mp::int_list<sizes ...>>;
  153. template <class T>
  154. struct nested_tuple<T, mp::nil>
  155. {
  156. using sub = no_arg;
  157. using list = std::tuple<no_arg>; // match the template for SmallArray.
  158. };
  159. template <class T, int S0>
  160. struct nested_tuple<T, mp::int_list<S0>>
  161. {
  162. using sub = T;
  163. using list = mp::makelist<S0, T>;
  164. };
  165. template <class T, int S0, int S1, int ... S>
  166. struct nested_tuple<T, mp::int_list<S0, S1, S ...>>
  167. {
  168. using sub = Small<T, S1, S ...>;
  169. using list = mp::makelist<S0, sub>;
  170. };
  171. } // namespace ra