concrete.H 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. // (c) Daniel Llorens - 2017
  2. // This library is free software; you can redistribute it and/or modify it under
  3. // the terms of the GNU Lesser General Public License as published by the Free
  4. // Software Foundation; either version 3 of the License, or (at your option) any
  5. // later version.
  6. /// @file concrete.H
  7. /// @brief Obtain concrete type from array expression.
  8. #pragma once
  9. #include "ra/big.H"
  10. #ifdef RA_CHECK_BOUNDS
  11. #define RA_CHECK_BOUNDS_RA_CONCRETE RA_CHECK_BOUNDS
  12. #else
  13. #ifndef RA_CHECK_BOUNDS_RA_CONCRETE
  14. #define RA_CHECK_BOUNDS_RA_CONCRETE 1
  15. #endif
  16. #endif
  17. #if RA_CHECK_BOUNDS_RA_CONCRETE==0
  18. #define CHECK_BOUNDS( cond )
  19. #else
  20. #define CHECK_BOUNDS( cond ) assert( cond )
  21. #endif
  22. namespace ra {
  23. template <class E, class Enable=void> struct concrete_type_def_1;
  24. template <class E> struct concrete_type_def_1<E, std::enable_if_t<E::rank_s()==RANK_ANY>>
  25. {
  26. using type = Big<value_t<E>>;
  27. };
  28. template <class E> struct concrete_type_def_1<E, std::enable_if_t<E::size_s()==DIM_ANY && E::rank_s()!=RANK_ANY>>
  29. {
  30. using type = Big<value_t<E>, E::rank_s()>;
  31. };
  32. template <class E> struct concrete_type_def_1<E, std::enable_if_t<E::size_s()!=DIM_ANY>>
  33. {
  34. template <int N, class I=std::make_integer_sequence<int, N>> struct T;
  35. template <int N, int ... I> struct T<N, std::integer_sequence<int, I ...>>
  36. {
  37. using type = Small<value_t<E>, E::size_s(I) ...>;
  38. };
  39. using type = typename T<E::rank_s()>::type;
  40. };
  41. // scalars are their own concrete_type.
  42. template <class E, class Enable=void> struct concrete_type_def;
  43. template <class E> struct concrete_type_def<E, std::enable_if_t<!is_scalar<E>>>
  44. {
  45. using type = typename concrete_type_def_1<decltype(start(std::declval<E>()))>::type;
  46. };
  47. template <class E> struct concrete_type_def<E, std::enable_if_t<is_scalar<E>>>
  48. {
  49. using type = std::decay_t<E>;
  50. };
  51. template <class E> using concrete_type = typename concrete_type_def<E>::type;
  52. template <class E> inline auto concrete(E && e) { return concrete_type<E>(std::forward<E>(e)); }
  53. // FIXME replace ra_traits::make
  54. template <class E, class X> inline auto
  55. with_same_shape(E && e, X && x) -> std::enable_if_t<is_scalar<concrete_type<E>>, concrete_type<E>>
  56. { return concrete_type<E>(std::forward<X>(x)); }
  57. template <class E, class X> inline auto
  58. with_same_shape(E && e, X && x) -> std::enable_if_t<concrete_type<E>::size_s()!=DIM_ANY, concrete_type<E>>
  59. { return concrete_type<E>(std::forward<X>(x)); }
  60. template <class E, class X> inline auto
  61. with_same_shape(E && e, X && x) -> std::enable_if_t<concrete_type<E>::size_s()==DIM_ANY, concrete_type<E>>
  62. { return concrete_type<E>(ra::start(e).shape(), std::forward<X>(x)); }
  63. template <class E> inline auto
  64. with_same_shape(E && e) -> std::enable_if_t<is_scalar<concrete_type<E>>, concrete_type<E>>
  65. { return concrete_type<E>(); }
  66. template <class E> inline auto
  67. with_same_shape(E && e) -> std::enable_if_t<concrete_type<E>::size_s()!=DIM_ANY, concrete_type<E>>
  68. { return concrete_type<E>(); }
  69. template <class E> inline auto
  70. with_same_shape(E && e) -> std::enable_if_t<concrete_type<E>::size_s()==DIM_ANY, concrete_type<E>>
  71. { return concrete_type<E>(ra::start(e).shape(), ra::unspecified); }
  72. template <class E, class S, class X> inline auto
  73. with_shape(S && s, X && x) -> std::enable_if_t<concrete_type<E>::size_s()!=DIM_ANY, concrete_type<E>>
  74. { return concrete_type<E>(std::forward<X>(x)); }
  75. template <class E, class S, class X> inline auto
  76. with_shape(S && s, X && x) -> std::enable_if_t<concrete_type<E>::size_s()==DIM_ANY, concrete_type<E>>
  77. { return concrete_type<E>(std::forward<S>(s), std::forward<X>(x)); }
  78. template <class E, class S, class X> inline auto
  79. with_shape(std::initializer_list<S> && s, X && x) -> std::enable_if_t<concrete_type<E>::size_s()!=DIM_ANY, concrete_type<E>>
  80. { return concrete_type<E>(std::forward<X>(x)); }
  81. template <class E, class S, class X> inline auto
  82. with_shape(std::initializer_list<S> && s, X && x) -> std::enable_if_t<concrete_type<E>::size_s()==DIM_ANY, concrete_type<E>>
  83. { return concrete_type<E>(s, std::forward<X>(x)); }
  84. // template <class E>
  85. // struct ra_traits_def<E, std::enable_if_t<is_ra<E>>>: public ra_traits_def<concrete_type<E>> {};
  86. } // namespace ra
  87. #undef CHECK_BOUNDS
  88. #undef RA_CHECK_BOUNDS_RA_CONCRETE