alsk/tests/serial.cpp

153 lines
4.1 KiB
C++

#include <catch.hpp>
#include <alsk/alsk.h>
#include "common.h"
using namespace alsk;
namespace {
using Vector = Measure<std::vector<int>>;
using Struct =
S<Serial,
S<Serial, Mult, Mult, MultC<double>, Add>,
MultC<double>,
Sqrt,
S<Serial, Add, Div>,
S<Serial, MultC<double>, Add, Div>,
Tupler
>;
using Links =
L<Serial, arg::R<5>(double, double, double),
L<Serial, arg::R<3>(arg::P<0>, arg::P<1>, arg::P<2>), // a, b, c
double(arg::P<1>, arg::P<1>), // b*b
double(arg::P<0>, arg::P<2>), // a*c
double(arg::R<1>), // a*c*#
double(arg::R<0>, arg::R<2>) // b*b + a*c*# = D
>,
double(arg::P<0>), // a*#
double(arg::R<0>), // sqrt(D)
L<Serial, arg::R<1>(arg::P<1>, arg::R<2>, arg::R<1>), // b, sqrt(D), a*#
double(arg::P<0>, arg::P<1>), // +
double(arg::R<0>, arg::P<2>) // ^/(a*#)
>,
L<Serial, arg::R<2>(arg::P<1>, arg::R<2>, arg::R<1>), // b, sqrt(D), a*#
double(arg::P<1>), // sqrt(D)*#
double(arg::R<0>, arg::P<0>), // ^+b
double(arg::R<1>, arg::P<2>) // ^/(a*#)
>,
std::tuple<double, double>(arg::R<3>, arg::R<4>)
>;
using Solver = BuildSkeletonT<Struct, Links>;
constexpr std::initializer_list<int> benchVec1{5, 2, 3, 7, 8, 9, 1, 2, 7, 6, 3, 2, 7};
constexpr std::initializer_list<int> benchVec2{2, 2, 3, 5, 2, 1, 1, 4, 7, 9, 2, 3, 5, 6, 1};
using MultiplyByV = MultiplyBy<Vector>;
using ProcessV = Process<Vector>;
using SumV = Sum<Vector>;
using ProdVectV = ProdVect<Vector>;
using CMTestStruct = S<Serial, MultiplyByV, MultiplyByV, ProcessV, ProcessV, SumV, ProdVectV>;
using CMTestLinks =
L<Serial, arg::R<4>(int, int, int, int&),
int(arg::P<0>), int(arg::P<1>),
Vector(arg::P<2>, arg::R<0>), Vector(arg::P<2>, arg::R<1>),
Vector(arg::R<2> const&, arg::R<3> const&),
void(arg::P<3>, arg::R<2> const&, arg::R<3> const&)
>;
using CMTest = BuildSkeletonT<CMTestStruct, CMTestLinks>;
decltype(auto) cmTest(int a, int b, int n, int& r) {
decltype(auto) r0 = MultiplyByV{Vector::value_type{benchVec1}}(a);
decltype(auto) r1 = MultiplyByV{Vector::value_type{benchVec2}}(b);
decltype(auto) r2 = ProcessV{}(n, r0);
decltype(auto) r3 = ProcessV{}(n, r1);
decltype(auto) r4 = SumV{}(r2, r3);
ProdVectV{}(r, r2, r3);
return r4;
}
}
TEST_CASE("Serial") {
SECTION("basic test") {
using F0 = std::function<int()>;
using FN = std::function<int(int)>;
using FX = std::function<int(int, int)>;
std::size_t count;
F0 f0 = [&]{ ++count; return 0; };
FN f1 = [&](int v) { ++count; return v+1; };
FN f2 = [&](int v) { ++count; return v*2; };
FX f3 = [&](int v, int x) { ++count; return v<<x; };
using Struct = S<Serial, F0, S<Serial, FN, FN>, FX>;
using Links = L<Serial, arg::R<2>(int), int(), L<Serial, arg::R<1>(arg::R<0>), int(arg::P<0>), int(arg::R<0>)>, int(arg::R<1>, arg::P<0>)>;
using Skel = BuildSkeletonT<Struct, Links>;
auto f = implement<exec::FirstLevelEqui, Skel>();
f.skeleton.task<0>() = f0;
f.skeleton.task<1>().task<0>() = f1;
f.skeleton.task<1>().task<1>() = f2;
f.skeleton.task<2>() = f3;
count = 0;
REQUIRE(f(3) == 16);
REQUIRE(count == 4);
}
SECTION("serial") {
auto solver = implement<exec::StaticPool, Solver>();
solver.skeleton.task<0>().task<2>().m = -4;
solver.skeleton.task<1>().m = -2;
solver.skeleton.task<4>().task<0>().m = -1;
double x0 = -2.63;
double x1 = 3.77;
double a = 3.7;
double b = -a*(x0+x1);
double c = a*x0*x1;
auto sol = solver(a, b, c);
REQUIRE(std::get<0>(sol) == Approx{x0});
REQUIRE(std::get<1>(sol) == Approx{x1});
}
SECTION("copy/moves") {
int a{500}, b{100}, n{1'000}, r;
int cpBase, mvBase, cpSkel, mvSkel;
_copy = _move = 0;
cmTest(a, b, n, r);
cpBase = _copy;
mvBase = _move;
std::printf("[base] copy: %zu, move: %zu\n", _copy, _move);
_copy = _move = 0;
auto cmTestSkel = implement<exec::Sequential, CMTest>();
// cmTestSkel(a, b);
cmTestSkel.skeleton.task<0>() = MultiplyByV{Vector::value_type{benchVec1}};
cmTestSkel.skeleton.task<1>() = MultiplyByV{Vector::value_type{benchVec2}};
cmTestSkel(a, b, n, r);
cpSkel = _copy;
mvSkel = _move;
std::printf("[skel] copy: %zu, move: %zu\n", _copy, _move);
REQUIRE(cpBase >= cpSkel);
REQUIRE(mvBase <= mvSkel);
}
}