#define BOOST_YAP_CONVERSION_OPERATOR_TEMPLATE #include #include #include template using term = boost::yap::terminal; namespace yap = boost::yap; namespace bh = boost::hana; namespace user { struct number { double value; friend number operator+ (number lhs, number rhs) { return number{lhs.value + rhs.value}; } friend number operator* (number lhs, number rhs) { return number{lhs.value * rhs.value}; } }; number naxpy (number a, number x, number y) { return number{a.value * x.value + y.value + 10.0}; } #if 0 // TODO: Document this verbose form. auto eval_expression_as ( yap::expression< yap::expr_kind::plus, bh::tuple< yap::expression< yap::expr_kind::multiplies, bh::tuple< term, term >, >, term > > const & expr, boost::hana::basic_type) { using namespace boost::hana::literals; return naxpy( expr.elements[0_c].elements[0_c].elements[0_c], expr.elements[0_c].elements[1_c].elements[0_c], expr.elements[1_c].elements[0_c] ); } #endif decltype(auto) eval_expression_as ( decltype(term{{0.0}} * number{} + number{}) const & expr, boost::hana::basic_type) { return naxpy( expr.left().left().value(), expr.left().right().value(), expr.right().value() ); } decltype(auto) transform_expression ( decltype(term{{0.0}} * number{} + number{}) const & expr ) { return naxpy( evaluate(expr.left().left()), evaluate(expr.left().right()), evaluate(expr.right()) ); } } TEST(user_expression_transform, test_user_expression_transform) { term k{{2.0}}; term a{{1.0}}; term x{{42.0}}; term y{{3.0}}; { yap::expression< yap::expr_kind::plus, bh::tuple< yap::expression< yap::expr_kind::multiplies, bh::tuple< yap::expression< yap::expr_kind::multiplies, bh::tuple< term, term > >, term > >, term > > expr = term{{2.0}} * user::number{1.0} * user::number{42.0} + user::number{3.0}; user::number result = expr; EXPECT_EQ(result.value, 87); } { yap::expression< yap::expr_kind::plus, bh::tuple< yap::expression< yap::expr_kind::multiplies, bh::tuple< term, term > >, term > > expr = term{{1.0}} * user::number{42.0} + user::number{3.0}; user::number result = expr; EXPECT_EQ(result.value, 55); } { yap::expression< yap::expr_kind::multiplies, bh::tuple< term, yap::expression< yap::expr_kind::plus, bh::tuple< yap::expression< yap::expr_kind::multiplies, bh::tuple< term, term > >, term > > > > expr = term{{2.0}} * (term{{1.0}} * user::number{42.0} + user::number{3.0}); user::number result = expr; EXPECT_EQ(result.value, 110); } { auto expr = (term{{1.0}} * user::number{42.0} + user::number{3.0}) * (term{{1.0}} * user::number{42.0} + user::number{3.0}) + (term{{1.0}} * user::number{42.0} + user::number{3.0}); user::number result = expr; // Note: +10 not done at the top level naxpy opportunity. EXPECT_EQ(result.value, 55 * 55 + 55); } }