algorithm.hpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #ifndef SIMPLE_GEOM_ALGORITHM_HPP
  2. #define SIMPLE_GEOM_ALGORITHM_HPP
  3. #include "algorithm.h"
  4. #include <functional>
  5. #include "simple/support/function_utils.hpp"
  6. #include "simple/support/algorithm/utils.hpp"
  7. #include "bool_algebra.hpp"
  8. namespace simple::geom
  9. {
  10. template <typename Coordinate, size_t Dimensions, typename Order, typename Function, size_t LoopDimesntions>
  11. constexpr void loop_on
  12. (
  13. vector<Coordinate, Dimensions, Order>& index,
  14. const vector<Coordinate, Dimensions, Order>& lower,
  15. const vector<Coordinate, Dimensions, Order>& upper,
  16. const vector<Coordinate, Dimensions, Order>& step,
  17. Function&& callback
  18. )
  19. {
  20. if constexpr (LoopDimesntions == 0)
  21. support::invoke(std::forward<Function>(callback),index);
  22. else
  23. {
  24. constexpr size_t I = LoopDimesntions-1;
  25. for
  26. (
  27. index[I] = lower[I];
  28. index[I] < upper[I];
  29. index[I] += step[I]
  30. )
  31. {
  32. loop_on<Coordinate,Dimensions,Order,Function,I>
  33. (index, lower, upper, step,
  34. std::forward<Function>(callback));
  35. }
  36. }
  37. };
  38. template <typename Coordinate, size_t Dimensions, typename Order, typename Function>
  39. constexpr void loop
  40. (
  41. const vector<Coordinate, Dimensions, Order>& lower,
  42. const vector<Coordinate, Dimensions, Order>& upper,
  43. const vector<Coordinate, Dimensions, Order>& step,
  44. Function&& callback
  45. )
  46. {
  47. vector<Coordinate, Dimensions, Order> index{};
  48. loop_on(index, lower, upper, step,
  49. std::forward<Function>(callback));
  50. }
  51. template <typename Coordinate, size_t Dimensions, typename Order, typename Function>
  52. constexpr void loop
  53. (
  54. const vector<Coordinate, Dimensions, Order>& upper,
  55. Function&& callback
  56. )
  57. {
  58. using vector = vector<Coordinate, Dimensions, Order>;
  59. vector index{};
  60. loop_on(index, vector::zero(), upper, vector::one(),
  61. std::forward<Function>(callback));
  62. }
  63. template <typename Coordinate, size_t Dimensions, typename Order, typename Function, size_t LoopDimesntions>
  64. constexpr void loop_on
  65. (
  66. vector<Coordinate, Dimensions, Order>& index,
  67. const support::range<vector<Coordinate, Dimensions, Order>>& bounds,
  68. const vector<Coordinate, Dimensions, Order>& step,
  69. Function&& callback
  70. )
  71. {
  72. loop_on(index, bounds.lower(), bounds.upper(), step,
  73. std::forward<Function>(callback));
  74. }
  75. template <typename Coordinate, size_t Dimensions, typename Order, typename Function>
  76. constexpr void loop
  77. (
  78. const support::range<vector<Coordinate, Dimensions, Order>>& bounds,
  79. const vector<Coordinate, Dimensions, Order>& step,
  80. Function&& callback
  81. )
  82. {
  83. vector<Coordinate, Dimensions, Order> index{};
  84. loop_on(index, bounds, step,
  85. std::forward<Function>(callback));
  86. }
  87. template <typename Coordinate, size_t Dimensions, typename Order, typename Function>
  88. constexpr void loop
  89. (
  90. const support::range<vector<Coordinate, Dimensions, Order>>& bounds,
  91. Function&& callback
  92. )
  93. {
  94. using vector = vector<Coordinate, Dimensions, Order>;
  95. vector index{};
  96. loop_on(index, bounds, vector::one(),
  97. std::forward<Function>(callback));
  98. }
  99. template <typename Coordinate,
  100. size_t Rows, size_t Columns,
  101. typename RowOrder, typename ColumnOrder
  102. >
  103. constexpr auto gauss_jordan_elimination
  104. (
  105. vector<
  106. vector<Coordinate, Columns, ColumnOrder>,
  107. Rows, RowOrder
  108. > m
  109. )
  110. {
  111. constexpr size_t D = std::min(Rows, Columns);
  112. for( size_t i = 0; i < D; ++i)
  113. {
  114. // TODO: make pivoting optional
  115. auto pivot = std::max_element(m.begin()+i, m.end(), [&i](auto a, auto b)
  116. {
  117. using support::abs;
  118. return abs(a[i]) < abs(b[i]);
  119. });
  120. support::swap(*pivot, m[i]);
  121. m[i] /= +m[i][i]; // ouch, easy to shoot foot here (+ makes a copy, otherwise disaster)
  122. for(size_t j = i+1; j < D; ++j)
  123. m[j] -= m[i] * m[j][i];
  124. for(size_t j = i; j --> 0;)
  125. m[j] -= m[i] * m[j][i];
  126. }
  127. return m;
  128. }
  129. template <typename Transform, typename Vector, typename AnotherCoord, typename Result>
  130. [[nodiscard]] constexpr Result
  131. deeply_transformed(const Vector& vector, Transform&& transform)
  132. {
  133. Result result{};
  134. loop(Vector::meta::template dimensions<>, [&](auto i)
  135. {
  136. result[i] = support::invoke(
  137. std::forward<Transform>(transform),
  138. vector[i]
  139. );
  140. });
  141. return result;
  142. }
  143. } // namespace simple::geom
  144. #endif /* end of include guard */