• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2016-2018 T. Zachary Laine
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See
4 // accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 #include <boost/yap/expression.hpp>
7 
8 
9 template<typename T>
10 using term = boost::yap::terminal<boost::yap::expression, T>;
11 
12 namespace yap = boost::yap;
13 namespace bh = boost::hana;
14 
15 
16 namespace user {
17 
18     struct number
19     {
20         double value;
21 
operator +(number lhs,number rhs)22         friend number operator+(number lhs, number rhs)
23         {
24             return number{lhs.value + rhs.value};
25         }
26 
operator *(number lhs,number rhs)27         friend number operator*(number lhs, number rhs)
28         {
29             return number{lhs.value * rhs.value};
30         }
31     };
32 
33     // A more efficient fused multiply-add operation would normally go here.
naxpy(number a,number x,number y)34     number naxpy(number a, number x, number y)
35     {
36         return number{a.value * x.value + y.value};
37     }
38 
39     // Transforms expressions of the form "a * x + y" to "naxpy(a, x, y)" via
40     // the implicit transform customiztion point.
41     template<typename Expr1, typename Expr2, typename Expr3>
transform_expression(yap::expression<yap::expr_kind::plus,bh::tuple<yap::expression<yap::expr_kind::multiplies,bh::tuple<Expr1,Expr2>>,Expr3>> const & expr)42     decltype(auto) transform_expression(yap::expression<
43                                         yap::expr_kind::plus,
44                                         bh::tuple<
45                                             yap::expression<
46                                                 yap::expr_kind::multiplies,
47                                                 bh::tuple<Expr1, Expr2>>,
48                                             Expr3>> const & expr)
49     {
50         return naxpy(
51             evaluate(expr.left().left()),
52             evaluate(expr.left().right()),
53             evaluate(expr.right()));
54     }
55 }
56 
57 term<user::number> a{{1.0}};
58 term<user::number> x{{42.0}};
59 term<user::number> y{{3.0}};
60 
61 user::number
62 eval_as_yap_expr(decltype((a * x + y) * (a * x + y) + (a * x + y)) & expr)
63 {
64     return yap::evaluate(expr);
65 }
66 
67 user::number eval_as_yap_expr_4x(decltype(
68     (a * x + y) * (a * x + y) + (a * x + y) + (a * x + y) * (a * x + y) +
69     (a * x + y) + (a * x + y) * (a * x + y) + (a * x + y) +
70     (a * x + y) * (a * x + y) + (a * x + y)) & expr)
71 {
72     return yap::evaluate(expr);
73 }
74 
eval_as_cpp_expr(user::number a,user::number x,user::number y)75 user::number eval_as_cpp_expr(user::number a, user::number x, user::number y)
76 {
77     return (a * x + y) * (a * x + y) + (a * x + y);
78 }
79 
eval_as_cpp_expr_4x(user::number a,user::number x,user::number y)80 user::number eval_as_cpp_expr_4x(user::number a, user::number x, user::number y)
81 {
82     return (a * x + y) * (a * x + y) + (a * x + y) + (a * x + y) * (a * x + y) +
83            (a * x + y) + (a * x + y) * (a * x + y) + (a * x + y) +
84            (a * x + y) * (a * x + y) + (a * x + y);
85 }
86 
87 
main()88 int main()
89 {
90     auto expr = (a * x + y) * (a * x + y) + (a * x + y);
91     user::number result_1 = eval_as_yap_expr(expr);
92     user::number result_2 =
93         eval_as_cpp_expr(yap::value(a), yap::value(x), yap::value(y));
94 
95     (void)result_1;
96     (void)result_2;
97 
98     return 0;
99 }
100