// Copyright (C) 2016-2018 T. Zachary Laine // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include int allocations = 0; void * operator new(std::size_t size) { ++allocations; void * retval = malloc(size); if (!retval) throw std::bad_alloc(); return retval; } void operator delete(void * ptr) noexcept { free(ptr); } struct take_nth { template auto operator()( boost::yap::expr_tag, std::vector const & vec) { return boost::yap::make_terminal(vec[n]); } std::size_t n; }; struct equal_sizes_impl { template auto operator()( boost::yap::expr_tag, std::vector const & vec) { auto const expr_size = vec.size(); if (expr_size != size) value = false; return 0; } std::size_t const size; bool value; }; template bool equal_sizes(std::size_t size, Expr const & expr) { equal_sizes_impl impl{size, true}; boost::yap::transform(boost::yap::as_expr(expr), impl); return impl.value; } template std::vector & assign(std::vector & vec, Expr const & e) { decltype(auto) expr = boost::yap::as_expr(e); assert(equal_sizes(vec.size(), expr)); for (std::size_t i = 0, size = vec.size(); i < size; ++i) { vec[i] = boost::yap::evaluate( boost::yap::transform(boost::yap::as_expr(expr), take_nth{i})); } return vec; } template std::vector & operator+=(std::vector & vec, Expr const & e) { decltype(auto) expr = boost::yap::as_expr(e); assert(equal_sizes(vec.size(), expr)); for (std::size_t i = 0, size = vec.size(); i < size; ++i) { vec[i] += boost::yap::evaluate( boost::yap::transform(boost::yap::as_expr(expr), take_nth{i})); } return vec; } template struct is_vector : std::false_type { }; template struct is_vector> : std::true_type { }; BOOST_YAP_USER_UDT_UNARY_OPERATOR( negate, boost::yap::expression, is_vector); // - BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( multiplies, boost::yap::expression, is_vector); // * BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( divides, boost::yap::expression, is_vector); // / BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( modulus, boost::yap::expression, is_vector); // % BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( plus, boost::yap::expression, is_vector); // + BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( minus, boost::yap::expression, is_vector); // - BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( less, boost::yap::expression, is_vector); // < BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( greater, boost::yap::expression, is_vector); // > BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( less_equal, boost::yap::expression, is_vector); // <= BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( greater_equal, boost::yap::expression, is_vector); // >= BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( equal_to, boost::yap::expression, is_vector); // == BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( not_equal_to, boost::yap::expression, is_vector); // != BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( logical_or, boost::yap::expression, is_vector); // || BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( logical_and, boost::yap::expression, is_vector); // && BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( bitwise_and, boost::yap::expression, is_vector); // & BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( bitwise_or, boost::yap::expression, is_vector); // | BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( bitwise_xor, boost::yap::expression, is_vector); // ^ int test_main(int, char * []) { int i; int const n = 10; std::vector a(n), b(n), c(n), d(n); std::vector e(n); // Reset allocation count. There should be none from this point on. allocations = 0; for (i = 0; i < n; ++i) { a[i] = i; b[i] = 2 * i; c[i] = 3 * i; d[i] = i; } assign(b, 2); assign(d, a + b * c); if_else(d < 30, b, c); a += if_else(d < 30, b, c); assign(e, c); e += e - 4 / (c + 1); for (i = 0; i < n; ++i) { std::cout << " a(" << i << ") = " << a[i] << " b(" << i << ") = " << b[i] << " c(" << i << ") = " << c[i] << " d(" << i << ") = " << d[i] << " e(" << i << ") = " << e[i] << std::endl; } BOOST_CHECK(allocations == 0); return 0; }