123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- // -*- mode: c++; coding: utf-8 -*-
- /// @file frame-new.C
- /// @brief Test abilities of post v10 driverless frame matching Expr
- // (c) Daniel Llorens - 2019
- // This library is free software; you can redistribute it and/or modify it under
- // the terms of the GNU Lesser General Public License as published by the Free
- // Software Foundation; either version 3 of the License, or (at your option) any
- // later version.
- #include <iostream>
- #include <iterator>
- #include "ra/format.H"
- // -------------------------------------
- // bit from example/throw.C which FIXME should be easier. Maybe an option in ra/macros.H.
- struct ra_error: public std::exception
- {
- std::string s;
- template <class ... A> ra_error(A && ... a): s(ra::format(std::forward<A>(a) ...)) {}
- virtual char const * what() const throw ()
- {
- return s.c_str();
- }
- };
- #ifdef RA_ASSERT
- #error RA_ASSERT is already defined!
- #endif
- #define RA_ASSERT( cond, ... ) \
- { if (!( cond )) throw ra_error("ra:: assert [" STRINGIZE(cond) "]", __VA_ARGS__); }
- // -------------------------------------
- #include "ra/test.H"
- #include "ra/operators.H"
- #include "ra/io.H"
- using std::cout, std::endl, std::flush;
- template <int i> using TI = ra::TensorIndex<i, int>;
- template <int i> using UU = decltype(std::declval<ra::Unique<double, i>>().iter());
- using mp::int_t;
- int main()
- {
- TestRecorder tr(std::cout);
- tr.section("view");
- {
- ra::Big<int, 3> a({2, 3, 4}, (ra::_0+1)*100 + (ra::_1+1)*10 + (ra::_2+1));
- ra::Big<int, 4> b({2, 2, 3, 4}, (ra::_0+1)*1000 + (ra::_1+1)*100 + (ra::_2+1)*10 + (ra::_3+1));
- cout << a << endl;
- }
- tr.section("II");
- {
- std::tuple<int_t<6>, int_t<3>, int_t<-4>> x;
- constexpr int ma = mp::fold_tuple(-99, x, [](auto && k, auto && a) { return max(k, std::decay_t<decltype(a)>::value); });
- constexpr int mi = mp::fold_tuple(+99, x, [](auto && k, auto && a) { return min(k, std::decay_t<decltype(a)>::value); });
- constexpr int su = mp::fold_tuple(0, x, [](auto && k, auto && a) { return k + std::decay_t<decltype(a)>::value; });
- cout << ma << endl;
- cout << mi << endl;
- cout << su << endl;
- }
- tr.section("static size - like Expr");
- {
- ra::Small<int, 2, 3, 4> a = (ra::_0+1)*100 + (ra::_1+1)*10 + (ra::_2+1);
- ra::Small<int, 2, 3, 4, 5> b = (ra::_0+1)*1000 + (ra::_1+1)*100 + (ra::_2+1)*10 + (ra::_3+1);
- #define EXPR expr([](auto && a, auto && b) { return a+b; }, start(a), start(b))
- tr.test_eq(4, EXPR.rank());
- tr.test_eq(b.size(0), EXPR.size(0));
- tr.test_eq(b.size(1), EXPR.size(1));
- tr.test_eq(b.size(2), EXPR.size(2));
- tr.test_eq(b.size(3), EXPR.size(3));
- tr.test_eq(2*3*4*5, size(EXPR));
- static_assert(4==EXPR.rank_s());
- static_assert(b.size_s(0)==EXPR.size_s(0));
- static_assert(b.size_s(1)==EXPR.size_s(1));
- static_assert(b.size_s(2)==EXPR.size_s(2));
- static_assert(b.size_s(3)==EXPR.size_s(3));
- static_assert(2*3*4*5 == size_s(EXPR));
- #undef EXPR
- }
- // properly fails to compile, which we cannot check at present [ra42]
- // tr.section("check mismatches - static");
- // {
- // ra::Small<int, 2, 3, 4> a = (ra::_0+1)*100 + (ra::_1+1)*10 + (ra::_2+1);
- // ra::Small<int, 2, 4, 4, 5> b = (ra::_0+1)*1000 + (ra::_1+1)*100 + (ra::_2+1)*10 + (ra::_3+1);
- // #define EXPR expr([](auto && a, auto && b) { return a+b; }, start(a), start(b))
- // tr.test_eq(2*3*4*5, size_s(EXPR));
- // tr.test_eq(3, EXPR.size_s(1));
- // #undef EXPR
- // }
- tr.section("static rank, dynamic size - like Expr");
- {
- ra::Big<int, 3> a({2, 3, 4}, (ra::_0+1)*100 + (ra::_1+1)*10 + (ra::_2+1));
- ra::Big<int, 4> b({2, 3, 4, 5}, (ra::_0+1)*1000 + (ra::_1+1)*100 + (ra::_2+1)*10 + (ra::_3+1));
- #define EXPR expr([](auto && a, auto && b) { return a+b; }, start(a), start(b))
- tr.test_eq(4, EXPR.rank());
- tr.test_eq(b.size(0), EXPR.size(0));
- tr.test_eq(b.size(1), EXPR.size(1));
- tr.test_eq(b.size(2), EXPR.size(2));
- tr.test_eq(b.size(3), EXPR.size(3));
- tr.test_eq(2*3*4*5, size(EXPR));
- // these _s are all static, but cannot Big cannot be constexpr yet.
- // also decltype(EXPR) fails until p0315r3 (c++20).
- // so check at runtime instead.
- tr.test_eq(4, EXPR.rank_s());
- tr.test_eq(ra::DIM_ANY, EXPR.size_s(0));
- tr.test_eq(ra::DIM_ANY, EXPR.size_s(1));
- tr.test_eq(ra::DIM_ANY, EXPR.size_s(2));
- tr.test_eq(ra::DIM_ANY, EXPR.size_s(3));
- tr.test_eq(ra::DIM_ANY, size_s(EXPR));
- cout << EXPR << endl;
- #undef EXPR
- }
- tr.section("check mismatches - dynamic");
- {
- ra::Big<int, 3> a({2, 3, 4}, (ra::_0+1)*100 + (ra::_1+1)*10 + (ra::_2+1));
- ra::Big<int, 4> b({2, 4, 4, 5}, (ra::_0+1)*1000 + (ra::_1+1)*100 + (ra::_2+1)*10 + (ra::_3+1));
- #define EXPR expr([](auto && a, auto && b) { return a+b; }, start(a), start(b))
- int x = 0;
- try {
- tr.test_eq(ra::DIM_ANY, EXPR.size_s(1));
- x = 1;
- } catch (ra_error & e) {
- }
- tr.info("caught error").test_eq(0, x);
- #undef EXPR
- }
- tr.section("dynamic rank - Expr driver selection is broken in this case.");
- {
- ra::Big<int, 3> as({2, 3, 4}, (ra::_0+1)*100 + (ra::_1+1)*10 + (ra::_2+1));
- ra::Big<int> ad({2, 3, 4}, (ra::_0+1)*100 + (ra::_1+1)*10 + (ra::_2+1));
- ra::Big<int, 4> bs({2, 3, 4, 5}, (ra::_0+1)*1000 + (ra::_1+1)*100 + (ra::_2+1)*10 + (ra::_3+1));
- ra::Big<int> bd({2, 3, 4, 5}, (ra::_0+1)*1000 + (ra::_1+1)*100 + (ra::_2+1)*10 + (ra::_3+1));
- #define EXPR(a, b) expr([](auto && a, auto && b) { return a+b; }, start(a), start(b))
- auto test = [&tr](auto tag, auto && a, auto && b)
- {
- tr.section(tag);
- tr.test_eq(4, EXPR(a, b).rank());
- tr.info("0d").test_eq(b.size(0), EXPR(a, b).size(0));
- tr.test_eq(b.size(1), EXPR(a, b).size(1));
- tr.test_eq(b.size(2), EXPR(a, b).size(2));
- tr.test_eq(b.size(3), EXPR(a, b).size(3));
- tr.info("0-size()").test_eq(2*3*4*5, size(EXPR(a, b)));
- tr.test_eq(ra::RANK_ANY, EXPR(a, b).rank_s());
- tr.test_eq(ra::DIM_ANY, size_s(EXPR(a, b)));
- tr.test_eq(ra::DIM_ANY, EXPR(a, b).size_s(0));
- tr.test_eq(ra::DIM_ANY, EXPR(a, b).size_s(1));
- tr.test_eq(ra::DIM_ANY, EXPR(a, b).size_s(2));
- tr.test_eq(ra::DIM_ANY, EXPR(a, b).size_s(3));
- tr.info("0-size_s()").test_eq(ra::DIM_ANY, size_s(EXPR(a, b)));
- };
- test("sta-dyn", as, bd);
- test("dyn-sta", ad, bs);
- test("dyn-dyn", ad, bd);
- #undef EXPR
- }
- tr.section("cases with periodic axes - dynamic (broken with Expr)");
- {
- ra::Big<int, 3> a({2, 3, 4}, (ra::_0+1)*100 + (ra::_1+1)*10 + (ra::_2+1));
- auto b = a(ra::all, ra::insert<1>, ra::iota(4, 0, 0));
- #define EXPR(a, b) expr([](auto && a, auto && b) { return a+b; }, start(a), start(b))
- tr.test_eq(4, EXPR(a, b).rank());
- tr.test_eq(b.size(0), EXPR(a, b).size(0));
- tr.test_eq(a.size(1), EXPR(a, b).size(1));
- tr.test_eq(b.size(2), EXPR(a, b).size(2));
- tr.test_eq(b.size(3), EXPR(a, b).size(3));
- tr.test_eq(2*3*4*4, size(EXPR(a, b)));
- // these _s are all static, but cannot Big cannot be constexpr yet.
- // also decltype(EXPR(a, b)) fails until p0315r3 (c++20).
- // so check at runtime instead.
- tr.test_eq(4, EXPR(a, b).rank_s());
- tr.test_eq(ra::DIM_ANY, EXPR(a, b).size_s(0));
- tr.test_eq(ra::DIM_ANY, EXPR(a, b).size_s(1));
- tr.test_eq(ra::DIM_ANY, EXPR(a, b).size_s(2));
- tr.test_eq(ra::DIM_ANY, EXPR(a, b).size_s(3));
- tr.test_eq(ra::DIM_ANY, size_s(EXPR(a, b)));
- cout << EXPR(a, b) << endl;
- // value test.
- ra::Big<int, 4> c({2, 3, 4, 4}, 0);
- c(ra::all, 0) = a(ra::all, ra::iota(4, 0, 0));
- c(ra::all, 1) = a(ra::all, ra::iota(4, 0, 0));
- c(ra::all, 2) = a(ra::all, ra::iota(4, 0, 0));
- tr.test_eq((a+c), EXPR(a, b));
- // order doesn't affect prefix matching with Expr
- tr.test_eq((a+c), EXPR(b, a));
- #undef EXPR
- }
- tr.section("broadcasting - like outer product");
- {
- ra::Big<int, 2> a({4, 3}, 10*ra::_1+100*ra::_0);
- ra::Big<int, 1> b({5}, ra::_0);
- cout << ra::start(ra::shape(from([](auto && a, auto && b) { return a-b; }, a, b))) << endl;
- #define EXPR(a, b) expr([](auto && a, auto && b) { return a-b; }, start(a(ra::dots<2>, ra::insert<1>)), start(b(ra::insert<2>, ra::dots<1>)))
- tr.test_eq(3, EXPR(a, b).rank_s());
- tr.test_eq(ra::DIM_ANY, EXPR(a, b).size_s(0));
- tr.test_eq(ra::DIM_ANY, EXPR(a, b).size_s(1));
- tr.test_eq(ra::DIM_ANY, EXPR(a, b).size_s(2));
- tr.test_eq(3, EXPR(a, b).rank());
- tr.test_eq(4, EXPR(a, b).size(0));
- tr.test_eq(3, EXPR(a, b).size(1));
- tr.test_eq(5, EXPR(a, b).size(2));
- tr.test_eq(from([](auto && a, auto && b) { return a-b; }, a, b), EXPR(a, b));
- #undef EXPR
- }
- tr.section("Expr has operatorX=");
- {
- ra::Big<int, 2> a({4, 3}, 10*ra::_1+100*ra::_0);
- expr([](auto & a) -> decltype(auto) { return a; }, start(a)) += 1;
- tr.test_eq(10*ra::_1 + 100*ra::_0 + 1, a);
- }
- tr.section("Compat with old Expr, from ra-0.C");
- {
- int p[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
- int * pp = &p[0]; // force pointer decay in case we ever enforce p's shape
- ra::View<int> d(ra::pack<ra::Dim>(ra::Small<int, 3> {5, 1, 2}, ra::Small<int, 3> {1, 0, 5}), pp);
- #define EXPR expr([](auto && a, auto && b) { return a==b; }, ra::_0*1 + ra::_1*0 + ra::_2*5 + 1, start(d))
- tr.test(every(EXPR));
- auto x = EXPR;
- static_assert(ra::DIM_ANY==size_s(x));
- static_assert(ra::DIM_ANY==ra::size_s(x));
- tr.test_eq(10, size(EXPR));
- }
- tr.section("DIM_BAD on any size_s(k) means size_s() is DIM_BAD");
- {
- using order = std::tuple<mp::int_t<0>, mp::int_t<1> >;
- using T0 = ra::Expr<ra::times, std::tuple<ra::TensorIndex<0>, ra::Scalar<int>>, order>;
- ra::dim_t s0 = ra::size_s<T0>();
- using T1 = ra::Expr<ra::times, std::tuple<ra::TensorIndex<1>, ra::Scalar<int>>, order>;
- ra::dim_t s1 = ra::size_s<T1>();
- using T2 = ra::Expr<ra::times, std::tuple<ra::TensorIndex<2>, ra::Scalar<int>>, order>;
- ra::dim_t s2 = ra::size_s<T2>();
- tr.test_eq(ra::DIM_BAD, s0);
- tr.test_eq(ra::DIM_BAD, s1);
- tr.test_eq(ra::DIM_BAD, s2);
- }
- return tr.summary();
- }
|