19namespace sequoia::testing
21 template<
class T,
class U>
22 inline constexpr bool can_multiply{
23 requires(
const T& t,
const U& u) { t * u; }
26 template<
class T,
class U>
27 inline constexpr bool can_divide{
28 requires(
const T& t,
const U& u) { t / u; }
31 template<
class T,
class U>
32 inline constexpr bool can_add{
33 requires(
const T& t,
const U& u) { t + u; }
36 template<
class T,
class U>
37 inline constexpr bool can_subtract{
38 requires(
const T& t,
const U& u) { t - u; }
41 template<
class T,
class U>
42 inline constexpr bool addition_combinable{
43 requires(T& t,
const U& u) { { t += u } -> std::convertible_to<T>; }
46 template<
class T,
class U>
47 inline constexpr bool subtraction_combinable{
48 requires(T& t,
const U& u) { { t -= u } -> std::convertible_to<T>; }
52 inline constexpr bool has_unary_plus{
53 requires(
const T& t) { { +t } -> std::convertible_to<T>; }
57 inline constexpr bool has_unary_minus{
58 requires(
const T& t) { { -t } -> std::convertible_to<T>; }
64 template<std::
floating_po
int T>
71 using is_complex_t =
typename is_complex<T>::type;
74 inline constexpr bool is_orthonormal_basis_v{
76 typename B::orthonormal;
77 requires std::same_as<typename B::orthonormal, std::true_type>;
81 template<
class Set, maths::weak_field Field, std::
size_t D>
85 using field_type = Field;
86 using is_vector_space = std::true_type;
87 using admits_canonical_basis = std::true_type;
88 constexpr static std::size_t dimension{D};
90 template<maths::basis Basis>
91 requires std::floating_point<field_type>&& is_orthonormal_basis_v<Basis>
95 return std::ranges::fold_left(std::views::zip(lhs.values(), rhs.values()), field_type{}, [](field_type f,
const auto& z){ return f + std::get<0>(z) * std::get<1>(z); });
98 template<maths::basis Basis>
99 requires is_complex_v<field_type>&& is_orthonormal_basis_v<Basis>
103 return std::ranges::fold_left(std::views::zip(lhs.values(), rhs.values()), field_type{}, [](field_type f,
const auto& z){ return f + conj(std::get<0>(z)) * std::get<1>(z); });
107 template<
class Set, maths::weak_field Field, std::
size_t D>
110 using set_type = Set;
112 using is_affine_space = std::true_type;
115 template<
class Set, maths::weak_field Field, std::
size_t D>
119 using is_basis = std::true_type;
120 using orthonormal = std::true_type;
123 template<
class Set, maths::weak_commutative_ring Ring, std::
size_t D>
126 using set_type = Set;
127 using commutative_ring_type = Ring;
128 using is_free_module = std::true_type;
129 using admits_canonical_basis = std::true_type;
130 constexpr static std::size_t dimension{D};
133 template<
class Set, maths::weak_commutative_ring Ring, std::
size_t D>
136 using is_basis = std::true_type;
145 using commutative_ring_type =
typename coord_type::commutative_ring_type;
146 constexpr static std::size_t D{coord_type::dimension};
148 template<test_mode Mode>
151 check(equality,
"Wrapped values", logger, actual.values(), prediction.values());
154 check(equality,
"Wrapped value", logger, actual.value(), prediction.value());
155 if constexpr(std::convertible_to<commutative_ring_type, bool>)
156 check(equality,
"Conversion to bool", logger,
static_cast<bool>(actual),
static_cast<bool>(prediction));
159 for(
auto i : std::views::iota(0uz, D))
161 check(equality, std::format(
"Value at index {}", i), logger, actual[i], prediction[i]);
165 template<test_mode Mode>
168 check(equality,
"Wrapped values", logger, actual.values(), std::span<const commutative_ring_type, D>{prediction});
169 check(equivalence,
"Iterators", logger, std::ranges::subrange{actual.begin(), actual.end()}, prediction);
170 check(equivalence,
"c-Iterators", logger, std::ranges::subrange{actual.cbegin(), actual.cend()}, prediction);
171 check(equivalence,
"r-Iterators", logger, std::ranges::subrange{actual.rbegin(), actual.rend()}, prediction);
172 check(equivalence,
"cr-Iterators", logger, std::ranges::subrange{actual.crbegin(), actual.crend()}, prediction);
174 for(
auto i : std::views::iota(0uz, D))
176 check(equality,
"operator[]", logger, actual[i], prediction[i]);
185 template<
class Label>
186 requires std::convertible_to<Label, std::size_t>
188 std::weak_ordering to_ordering(Label From, Label To, inverted_ordering invert)
190 const bool inverted{invert == inverted_ordering::yes};
191 return (((From < To) && !inverted) || ((From > To) && inverted)) ? std::weak_ordering::less
192 : (((From > To) && !inverted) || ((From < To) && inverted)) ? std::weak_ordering::greater
193 : std::weak_ordering::equivalent;
196 template<maths::network Graph,
class Label,
class Fn>
197 requires std::convertible_to<Label, std::size_t>
198 void add_transition(Graph& g, Label From, Label To, std::string_view message, Fn f, std::weak_ordering ordering)
200 g.join(From, To, std::string{message}, f, ordering);
203 template<maths::network Graph,
class Label,
class Fn>
204 requires std::convertible_to<Label, std::size_t>
205 void add_transition(Graph& g, Label From, Label To, std::string_view message, Fn f)
207 g.join(From, To, std::string{message}, f);
210 template<
class Coords, maths::network Graph,
class Label,
class Fn>
211 requires std::is_invocable_r_v<Coords, Fn, Coords> && std::convertible_to<Label, std::size_t>
212 void add_transition(Graph& g, Label From, Label To, std::string_view message, Fn f, inverted_ordering invert={})
214 using ring_t = Coords::commutative_ring_type;
215 constexpr static auto dimension{Coords::dimension};
217 if constexpr((dimension == 1) && std::totally_ordered<ring_t>)
219 add_transition(g, From, To, message, f, to_ordering(From, To, invert));
223 add_transition(g, From, To, message, f);
227 template<
class Coordinates>
230 enum dim_1_label{ two, one, zero, neg_one };
231 enum dim_2_label{ neg_one_neg_one, neg_one_zero, zero_neg_one, zero_zero, zero_one, one_zero, one_one, one_two };
234 using coords_t = Coordinates;
235 using space_t = Coordinates::space_type;
236 using disp_t = coords_t::displacement_coordinates_type;
237 using module_t = coords_t::free_module_type;
238 using ring_t = coords_t::commutative_ring_type;
239 using units_t = coords_t::basis_isomorphism_type;
240 constexpr static std::size_t dimension{Coordinates::dimension};
241 constexpr static bool orderable{(dimension == 1) && std::totally_ordered<ring_t>};
249 , m_Graph{make_graph(m_Test)}
259 return do_make_graph(test);
265 if constexpr (dimension == 1)
return make_dim_1_transition_graph(test);
266 else if constexpr(dimension == 2)
return make_dim_2_transition_graph(test);
270 auto make_checker()
const
272 if constexpr(orderable)
275 [&test=m_Test](std::string_view description,
const coords_t& obtained,
const coords_t& prediction,
const coords_t& parent, std::weak_ordering ordering) {
276 test.check(equality, description, obtained, prediction);
277 if(ordering != std::weak_ordering::equivalent)
278 test.check_semantics(description, prediction, parent, ordering);
284 [&test=m_Test](std::string_view description,
const coords_t& obtained,
const coords_t& prediction,
const coords_t& parent, std::size_t host, std::size_t target) {
285 test.check(equality, description, obtained, prediction);
286 if(host!= target) test.check_semantics(description, prediction, parent);
291 static graph_type make_dim_1_transition_graph(
regular_test& test)
297 {coords_t{ring_t(2), units_t{}}, coords_t{ring_t(1), units_t{}}, coords_t{}}
300 add_dim_1_common_transitions(g, test);
302 if constexpr(has_unary_minus<Coordinates>)
304 add_dim_1_negative_transitions(g, test);
306 else if constexpr(maths::defines_half_line_validator_v<typename Coordinates::validator_type> && std::is_signed_v<ring_t>)
308 add_dim_1_attempted_negative_transitions(g, test);
313 add_dim_1_distinguished_origin_transitions(g, test);
316 if constexpr(Coordinates::has_freely_mutable_components)
318 add_dim_1_free_mutations(g, test);
321 if constexpr(std::constructible_from<coords_t, ring_t, ring_t>)
323 add_dim_1_no_unit_construction(g, test);
329 static graph_type make_dim_2_transition_graph(
regular_test& test)
331 using edge_t = transition_checker<coords_t>::edge;
335 edge_t{dim_2_label::neg_one_neg_one, test.report(
"+ (-1, -1)"), [](coords_t v) -> coords_t {
return +v; }},
336 edge_t{dim_2_label::neg_one_zero, test.report(
"(-1, -1) + (0, 1)"), [&](coords_t v) -> coords_t {
return v + disp_t{std::array{ring_t{}, ring_t(1)}, units_t{}}; }},
337 edge_t{dim_2_label::neg_one_zero, test.report(
"(-1, -1) += (0, 1)"), [&](coords_t v) -> coords_t {
return v += disp_t{std::array{ring_t{}, ring_t(1)}, units_t{}}; }},
338 edge_t{dim_2_label::zero_neg_one, test.report(
"(-1, -1) + (1, 0)"), [&](coords_t v) -> coords_t {
return v + disp_t{std::array{ring_t(1), ring_t{}}, units_t{}}; }},
339 edge_t{dim_2_label::zero_neg_one, test.report(
"(-1, -1) += (1, 0)"), [&](coords_t v) -> coords_t {
return v += disp_t{std::array{ring_t(1), ring_t{}}, units_t{}}; }}
342 edge_t{dim_2_label::neg_one_neg_one, test.report(
"(-1, 0) - (0, 1)"), [&](coords_t v) -> coords_t {
return v - disp_t{std::array{ring_t{}, ring_t(1)}, units_t{}}; }},
343 edge_t{dim_2_label::neg_one_neg_one, test.report(
"(-1, 0) -= (0, 1)"), [&](coords_t v) -> coords_t {
return v -= disp_t{std::array{ring_t{}, ring_t(1)}, units_t{}}; }}
346 edge_t{dim_2_label::neg_one_neg_one, test.report(
"(0, -1) - (1, 0)"), [&](coords_t v) -> coords_t {
return v - disp_t{std::array{ring_t{1}, ring_t(0)}, units_t{}}; }},
347 edge_t{dim_2_label::neg_one_neg_one, test.report(
"(0, -1) -= (1, 0)"), [&](coords_t v) -> coords_t {
return v -= disp_t{std::array{ring_t{1}, ring_t(0)}, units_t{}}; }}
360 {coords_t{std::array{ring_t(-1), ring_t(-1)}, units_t{}},
361 coords_t{std::array{ring_t(-1), ring_t{}}, units_t{}},
362 coords_t{std::array{ring_t{}, ring_t(-1)}, units_t{}},
363 coords_t{std::array{ring_t{}, ring_t{}}, units_t{}},
364 coords_t{std::array{ring_t{}, ring_t(1)}, units_t{}},
365 coords_t{std::array{ring_t(1), ring_t{}}, units_t{}},
366 coords_t{std::array{ring_t(1), ring_t(1)}, units_t{}},
367 coords_t{std::array{ring_t(1), ring_t(2)}, units_t{}}
373 add_dim_2_distinguished_origin_transitions(g, test);
376 if constexpr(Coordinates::has_freely_mutable_components)
378 add_dim_2_free_mutations(g, test);
381 if constexpr(std::constructible_from<coords_t, ring_t, ring_t>)
383 add_dim_2_no_unit_construction(g, test);
392 add_transition<coords_t>(
396 test.report(
"(0) + (1)"),
397 [&](coords_t p) -> coords_t { return p + disp_t{ring_t(1), units_t{}}; }
400 add_transition<coords_t>(
404 test.report(
"(0) += (1)"),
405 [&](coords_t p) -> coords_t { return p += disp_t{ring_t(1), units_t{}}; }
410 add_transition<coords_t>(
414 test.report(
"(1) - (1)"),
415 [&](coords_t p) -> coords_t { return p - disp_t{ring_t(1), units_t{}}; }
418 add_transition<coords_t>(
422 test.report(
"(1) -= (1)"),
423 [&](coords_t p) -> coords_t { return p -= disp_t{ring_t(1), units_t{}}; }
426 add_transition<coords_t>(
431 [](coords_t p) -> coords_t { return +p;}
434 add_transition<coords_t>(
438 test.report(
"(1) + (1)"),
439 [&](coords_t p) -> coords_t { return p + disp_t{ring_t(1), units_t{}}; }
442 add_transition<coords_t>(
446 test.report(
"(1) += (1)"),
447 [&](coords_t p) -> coords_t { return p += disp_t{ring_t(1), units_t{}}; }
452 add_transition<coords_t>(
456 test.report(
"(2) - (1)"),
457 [&](coords_t p) -> coords_t { return p - disp_t{ring_t(1), units_t{}}; }
461 template<
class... Units>
462 static void add_dim_1_negative_transitions(maths::network
auto& g, regular_test& test)
464 g.add_node(ring_t(-1), units_t{});
467 if constexpr(coords_t::has_distinguished_origin && !std::is_unsigned_v<ring_t>)
469 add_transition<coords_t>(
472 dim_1_label::neg_one,
474 [](coords_t p) -> coords_t { return -p; },
475 std::is_unsigned_v<ring_t> ? inverted_ordering::yes : inverted_ordering::no
479 add_transition<coords_t>(
482 dim_1_label::neg_one,
483 test.report(
"(1) - (2)"),
484 [&](coords_t p) -> coords_t { return p - disp_t{ring_t(2), units_t{}}; },
485 std::is_unsigned_v<ring_t> ? inverted_ordering::yes : inverted_ordering::no
490 if constexpr(coords_t::has_distinguished_origin && !std::is_unsigned_v<ring_t>)
492 add_transition<coords_t>(
494 dim_1_label::neg_one,
496 test.report(
"- (-1)"),
497 [](coords_t p) -> coords_t { return -p; },
498 std::is_unsigned_v<ring_t> ? inverted_ordering::yes : inverted_ordering::no
502 add_transition<coords_t>(
504 dim_1_label::neg_one,
505 dim_1_label::neg_one,
506 test.report(
"+ (-1)"),
507 [](coords_t p) -> coords_t { return +p; }
510 if constexpr(Coordinates::has_freely_mutable_components)
512 add_transition<coords_t>(
514 dim_1_label::neg_one,
516 test.report(
"(-1) += 1"),
517 [](coords_t p) -> coords_t { auto& v{p.value()}; v += 1;
return p; },
518 std::is_unsigned_v<ring_t> ? inverted_ordering::yes : inverted_ordering::no
521 add_transition<coords_t>(
523 dim_1_label::neg_one,
525 test.report(
"(-1) + 1"),
526 [](coords_t p) -> coords_t { auto& v{p.value()}; v += 1;
return p; },
527 std::is_unsigned_v<ring_t> ? inverted_ordering::yes : inverted_ordering::no
532 static void add_dim_1_attempted_negative_transitions(maths::network
auto& g, regular_test& test)
534 add_transition<coords_t>(
538 test.report(
"(1) -= (2)"),
539 [&](coords_t p) -> coords_t {
540 test.check_exception_thrown<std::domain_error>(
"", [&](){ return p -= disp_t{ring_t(2), units_t{}};});
545 add_transition<coords_t>(
549 test.report(
"(1) - (2)"),
550 [&](coords_t p) -> coords_t {
551 test.check_exception_thrown<std::domain_error>(
"", [&](){ return p = (p - disp_t{ring_t(2), units_t{}}); });
556 if constexpr(has_distinguished_origin)
558 add_transition<coords_t>(
562 test.report(
"(1) *= ring_t{-1}"),
563 [&](coords_t v) -> coords_t {
564 test.check_exception_thrown<std::domain_error>(
"", [&v](){ return v *= ring_t{-1}; });
569 add_transition<coords_t>(
573 test.report(
"ring_t{-1} * (1)"),
574 [&test](coords_t v) -> coords_t {
575 test.check_exception_thrown<std::domain_error>(
"", [&v](){ return v = ring_t{-1} * v; });
580 add_transition<coords_t>(
584 test.report(
"(1) /= ring_t{-1}"),
585 [&test](coords_t v) -> coords_t {
586 test.check_exception_thrown<std::domain_error>(
"", [&v](){ return v /= ring_t{-1}; });
591 add_transition<coords_t>(
595 test.report(
"(1) / ring_t{-1}"),
596 [&test](coords_t v) -> coords_t {
597 test.check_exception_thrown<std::domain_error>(
"", [&v](){ return v = v / ring_t{-1}; });
604 static void add_dim_1_distinguished_origin_transitions(maths::network
auto& g, regular_test& test)
607 add_transition<coords_t>(
611 test.report(
"(1) * ring_t{}"),
612 [](coords_t v) -> coords_t { return v * ring_t{}; }
615 add_transition<coords_t>(
619 test.report(
"(1) * span{ring_t{}}"),
620 [](coords_t v) -> coords_t { return v * std::array{ring_t{}}; }
623 add_transition<coords_t>(
627 test.report(
"ring_t{} * (1)"),
628 [](coords_t v) -> coords_t { return ring_t{} * v; }
631 add_transition<coords_t>(
635 test.report(
"span{ring_t{}} * (1)"),
636 [](coords_t v) -> coords_t { return std::array{ring_t{}} * v; }
639 add_transition<coords_t>(
643 test.report(
"(1) *= ring_t{}"),
644 [](coords_t v) -> coords_t { return v *= ring_t{}; }
647 add_transition<coords_t>(
651 test.report(
"(1) *= span{ring_t{}}"),
652 [](coords_t v) -> coords_t { return v *= std::array{ring_t{}}; }
657 add_transition<coords_t>(
661 test.report(
"(1) * ring_t{2}"),
662 [](coords_t v) -> coords_t { return v * ring_t{2}; }
665 add_transition<coords_t>(
669 test.report(
"(1) * array{ring_t{2}}"),
670 [](coords_t v) -> coords_t { return v * std::array{ring_t{2}}; }
673 add_transition<coords_t>(
677 test.report(
"ring_t{2} * (1)"),
678 [](coords_t v) -> coords_t { return ring_t{2} * v; }
681 add_transition<coords_t>(
685 test.report(
"span{ring_t{2}} * (1)"),
686 [](coords_t v) -> coords_t { return std::array{ring_t{2}} * v; }
689 add_transition<coords_t>(
693 test.report(
"(1) *= ring_t{2}"),
694 [](coords_t v) -> coords_t { return v *= ring_t{2}; }
697 add_transition<coords_t>(
701 test.report(
"(1) *= span{ring_t{2}}"),
702 [](coords_t v) -> coords_t { return v *= std::array{ring_t{2}}; }
707 if constexpr(maths::vector_space<module_t>)
709 add_transition<coords_t>(
713 test.report(
"(2) / ring_t{2}"),
714 [](coords_t v) -> coords_t { return v / ring_t{2}; }
717 add_transition<coords_t>(
721 test.report(
"(2) / span{ring_t{2}}"),
722 [](coords_t v) -> coords_t { return v / std::array{ring_t{2}}; }
725 add_transition<coords_t>(
729 test.report(
"(2) /= ring_t{2}"),
730 [](coords_t v) -> coords_t { return v /= ring_t{2}; }
733 add_transition<coords_t>(
737 test.report(
"(2) /= span{ring_t{2}}"),
738 [](coords_t v) -> coords_t { return v /= std::array{ring_t{2}}; }
743 static void add_dim_1_free_mutations(maths::network
auto& g, regular_test& test)
746 add_transition<coords_t>(
750 test.report(
"(1)[0] * ring_t{}"),
751 [](coords_t v) -> coords_t { v[0] *= ring_t{};
return v; }
754 add_transition<coords_t>(
758 test.report(
"(1).begin[0] * ring_t{}"),
759 [](coords_t v) -> coords_t { v.begin()[0] *= ring_t{};
return v; }
762 add_transition<coords_t>(
766 test.report(
"(1).rbegin[0] * ring_t{}"),
767 [](coords_t v) -> coords_t { v.rbegin()[0] *= ring_t{};
return v; }
772 add_transition<coords_t>(
776 test.report(
"(1)[0] * ring_t{2}"),
777 [](coords_t v) -> coords_t { v[0] *= ring_t{2};
return v; }
780 add_transition<coords_t>(
784 test.report(
"(1).begin[0] * ring_t{2}"),
785 [](coords_t v) -> coords_t { v.begin()[0] *= ring_t{2};
return v; }
788 add_transition<coords_t>(
792 test.report(
"(1).rbegin[0] * ring_t{2}"),
793 [](coords_t v) -> coords_t { v.rbegin()[0] *= ring_t{2};
return v; }
797 static void add_dim_1_no_unit_construction(maths::network
auto& g, regular_test& test)
800 add_transition<coords_t>(
804 test.report(
"(0) + (1)"),
805 [&](coords_t p) -> coords_t { return p + disp_t{ring_t(1)}; }
809 static void add_dim_2_distinguished_origin_transitions(maths::network
auto& g, regular_test& test)
813 add_transition<coords_t>(
815 dim_2_label::neg_one_neg_one,
816 dim_2_label::one_one,
817 test.report(
"- (-1, -1)"),
818 [](coords_t v) -> coords_t { return -v; }
821 add_transition<coords_t>(
823 dim_2_label::neg_one_neg_one,
824 dim_2_label::one_one,
825 test.report(
"(-1, -1) *= -1"),
826 [](coords_t v) -> coords_t { return v *= ring_t{-1}; }
829 add_transition<coords_t>(
831 dim_2_label::neg_one_neg_one,
832 dim_2_label::one_one,
833 test.report(
"(-1, -1) *= span{-1, -1}"),
834 [](coords_t v) -> coords_t { return v *= std::array<ring_t, 2>{-1, -1}; }
837 add_transition<coords_t>(
839 dim_2_label::neg_one_neg_one,
840 dim_2_label::one_one,
841 test.report(
"(-1, -1) * -1"),
842 [](coords_t v) -> coords_t { return v * ring_t{-1}; }
845 add_transition<coords_t>(
847 dim_2_label::neg_one_neg_one,
848 dim_2_label::one_one,
849 test.report(
"(-1, -1) * span{-1, -1}"),
850 [](coords_t v) -> coords_t { return v * std::array<ring_t, 2>{-1, -1}; }
853 if constexpr(maths::vector_space<module_t>)
855 add_transition<coords_t>(
857 dim_2_label::neg_one_neg_one,
858 dim_2_label::one_one,
859 test.report(
"(-1, -1) /= -1"),
860 [](coords_t v) -> coords_t { return v /= ring_t{-1}; }
863 add_transition<coords_t>(
865 dim_2_label::neg_one_neg_one,
866 dim_2_label::one_one,
867 test.report(
"(-1, -1) /= span{-1, -1}"),
868 [](coords_t v) -> coords_t { return v /= std::array<ring_t, 2>{-1, -1}; }
871 add_transition<coords_t>(
873 dim_2_label::neg_one_neg_one,
874 dim_2_label::one_one,
875 test.report(
"(-1, -1) / -1"),
876 [](coords_t v) -> coords_t { return v / ring_t{-1}; }
879 add_transition<coords_t>(
881 dim_2_label::neg_one_neg_one,
882 dim_2_label::one_one,
883 test.report(
"(-1, -1) / span{-1, -1}"),
884 [](coords_t v) -> coords_t { return v / std::array<ring_t, 2>{-1, -1}; }
889 add_transition<coords_t>(
891 dim_2_label::neg_one_neg_one,
892 dim_2_label::one_zero,
893 test.report(
"(-1, -1) *= span{-1, 0}"),
894 [](coords_t v) -> coords_t { return v *= std::array<ring_t, 2>{-1, 0}; }
898 if constexpr(maths::vector_space<module_t>)
900 add_transition<coords_t>(
902 dim_2_label::neg_one_neg_one,
903 dim_2_label::one_two,
904 test.report(
"(-1, -1) /= span{-1, -0.5}"),
905 [](coords_t v) -> coords_t { return v /= std::array<ring_t, 2>{-1, -0.5}; }
908 add_transition<coords_t>(
910 dim_2_label::neg_one_neg_one,
911 dim_2_label::one_two,
912 test.report(
"(-1, -1) / span{-1, -0.5}"),
913 [](coords_t v) -> coords_t { return v / std::array<ring_t, 2>{-1, -0.5}; }
918 static void add_dim_2_free_mutations(maths::network
auto& g, regular_test& test)
922 add_transition<coords_t>(
924 dim_2_label::neg_one_neg_one,
925 dim_2_label::neg_one_zero,
926 test.report(
"(-1, -1)[1] *= 0"),
927 [](coords_t v) -> coords_t { v[1] *= ring_t{};
return v; }
930 add_transition<coords_t>(
932 dim_2_label::neg_one_neg_one,
933 dim_2_label::neg_one_zero,
934 test.report(
"(-1, -1).begin()[1] *= 0"),
935 [](coords_t v) -> coords_t { v.begin()[1] *= ring_t{};
return v; }
938 add_transition<coords_t>(
940 dim_2_label::neg_one_neg_one,
941 dim_2_label::neg_one_zero,
942 test.report(
"(-1, -1).rbegin()[0] *= 0"),
943 [](coords_t v) -> coords_t { v.rbegin()[0] *= ring_t{};
return v; }
947 add_transition<coords_t>(
949 dim_2_label::zero_one,
950 dim_2_label::one_one,
951 test.report(
"(0, 1)[0] += 1"),
952 [](coords_t v) -> coords_t { v[0] += ring_t{1};
return v; }
955 add_transition<coords_t>(
957 dim_2_label::zero_one,
958 dim_2_label::one_one,
959 test.report(
"(0, 1).begin[0] += 1"),
960 [](coords_t v) -> coords_t { v.begin()[0] += ring_t{1};
return v; }
963 add_transition<coords_t>(
965 dim_2_label::zero_one,
966 dim_2_label::one_one,
967 test.report(
"(0, 1).rbegin[1] += 1"),
968 [](coords_t v) -> coords_t { v.rbegin()[1] += ring_t{1};
return v; }
972 static void add_dim_2_no_unit_construction(maths::network
auto& g, regular_test& test)
976 add_transition<coords_t>(
978 dim_2_label::neg_one_neg_one,
979 dim_2_label::neg_one_neg_one,
980 test.report(
"(-1, -1) without units"),
981 [](coords_t v) -> coords_t { return {v[0], v[1]}; }
984 add_transition<coords_t>(
986 dim_2_label::neg_one_neg_one,
987 dim_2_label::neg_one_neg_one,
988 test.report(
"(-1, -1) without units"),
989 [](coords_t v) -> coords_t { return coords_t{v.values()}; }
bool check(CheckType flavour, std::string description, test_logger< Mode > &logger, Iter first, Sentinel last, PredictionIter predictionFirst, PredictionSentinel predictionLast, tutor< Advisor > advisor={})
The workhorse for comparing the contents of ranges.
Definition: FreeCheckers.hpp:379
inverted_ordering
Definition: GeometryTestingUtilities.hpp:183
Utilities for checking regular semantics.
Abstractions pertaining to vector spaces, affine spaces and their generalizations.
Facility to define tests via a graph comprising states of an object and transitions between them.
Type to indicate a distinguished origin, relevant for free modules.
Definition: Spaces.hpp:1239
Definition: DynamicGraph.hpp:303
class template from which all concrete tests should derive.
Definition: FreeTestCore.hpp:144
Definition: GeometryTestingUtilities.hpp:229
Definition: TestLogger.hpp:183
A concept to determine if a basis is appropriate for a particular free module.
Definition: Spaces.hpp:692
A basis must identify the free module to which it corresponds.
Definition: Spaces.hpp:644
concept for convex spaces
Definition: Spaces.hpp:518
Definition: GraphTraits.hpp:18
Definition: Spaces.hpp:1162
Definition: GeometryTestingUtilities.hpp:117
Definition: GeometryTestingUtilities.hpp:135
Definition: FreeCheckers.hpp:82
Definition: FreeCheckers.hpp:87
Definition: GeometryTestingUtilities.hpp:62
Definition: GeometryTestingUtilities.hpp:109
Definition: GeometryTestingUtilities.hpp:125
Definition: GeometryTestingUtilities.hpp:83
Definition: StateTransitionUtilities.hpp:77
class template, specializations of which implement various comparisons for the specified type.
Definition: FreeCheckers.hpp:78