type.hh 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // -*- mode: c++; coding: utf-8 -*-
  2. /// @file type.hh
  3. /// @brief Type predicates.
  4. // (c) Daniel Llorens - 2013-2017, 2020
  5. // This library is free software; you can redistribute it and/or modify it under
  6. // the terms of the GNU Lesser 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 <cstdint>
  11. #include <vector>
  12. #include <array>
  13. #include <algorithm>
  14. #include <iterator>
  15. #include "ra/bootstrap.hh"
  16. namespace ra {
  17. // --------------
  18. // foreign types we care about. Specialize _def for more.
  19. // --------------
  20. RA_IS_DEF(is_scalar, (!std::is_pointer_v<A> && std::is_scalar_v<A>))
  21. template <> constexpr bool is_scalar_def<std::strong_ordering> = true;
  22. template <> constexpr bool is_scalar_def<std::weak_ordering> = true;
  23. template <> constexpr bool is_scalar_def<std::partial_ordering> = true;
  24. RA_IS_DEF(is_foreign_vector, false)
  25. template <class T, class A> constexpr bool is_foreign_vector_def<std::vector<T, A>> = true;
  26. template <class T, std::size_t N> constexpr bool is_foreign_vector_def<std::array<T, N>> = true;
  27. template <class A> constexpr bool is_builtin_array = std::is_array_v<std::remove_cv_t<std::remove_reference_t<A>>>;
  28. // --------------
  29. // ra_traits are intended mostly for foreign types. FIXME Not sure this is the interface I want.
  30. // --------------
  31. template <class A> using ra_traits = ra_traits_def<std::remove_cv_t<std::remove_reference_t<A>>>;
  32. template <class T, class A>
  33. struct ra_traits_def<std::vector<T, A>>
  34. {
  35. using V = std::vector<T, A>;
  36. constexpr static auto shape(V const & v) { return std::array<dim_t, 1> { dim_t(v.size()) }; }
  37. constexpr static dim_t size(V const & v) { return v.size(); }
  38. constexpr static dim_t size_s() { return DIM_ANY; }
  39. constexpr static rank_t rank(V const & v) { return 1; }
  40. constexpr static rank_t rank_s() { return 1; }
  41. };
  42. template <class T, std::size_t N>
  43. struct ra_traits_def<std::array<T, N>>
  44. {
  45. using V = std::array<T, N>;
  46. constexpr static auto shape(V const & v) { return std::array<dim_t, 1> { N }; }
  47. constexpr static dim_t size(V const & v) { return v.size(); }
  48. constexpr static dim_t size_s() { return N; }
  49. constexpr static rank_t rank(V const & v) { return 1; }
  50. constexpr static rank_t rank_s() { return 1; };
  51. };
  52. template <class T>
  53. struct ra_traits_def<std::initializer_list<T>>
  54. {
  55. using V = std::initializer_list<T>;
  56. constexpr static auto shape(V const & v) { return std::array<dim_t, 1> { dim_t(v.size()) }; }
  57. constexpr static dim_t size(V const & v) { return v.size(); }
  58. constexpr static rank_t rank(V const & v) { return 1; }
  59. constexpr static rank_t rank_s() { return 1; }
  60. constexpr static dim_t size_s() { return DIM_ANY; }
  61. };
  62. template <class T>
  63. requires (is_scalar<T>)
  64. struct ra_traits_def<T>
  65. {
  66. using V = T;
  67. constexpr static std::array<dim_t, 0> shape(V const & v) { return std::array<dim_t, 0> {}; }
  68. constexpr static dim_t size(V const & v) { return 1; }
  69. constexpr static dim_t size_s() { return 1; }
  70. constexpr static rank_t rank(V const & v) { return 0; }
  71. constexpr static rank_t rank_s() { return 0; }
  72. };
  73. // --------------
  74. // type classification
  75. // --------------
  76. // TODO make things is_iterator explicitly, as with is_scalar, and not by poking in the insides.
  77. // TODO check the rest of the required interface of A and A::flat() right here. Concepts...
  78. RA_IS_DEF(is_iterator, (requires { std::declval<A>().flat(); }))
  79. RA_IS_DEF(is_iterator_pos_rank, is_iterator<A> && A::rank_s()!=0)
  80. RA_IS_DEF(is_slice, (requires { std::declval<A>().iter(); } && requires { ra_traits<A>::size; })) // require ::size to reject public-derived from A
  81. RA_IS_DEF(is_slice_pos_rank, is_slice<A> && A::rank_s()!=0)
  82. template <class A> constexpr bool is_ra = is_iterator<A> || is_slice<A>;
  83. template <class A> constexpr bool is_ra_pos_rank = is_iterator_pos_rank<A> || is_slice_pos_rank<A>; // internal only FIXME
  84. template <class A> constexpr bool is_ra_zero_rank = is_ra<A> && !is_ra_pos_rank<A>;
  85. template <class A> constexpr bool is_zero_or_scalar = is_ra_zero_rank<A> || is_scalar<A>;
  86. template <class ... A> constexpr bool ra_pos_and_any = (is_ra_pos_rank<A> || ...) && ((is_ra<A> || is_scalar<A> || is_foreign_vector<A> || is_builtin_array<A>) && ...);
  87. // all args have rank 0 (so immediate application), but at least one is ra:: (don't collide with the scalar version).
  88. template <class ... A> constexpr bool ra_zero = !(is_scalar<A> && ...) && (is_zero_or_scalar<A> && ...);
  89. } // namespace ra