• 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/yap.hpp>
7 
8 #include <vector>
9 #include <iostream>
10 
11 #include <boost/test/minimal.hpp>
12 
13 
14 int allocations = 0;
15 
operator new(std::size_t size)16 void * operator new(std::size_t size)
17 {
18     ++allocations;
19     void * retval = malloc(size);
20     if (!retval)
21         throw std::bad_alloc();
22     return retval;
23 }
24 
operator delete(void * ptr)25 void operator delete(void * ptr) noexcept { free(ptr); }
26 
27 
28 struct take_nth
29 {
30     template<typename T>
operator ()take_nth31     auto operator()(
32         boost::yap::expr_tag<boost::yap::expr_kind::terminal>,
33         std::vector<T> const & vec)
34     {
35         return boost::yap::make_terminal(vec[n]);
36     }
37 
38     std::size_t n;
39 };
40 
41 struct equal_sizes_impl
42 {
43     template<typename T>
operator ()equal_sizes_impl44     auto operator()(
45         boost::yap::expr_tag<boost::yap::expr_kind::terminal>,
46         std::vector<T> const & vec)
47     {
48         auto const expr_size = vec.size();
49         if (expr_size != size)
50             value = false;
51         return 0;
52     }
53 
54     std::size_t const size;
55     bool value;
56 };
57 
58 template<typename Expr>
equal_sizes(std::size_t size,Expr const & expr)59 bool equal_sizes(std::size_t size, Expr const & expr)
60 {
61     equal_sizes_impl impl{size, true};
62     boost::yap::transform(boost::yap::as_expr(expr), impl);
63     return impl.value;
64 }
65 
66 
67 template<typename T, typename Expr>
assign(std::vector<T> & vec,Expr const & e)68 std::vector<T> & assign(std::vector<T> & vec, Expr const & e)
69 {
70     decltype(auto) expr = boost::yap::as_expr(e);
71     assert(equal_sizes(vec.size(), expr));
72     for (std::size_t i = 0, size = vec.size(); i < size; ++i) {
73         vec[i] = boost::yap::evaluate(
74             boost::yap::transform(boost::yap::as_expr(expr), take_nth{i}));
75     }
76     return vec;
77 }
78 
79 template<typename T, typename Expr>
operator +=(std::vector<T> & vec,Expr const & e)80 std::vector<T> & operator+=(std::vector<T> & vec, Expr const & e)
81 {
82     decltype(auto) expr = boost::yap::as_expr(e);
83     assert(equal_sizes(vec.size(), expr));
84     for (std::size_t i = 0, size = vec.size(); i < size; ++i) {
85         vec[i] += boost::yap::evaluate(
86             boost::yap::transform(boost::yap::as_expr(expr), take_nth{i}));
87     }
88     return vec;
89 }
90 
91 template<typename T>
92 struct is_vector : std::false_type
93 {
94 };
95 
96 template<typename T, typename A>
97 struct is_vector<std::vector<T, A>> : std::true_type
98 {
99 };
100 
101 BOOST_YAP_USER_UDT_UNARY_OPERATOR(
102     negate, boost::yap::expression, is_vector); // -
103 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
104     multiplies, boost::yap::expression, is_vector); // *
105 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
106     divides, boost::yap::expression, is_vector); // /
107 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
108     modulus, boost::yap::expression, is_vector); // %
109 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
110     plus, boost::yap::expression, is_vector); // +
111 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
112     minus, boost::yap::expression, is_vector); // -
113 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
114     less, boost::yap::expression, is_vector); // <
115 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
116     greater, boost::yap::expression, is_vector); // >
117 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
118     less_equal, boost::yap::expression, is_vector); // <=
119 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
120     greater_equal, boost::yap::expression, is_vector); // >=
121 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
122     equal_to, boost::yap::expression, is_vector); // ==
123 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
124     not_equal_to, boost::yap::expression, is_vector); // !=
125 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
126     logical_or, boost::yap::expression, is_vector); // ||
127 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
128     logical_and, boost::yap::expression, is_vector); // &&
129 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
130     bitwise_and, boost::yap::expression, is_vector); // &
131 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
132     bitwise_or, boost::yap::expression, is_vector); // |
133 BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR(
134     bitwise_xor, boost::yap::expression, is_vector); // ^
135 
test_main(int,char * [])136 int test_main(int, char * [])
137 {
138     int i;
139     int const n = 10;
140     std::vector<int> a(n), b(n), c(n), d(n);
141     std::vector<double> e(n);
142 
143     // Reset allocation count.  There should be none from this point on.
144     allocations = 0;
145 
146     for (i = 0; i < n; ++i) {
147         a[i] = i;
148         b[i] = 2 * i;
149         c[i] = 3 * i;
150         d[i] = i;
151     }
152 
153     assign(b, 2);
154     assign(d, a + b * c);
155 
156     if_else(d < 30, b, c);
157     a += if_else(d < 30, b, c);
158 
159     assign(e, c);
160     e += e - 4 / (c + 1);
161 
162     for (i = 0; i < n; ++i) {
163         std::cout << " a(" << i << ") = " << a[i] << " b(" << i
164                   << ") = " << b[i] << " c(" << i << ") = " << c[i] << " d("
165                   << i << ") = " << d[i] << " e(" << i << ") = " << e[i]
166                   << std::endl;
167     }
168 
169     BOOST_CHECK(allocations == 0);
170 
171     return 0;
172 }
173