#include "test_header.h" #include namespace { template void setMARandom(MA& ma, int seed) { std::srand(seed); double n = 0; double d = 0; for(auto& x: ma.vdata()){ double nx = 0; double dx = 0; while(nx == x or dx == d or nx == dx or dx == 0){ nx = static_cast(std::rand() % 1000); dx = static_cast(std::rand() % 1000); } n = nx; d = dx; assert(n != d); x = n/d; } } template DynamicO mkDynOp(const Op& op) { return DynamicO(op); } template DynamicO mkDynMul(const Op1& op1, const Op2& op2) { auto op = op1 * op2; return DynamicO(std::make_shared>(op)); } class OpTest_Dyn : public ::testing::Test { protected: MultiArray ma1; MultiArray ma2; MultiArray ma3; MultiArray ma5; MultiArray res1; MultiArray res2; std::map> imap; std::shared_ptr dr1; std::shared_ptr dr2; std::shared_ptr dr3; std::shared_ptr dr4; std::shared_ptr dr5; std::shared_ptr dr6; std::shared_ptr cr1; OpTest_Dyn() { cr1 = createRangeE(5); auto cr2 = createRangeE(7); auto cr3 = createRangeE(11); auto cr4 = createRangeE(3); auto cr5 = createRangeE(13); dr1 = createRangeE(cr2,cr2,cr3,cr4); dr2 = createRangeE(cr3,cr3,cr4); dr3 = createRangeE(cr2,cr5); dr5 = createRangeE(cr5); dr6 = createRangeE(cr3,cr4); dr4 = createRangeE(cr2,cr3,cr4,cr4); ma1 = mkArray(cr1,dr1); ma2 = mkArray(cr1,dr2); ma3 = mkArray(dr3); ma5 = mkArray(dr5); res1 = mkArray(cr1,dr4); res2 = mkArray(cr1,dr6); setMARandom(ma1, 25); setMARandom(ma2, 31); setMARandom(ma3, 47); setMARandom(ma5, 59); imap["i2_1"] = mkIndexW(getIndex(cr2)); imap["i2_2"] = mkIndexW(getIndex(cr2)); imap["i3_1"] = mkIndexW(getIndex(cr3)); imap["i3_2"] = mkIndexW(getIndex(cr3)); imap["i4_1"] = mkIndexW(getIndex(cr4)); imap["i4_2"] = mkIndexW(getIndex(cr4)); imap["i5_1"] = mkIndexW(getIndex(cr5)); imap["i5_2"] = mkIndexW(getIndex(cr5)); } }; TEST_F(OpTest_Dyn, Multiply) { auto i1 = getIndex(cr1); auto di1 = getIndex(dr1); auto di2 = getIndex(dr2); auto di4 = getIndex(dr4); (*di1)({imap["i2_1"],imap["i2_2"],imap["i3_1"],imap["i4_1"]}); (*di2)({imap["i3_1"],imap["i3_1"],imap["i4_2"]}); (*di4)({imap["i2_1"],imap["i3_1"],imap["i4_1"],imap["i4_2"]}); auto resx1 = res1; auto resx2 = res1; auto resx3 = res1; res1(i1,di4) = ma1(i1,di1) * ma2(i1,di2); resx1(i1,di4) = mkDynOp(ma1(i1,di1)) * mkDynOp(ma2(i1,di2)); resx2(i1,di4) = mkDynOp(ma1(i1,di1) * ma2(i1,di2)); resx3(i1,di4) = mkDynOp(mkDynOp(ma1(i1,di1)) * mkDynOp(ma2(i1,di2))); auto i2_1 = imap.at("i2_1"); auto i2_2 = imap.at("i2_2"); auto i3_1 = imap.at("i3_1"); auto i4_1 = imap.at("i4_1"); auto i4_2 = imap.at("i4_2"); for(size_t ii1 = 0; ii1 != i1->max(); ++ii1){ for(size_t ii2_1 = 0; ii2_1 != i2_1->max(); ++ii2_1){ size_t ii2_2 = 0; for(size_t ii3_1 = 0; ii3_1 != i3_1->max(); ++ii3_1){ for(size_t ii4_1 = 0; ii4_1 != i4_1->max(); ++ii4_1){ for(size_t ii4_2 = 0; ii4_2 != i4_2->max(); ++ii4_2){ const size_t jr = (((ii1*i2_1->max() + ii2_1)*i3_1->max() + ii3_1)*i4_1->max() + ii4_1)*i4_2->max() + ii4_2; const size_t j1 = (((ii1*i2_1->max() + ii2_1)*i2_2->max() + ii2_2)*i3_1->max() + ii3_1)*i4_1->max() + ii4_1; const size_t j2 = ((ii1*i3_1->max() + ii3_1)*i3_1->max() + ii3_1)*i4_2->max() + ii4_2; auto resv = xround(res1.vdata()[jr]); auto resx1v = xround(resx1.vdata()[jr]); auto resx2v = xround(resx2.vdata()[jr]); auto resx3v = xround(resx3.vdata()[jr]); auto x12 = xround(ma1.vdata()[j1]*ma2.vdata()[j2]); EXPECT_EQ( resv, x12 ); EXPECT_EQ( resx1v, x12 ); EXPECT_EQ( resx2v, x12 ); EXPECT_EQ( resx3v, x12 ); } } } } //std::cout << std::endl; } } TEST_F(OpTest_Dyn, Contract) { auto i1 = getIndex(cr1); auto di1 = getIndex(dr1); auto di3 = getIndex(dr3); auto di5 = getIndex(dr5); auto di6 = getIndex(dr6); (*di1)({imap["i2_1"],imap["i2_1"],imap["i3_1"],imap["i4_1"]}); (*di3)({imap["i2_1"],imap["i5_1"]}); (*di5)({imap["i5_1"]}); (*di6)({imap["i3_1"],imap["i4_1"]}); auto resx1 = res2; auto resx2 = res2; auto resx3 = res2; res2(i1,di6) += (ma1(i1,di1) * ma5(di5)).c(di3); resx1(i1,di6) += (mkDynOp(ma1(i1,di1)) * mkDynOp(ma5(di5))).c(di3); resx2(i1,di6) += mkDynOp((ma1(i1,di1) * ma5(di5)).c(di3)); resx3(i1,di6) += mkDynOp((mkDynOp(ma1(i1,di1)) * mkDynOp(ma5(di5))).c(di3)); auto i2_1 = imap.at("i2_1"); auto i3_1 = imap.at("i3_1"); auto i4_1 = imap.at("i4_1"); auto i5_1 = imap.at("i5_1"); for(size_t ii1 = 0; ii1 != i1->max(); ++ii1){ for(size_t ii3_1 = 0; ii3_1 != i3_1->max(); ++ii3_1){ for(size_t ii4_1 = 0; ii4_1 != i4_1->max(); ++ii4_1){ double vv = 0; const size_t jr = (ii1*i3_1->max() + ii3_1)*i4_1->max() + ii4_1; for(size_t ii2_1 = 0; ii2_1 != i2_1->max(); ++ii2_1){ const size_t j1 = (((ii1*i2_1->max() + ii2_1)*i2_1->max() + ii2_1)*i3_1->max() + ii3_1)*i4_1->max() + ii4_1; for(size_t ii5_1 = 0; ii5_1 != i5_1->max(); ++ii5_1){ const size_t j2 = ii5_1; vv += ma1.vdata()[j1] * ma5.vdata()[j2]; } } auto resv = xround(res2.vdata()[jr]); auto resx1v = xround(resx1.vdata()[jr]); auto resx2v = xround(resx2.vdata()[jr]); auto resx3v = xround(resx3.vdata()[jr]); auto x12 = xround(vv); EXPECT_EQ( resv, x12 ); EXPECT_EQ( resx1v, x12 ); EXPECT_EQ( resx2v, x12 ); EXPECT_EQ( resx3v, x12 ); } } //std::cout << std::endl; } } TEST_F(OpTest_Dyn, Functional) { auto i1 = getIndex(cr1); auto di1 = getIndex(dr1); auto di2 = getIndex(dr2); auto di4 = getIndex(dr4); (*di1)({imap["i2_1"],imap["i2_2"],imap["i3_1"],imap["i4_1"]}); (*di2)({imap["i3_1"],imap["i3_1"],imap["i4_2"]}); (*di4)({imap["i2_1"],imap["i3_1"],imap["i4_1"],imap["i4_2"]}); auto resx1 = res1; auto resx2 = res1; auto resx3 = res1; res1(i1,di4) = ma1(i1,di1) * exp(ma2(i1,di2)); resx1(i1,di4) = mkDynOp(ma1(i1,di1)) * exp(mkDynOp(ma2(i1,di2))); resx2(i1,di4) = mkDynOp(ma1(i1,di1) * exp(ma2(i1,di2))); resx3(i1,di4) = mkDynOp(mkDynOp(ma1(i1,di1)) * mkDynOp(exp(mkDynOp(ma2(i1,di2))))); auto i2_1 = imap.at("i2_1"); auto i2_2 = imap.at("i2_2"); auto i3_1 = imap.at("i3_1"); auto i4_1 = imap.at("i4_1"); auto i4_2 = imap.at("i4_2"); for(size_t ii1 = 0; ii1 != i1->max(); ++ii1){ for(size_t ii2_1 = 0; ii2_1 != i2_1->max(); ++ii2_1){ size_t ii2_2 = 0; for(size_t ii3_1 = 0; ii3_1 != i3_1->max(); ++ii3_1){ for(size_t ii4_1 = 0; ii4_1 != i4_1->max(); ++ii4_1){ for(size_t ii4_2 = 0; ii4_2 != i4_2->max(); ++ii4_2){ const size_t jr = (((ii1*i2_1->max() + ii2_1)*i3_1->max() + ii3_1)*i4_1->max() + ii4_1)*i4_2->max() + ii4_2; const size_t j1 = (((ii1*i2_1->max() + ii2_1)*i2_2->max() + ii2_2)*i3_1->max() + ii3_1)*i4_1->max() + ii4_1; const size_t j2 = ((ii1*i3_1->max() + ii3_1)*i3_1->max() + ii3_1)*i4_2->max() + ii4_2; auto resv = xround(res1.vdata()[jr]); auto resx1v = xround(resx1.vdata()[jr]); auto resx2v = xround(resx2.vdata()[jr]); auto resx3v = xround(resx3.vdata()[jr]); auto x12 = xround(ma1.vdata()[j1]*exp(ma2.vdata()[j2])); EXPECT_EQ( resv, x12 ); EXPECT_EQ( resx1v, x12 ); EXPECT_EQ( resx2v, x12 ); EXPECT_EQ( resx3v, x12 ); } } } } //std::cout << std::endl; } } }