• 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 #include <algorithm>
9 #include <cassert>
10 #include <iostream>
11 #include <vector>
12 
13 #include <boost/test/minimal.hpp>
14 
15 
16 int allocations = 0;
17 
operator new(std::size_t size)18 void * operator new(std::size_t size)
19 {
20     ++allocations;
21     void * retval = malloc(size);
22     if (!retval)
23         throw std::bad_alloc();
24     return retval;
25 }
26 
operator delete(void * ptr)27 void operator delete(void * ptr) noexcept { free(ptr); }
28 
29 
30 template<boost::yap::expr_kind Kind, typename Tuple>
31 struct lazy_vector_expr;
32 
33 
34 struct take_nth
35 {
36     boost::yap::terminal<lazy_vector_expr, double> operator()(
37         boost::yap::terminal<lazy_vector_expr, std::vector<double>> const &
38             expr);
39 
40     std::size_t n;
41 };
42 
43 template<boost::yap::expr_kind Kind, typename Tuple>
44 struct lazy_vector_expr
45 {
46     static const boost::yap::expr_kind kind = Kind;
47 
48     Tuple elements;
49 
operator []lazy_vector_expr50     auto operator[](std::size_t n) const
51     {
52         return boost::yap::evaluate(boost::yap::transform(*this, take_nth{n}));
53     }
54 };
55 
BOOST_YAP_USER_BINARY_OPERATOR(plus,lazy_vector_expr,lazy_vector_expr)56 BOOST_YAP_USER_BINARY_OPERATOR(plus, lazy_vector_expr, lazy_vector_expr)
57 BOOST_YAP_USER_BINARY_OPERATOR(minus, lazy_vector_expr, lazy_vector_expr)
58 
59 boost::yap::terminal<lazy_vector_expr, double> take_nth::operator()(
60     boost::yap::terminal<lazy_vector_expr, std::vector<double>> const & expr)
61 {
62     double x = boost::yap::value(expr)[n];
63     return boost::yap::make_terminal<lazy_vector_expr, double>(std::move(x));
64 }
65 
66 struct lazy_vector : lazy_vector_expr<
67                          boost::yap::expr_kind::terminal,
68                          boost::hana::tuple<std::vector<double>>>
69 {
lazy_vectorlazy_vector70     lazy_vector() {}
71 
lazy_vectorlazy_vector72     explicit lazy_vector(std::vector<double> && vec)
73     {
74         elements = boost::hana::tuple<std::vector<double>>(std::move(vec));
75     }
76 
77     template<boost::yap::expr_kind Kind, typename Tuple>
operator +=lazy_vector78     lazy_vector & operator+=(lazy_vector_expr<Kind, Tuple> const & rhs)
79     {
80         std::vector<double> & this_vec = boost::yap::value(*this);
81         for (int i = 0, size = (int)this_vec.size(); i < size; ++i) {
82             this_vec[i] += rhs[i];
83         }
84         return *this;
85     }
86 };
87 
88 
test_main(int,char * [])89 int test_main(int, char * [])
90 {
91     lazy_vector v1{std::vector<double>(4, 1.0)};
92     lazy_vector v2{std::vector<double>(4, 2.0)};
93     lazy_vector v3{std::vector<double>(4, 3.0)};
94 
95     // Reset allocation count.  There should be none from this point on.
96     allocations = 0;
97 
98     double d1 = (v2 + v3)[2];
99     std::cout << d1 << "\n";
100 
101     v1 += v2 - v3;
102     std::cout << '{' << v1[0] << ',' << v1[1] << ',' << v1[2] << ',' << v1[3]
103               << '}' << "\n";
104 
105     BOOST_CHECK(allocations == 0);
106 
107     return 0;
108 }
109