opcheck.H 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // (c) Daniel Llorens - 2011-2013, 2015
  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 opcheck.H
  7. /// @brief Check array argument agreement and select driving argument.
  8. #pragma once
  9. #include "ra/tuple-list.H"
  10. #include "ra/bootstrap.H"
  11. namespace ra {
  12. // Pick arg of largest rank as driver. Var rank counts as Inf, because it might
  13. // be larger. (This might be wrong; proper pick should be done at run time.) For
  14. // equal rank, prefer static size, because sizes must match. When I can pick
  15. // either, pick always the first.
  16. // TODO Should check dimensions down to smallest rank, as old opcheck() (??)
  17. // |-------------+----------+----------+--------------------|
  18. // | ranks B \ A | RANK_BAD | RANK_ANY | fixed |
  19. // |-------------+----------+----------+--------------------|
  20. // | RANK_BAD | A | A | A |
  21. // |-------------+----------+----------+--------------------|
  22. // | RANK_ANY | B | A | B |
  23. // |-------------+----------+----------+--------------------|
  24. // | fixed | B | A | A>B or check sizes |
  25. // |-------------+----------+----------+--------------------|
  26. // |-------------+---------+---------+-------|
  27. // | sizes B \ A | DIM_BAD | DIM_ANY | fixed |
  28. // |-------------+---------+---------+-------|
  29. // | DIM_BAD | A | A | A |
  30. // |-------------+---------+---------+-------|
  31. // | DIM_ANY | B | A | A |
  32. // |-------------+---------+---------+-------|
  33. // | fixed | B | B | A>=B |
  34. // |-------------+---------+---------+-------|
  35. template <class A, class B>
  36. struct pick_driver
  37. {
  38. constexpr static int ra = A::rank_s();
  39. constexpr static int rb = B::rank_s();
  40. constexpr static int sa = A::size_s();
  41. constexpr static int sb = B::size_s();
  42. constexpr static bool value_ =
  43. // check by rank
  44. rb==RANK_BAD
  45. ? 1
  46. : rb==RANK_ANY
  47. ? ra==RANK_ANY
  48. : ra==RANK_BAD
  49. ? 0
  50. : ra==RANK_ANY
  51. ? 1
  52. : ra>rb
  53. ? 1
  54. : ra<rb
  55. ? 0
  56. // check by size
  57. : sb==DIM_BAD
  58. ? 1
  59. : sa==DIM_BAD
  60. ? 0
  61. : sb==DIM_ANY
  62. ? 1
  63. : (sa!=DIM_ANY && sa>=sb);
  64. constexpr static int value = value_ ? 0 : 1; // 0 if ra wins, else 1
  65. };
  66. constexpr bool gt_rank(rank_t ra, rank_t rb)
  67. {
  68. return rb==RANK_BAD
  69. ? 1
  70. : rb==RANK_ANY
  71. ? ra==RANK_ANY
  72. : ra==RANK_BAD
  73. ? 0
  74. : ra==RANK_ANY
  75. ? 1
  76. : ra>=rb;
  77. }
  78. template <class A, class B>
  79. struct max_i
  80. {
  81. constexpr static int value = gt_rank(A::value, B::value) ? 0 : 1; // 0 if ra wins, else 1
  82. };
  83. template <class ... P> using largest_rank = mp::IndexOf<pick_driver, std::tuple<P ...>>;
  84. template <class ... P> using largest_i = mp::IndexOf<max_i, std::tuple<P ...>>;
  85. template <class T> using largest_i_tuple = mp::IndexOf<max_i, T>;
  86. // TODO Allow infinite rank; need a special value of crank for that.
  87. inline constexpr rank_t dependent_cell_rank(rank_t rank, rank_t crank)
  88. {
  89. return crank>=0 ? crank // not dependent
  90. : rank==RANK_ANY ? RANK_ANY // defer
  91. : rank+crank;
  92. }
  93. inline constexpr rank_t dependent_frame_rank(rank_t rank, rank_t crank)
  94. {
  95. return rank==RANK_ANY ? RANK_ANY // defer
  96. : crank>=0 ? rank-crank // not dependent
  97. : -crank;
  98. }
  99. } // namespace ra