diff options
Diffstat (limited to 'eval/src/tests/tensor')
31 files changed, 0 insertions, 2206 deletions
diff --git a/eval/src/tests/tensor/dense_add_dimension_optimizer/CMakeLists.txt b/eval/src/tests/tensor/dense_add_dimension_optimizer/CMakeLists.txt deleted file mode 100644 index 1bc9f93b1a2..00000000000 --- a/eval/src/tests/tensor/dense_add_dimension_optimizer/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -vespa_add_executable(eval_dense_add_dimension_optimizer_test_app TEST - SOURCES - dense_add_dimension_optimizer_test.cpp - DEPENDS - vespaeval -) -vespa_add_test(NAME eval_dense_add_dimension_optimizer_test_app COMMAND eval_dense_add_dimension_optimizer_test_app) diff --git a/eval/src/tests/tensor/dense_add_dimension_optimizer/dense_add_dimension_optimizer_test.cpp b/eval/src/tests/tensor/dense_add_dimension_optimizer/dense_add_dimension_optimizer_test.cpp deleted file mode 100644 index 0e8e50daae5..00000000000 --- a/eval/src/tests/tensor/dense_add_dimension_optimizer/dense_add_dimension_optimizer_test.cpp +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include <vespa/vespalib/testkit/test_kit.h> -#include <vespa/eval/eval/fast_value.h> -#include <vespa/eval/eval/tensor_function.h> -#include <vespa/eval/tensor/dense/dense_replace_type_function.h> -#include <vespa/eval/tensor/dense/dense_fast_rename_optimizer.h> -#include <vespa/eval/eval/test/tensor_model.hpp> -#include <vespa/eval/eval/test/eval_fixture.h> - -#include <vespa/vespalib/util/stringfmt.h> -#include <vespa/vespalib/util/stash.h> - -using namespace vespalib; -using namespace vespalib::eval; -using namespace vespalib::eval::test; -using namespace vespalib::tensor; -using namespace vespalib::eval::tensor_function; - -const ValueBuilderFactory &prod_factory = FastValueBuilderFactory::get(); - -EvalFixture::ParamRepo make_params() { - return EvalFixture::ParamRepo() - .add("x5", spec({x(5)}, N())) - .add("x5f", spec(float_cells({x(5)}), N())) - .add("x5y1", spec({x(5),y(1)}, N())) - .add("y1z1", spec({y(1),z(1)}, N())) - .add("x_m", spec({x({"a"})}, N())); -} -EvalFixture::ParamRepo param_repo = make_params(); - -void verify_optimized(const vespalib::string &expr) { - EvalFixture fixture(prod_factory, expr, param_repo, true); - EXPECT_EQUAL(fixture.result(), EvalFixture::ref(expr, param_repo)); - auto info = fixture.find_all<DenseReplaceTypeFunction>(); - EXPECT_EQUAL(info.size(), 1u); -} - -void verify_not_optimized(const vespalib::string &expr) { - EvalFixture fixture(prod_factory, expr, param_repo, true); - EXPECT_EQUAL(fixture.result(), EvalFixture::ref(expr, param_repo)); - auto info = fixture.find_all<DenseReplaceTypeFunction>(); - EXPECT_TRUE(info.empty()); -} - -TEST("require that dimension addition can be optimized") { - TEST_DO(verify_optimized("join(x5,tensor(y[1])(1),f(a,b)(a*b))")); - TEST_DO(verify_optimized("join(tensor(y[1])(1),x5,f(a,b)(a*b))")); - TEST_DO(verify_optimized("x5*tensor(y[1])(1)")); - TEST_DO(verify_optimized("tensor(y[1])(1)*x5")); - TEST_DO(verify_optimized("x5y1*tensor(z[1])(1)")); - TEST_DO(verify_optimized("tensor(z[1])(1)*x5y1")); -} - -TEST("require that multi-dimension addition can be optimized") { - TEST_DO(verify_optimized("x5*tensor(a[1],b[1],c[1])(1)")); -} - -TEST("require that dimension addition can be chained (and compacted)") { - TEST_DO(verify_optimized("tensor(z[1])(1)*x5*tensor(y[1])(1)")); -} - -TEST("require that constant dimension addition is optimized") { - TEST_DO(verify_optimized("tensor(x[1])(1)*tensor(y[1])(1)")); - TEST_DO(verify_optimized("tensor(x[1])(1.1)*tensor(y[1])(1)")); - TEST_DO(verify_optimized("tensor(x[1])(1)*tensor(y[1])(1.1)")); - TEST_DO(verify_optimized("tensor(x[2])(1)*tensor(y[1])(1)")); - TEST_DO(verify_optimized("tensor(x[1])(1)*tensor(y[2])(1)")); -} - -TEST("require that non-canonical dimension addition is not optimized") { - TEST_DO(verify_not_optimized("x5+tensor(y[1])(0)")); - TEST_DO(verify_not_optimized("tensor(y[1])(0)+x5")); - TEST_DO(verify_not_optimized("x5-tensor(y[1])(0)")); - TEST_DO(verify_not_optimized("x5/tensor(y[1])(1)")); - TEST_DO(verify_not_optimized("tensor(y[1])(1)/x5")); -} - -TEST("require that dimension addition with overlapping dimensions is optimized") { - TEST_DO(verify_optimized("x5y1*tensor(y[1],z[1])(1)")); - TEST_DO(verify_optimized("tensor(y[1],z[1])(1)*x5y1")); -} - -TEST("require that dimension addition with inappropriate dimensions is not optimized") { - TEST_DO(verify_not_optimized("x_m*tensor(y[1])(1)")); - TEST_DO(verify_not_optimized("tensor(y[1])(1)*x_m")); -} - -TEST("require that dimension addition optimization requires unit constant tensor") { - TEST_DO(verify_not_optimized("x5*tensor(y[1])(0.9)")); - TEST_DO(verify_not_optimized("tensor(y[1])(1.1)*x5")); - TEST_DO(verify_not_optimized("x5*tensor(y[1],z[2])(1)")); - TEST_DO(verify_not_optimized("tensor(y[1],z[2])(1)*x5")); - TEST_DO(verify_not_optimized("x5*y1z1")); - TEST_DO(verify_not_optimized("y1z1*x5")); - TEST_DO(verify_not_optimized("tensor(x[1])(1.1)*tensor(y[1])(1.1)")); - TEST_DO(verify_not_optimized("tensor(x[2])(1)*tensor(y[2])(1)")); -} - -TEST("require that optimization also works for float cells") { - TEST_DO(verify_optimized("x5*tensor<float>(a[1],b[1],c[1])(1)")); - TEST_DO(verify_optimized("x5f*tensor<float>(a[1],b[1],c[1])(1)")); -} - -TEST("require that optimization is disabled if unit vector would promote tensor cell types") { - TEST_DO(verify_not_optimized("x5f*tensor(a[1],b[1],c[1])(1)")); -} - -TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/eval/src/tests/tensor/dense_dimension_combiner/CMakeLists.txt b/eval/src/tests/tensor/dense_dimension_combiner/CMakeLists.txt deleted file mode 100644 index eaee8ebb4e4..00000000000 --- a/eval/src/tests/tensor/dense_dimension_combiner/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -vespa_add_executable(eval_dense_dimension_combiner_test_app TEST - SOURCES - dense_dimension_combiner_test.cpp - DEPENDS - vespaeval -) -vespa_add_test(NAME eval_dense_dimension_combiner_test_app COMMAND eval_dense_dimension_combiner_test_app) diff --git a/eval/src/tests/tensor/dense_dimension_combiner/dense_dimension_combiner_test.cpp b/eval/src/tests/tensor/dense_dimension_combiner/dense_dimension_combiner_test.cpp deleted file mode 100644 index b8949e3a7e6..00000000000 --- a/eval/src/tests/tensor/dense_dimension_combiner/dense_dimension_combiner_test.cpp +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include <vespa/vespalib/testkit/test_kit.h> -#include <vespa/eval/tensor/dense/dense_dimension_combiner.h> - -using namespace vespalib; -using namespace vespalib::eval; -using namespace vespalib::tensor; - -void verifyLeft(DenseDimensionCombiner &d, size_t last) { - d.commonReset(); - d.leftReset(); - EXPECT_TRUE(d.leftInRange()); - EXPECT_EQUAL(d.leftIdx(), 0u); - size_t expect = 0; - while (d.leftInRange()) { - d.stepLeft(); - EXPECT_GREATER(d.leftIdx(), expect); - expect = d.leftIdx(); - } - EXPECT_FALSE(d.leftInRange()); - EXPECT_EQUAL(expect, last); - d.leftReset(); - EXPECT_TRUE(d.leftInRange()); - EXPECT_EQUAL(d.leftIdx(), 0u); -} - -void verifyRight(DenseDimensionCombiner &d, size_t last) { - d.commonReset(); - d.rightReset(); - EXPECT_TRUE(d.rightInRange()); - EXPECT_EQUAL(d.rightIdx(), 0u); - size_t expect = 0; - while (d.rightInRange()) { - d.stepRight(); - EXPECT_GREATER(d.rightIdx(), expect); - expect = d.rightIdx(); - } - EXPECT_FALSE(d.rightInRange()); - EXPECT_EQUAL(expect, last); - d.rightReset(); - EXPECT_TRUE(d.rightInRange()); - EXPECT_EQUAL(d.rightIdx(), 0u); -} - - -TEST("require that one left, one common, one right dimension works") { - ValueType t12_lc = ValueType::tensor_type({{"d1_l", 3},{"d2_c", 4}}); - ValueType t23_cr = ValueType::tensor_type({{"d2_c", 4},{"d3_r", 5}}); - - DenseDimensionCombiner d(t12_lc, t23_cr); - - EXPECT_TRUE(d.leftInRange()); - EXPECT_TRUE(d.rightInRange()); - EXPECT_TRUE(d.commonInRange()); - EXPECT_EQUAL(d.leftIdx(), 0u); - EXPECT_EQUAL(d.rightIdx(), 0u); - EXPECT_EQUAL(d.outputIdx(), 0u); - - d.stepCommon(); - EXPECT_TRUE(d.leftInRange()); - EXPECT_TRUE(d.rightInRange()); - EXPECT_TRUE(d.commonInRange()); - EXPECT_EQUAL(d.leftIdx(), 1u); - EXPECT_EQUAL(d.rightIdx(), 5u); - EXPECT_EQUAL(d.outputIdx(), 5u); - - d.stepRight(); - EXPECT_TRUE(d.leftInRange()); - EXPECT_TRUE(d.rightInRange()); - EXPECT_TRUE(d.commonInRange()); - EXPECT_EQUAL(d.leftIdx(), 1u); - EXPECT_EQUAL(d.rightIdx(), 6u); - EXPECT_EQUAL(d.outputIdx(), 6u); - - d.stepLeft(); - EXPECT_TRUE(d.leftInRange()); - EXPECT_TRUE(d.rightInRange()); - EXPECT_TRUE(d.commonInRange()); - EXPECT_EQUAL(d.leftIdx(), 5u); - EXPECT_EQUAL(d.rightIdx(), 6u); - EXPECT_EQUAL(d.outputIdx(), 26u); - - d.stepLeft(); - EXPECT_TRUE(d.leftInRange()); - EXPECT_TRUE(d.rightInRange()); - EXPECT_TRUE(d.commonInRange()); - EXPECT_EQUAL(d.leftIdx(), 9u); - EXPECT_EQUAL(d.rightIdx(), 6u); - EXPECT_EQUAL(d.outputIdx(), 46u); - - d.stepLeft(); - EXPECT_FALSE(d.leftInRange()); - EXPECT_TRUE(d.rightInRange()); - EXPECT_TRUE(d.commonInRange()); - EXPECT_EQUAL(d.leftIdx(), 13u); - EXPECT_EQUAL(d.rightIdx(), 6u); - EXPECT_EQUAL(d.outputIdx(), 6u); - - d.leftReset(); - EXPECT_TRUE(d.leftInRange()); - EXPECT_TRUE(d.rightInRange()); - EXPECT_TRUE(d.commonInRange()); - EXPECT_EQUAL(d.leftIdx(), 1u); - EXPECT_EQUAL(d.rightIdx(), 6u); - EXPECT_EQUAL(d.outputIdx(), 6u); - - d.stepCommon(); - EXPECT_TRUE(d.leftInRange()); - EXPECT_TRUE(d.rightInRange()); - EXPECT_TRUE(d.commonInRange()); - EXPECT_EQUAL(d.leftIdx(), 2u); - EXPECT_EQUAL(d.rightIdx(), 11u); - EXPECT_EQUAL(d.outputIdx(), 11u); - - d.stepRight(); - EXPECT_TRUE(d.leftInRange()); - EXPECT_TRUE(d.rightInRange()); - EXPECT_TRUE(d.commonInRange()); - EXPECT_EQUAL(d.leftIdx(), 2u); - EXPECT_EQUAL(d.rightIdx(), 12u); - EXPECT_EQUAL(d.outputIdx(), 12u); - - TEST_DO(verifyLeft(d, 12)); - TEST_DO(verifyRight(d, 20)); -} - -TEST("require that two left, no common, two right dimensions works") { - ValueType t12_ll = ValueType::tensor_type({{"d1_l", 3},{"d2_l", 4}}); - ValueType t34_rr = ValueType::tensor_type({{"d3_r", 5},{"d4_r", 2}}); - - DenseDimensionCombiner d(t12_ll, t34_rr); - - EXPECT_TRUE(d.leftInRange()); - EXPECT_TRUE(d.rightInRange()); - EXPECT_TRUE(d.commonInRange()); - EXPECT_EQUAL(d.leftIdx(), 0u); - EXPECT_EQUAL(d.rightIdx(), 0u); - EXPECT_EQUAL(d.outputIdx(), 0u); - - d.stepCommon(); - EXPECT_TRUE(d.leftInRange()); - EXPECT_TRUE(d.rightInRange()); - EXPECT_FALSE(d.commonInRange()); - EXPECT_EQUAL(d.leftIdx(), 0u); - EXPECT_EQUAL(d.rightIdx(), 0u); - EXPECT_EQUAL(d.outputIdx(), 120u); - - d.commonReset(); - d.stepRight(); - EXPECT_TRUE(d.leftInRange()); - EXPECT_TRUE(d.rightInRange()); - EXPECT_TRUE(d.commonInRange()); - EXPECT_EQUAL(d.leftIdx(), 0u); - EXPECT_EQUAL(d.rightIdx(), 1u); - EXPECT_EQUAL(d.outputIdx(), 1u); - - d.stepLeft(); - EXPECT_TRUE(d.leftInRange()); - EXPECT_TRUE(d.rightInRange()); - EXPECT_TRUE(d.commonInRange()); - EXPECT_EQUAL(d.leftIdx(), 1u); - EXPECT_EQUAL(d.rightIdx(), 1u); - EXPECT_EQUAL(d.outputIdx(), 11u); - - d.stepLeft(); - d.stepLeft(); - d.stepLeft(); - d.stepLeft(); - d.stepLeft(); - d.stepLeft(); - d.stepLeft(); - - EXPECT_TRUE(d.leftInRange()); - EXPECT_TRUE(d.rightInRange()); - EXPECT_TRUE(d.commonInRange()); - EXPECT_EQUAL(d.leftIdx(), 8u); - EXPECT_EQUAL(d.rightIdx(), 1u); - EXPECT_EQUAL(d.outputIdx(), 81u); - - TEST_DO(verifyLeft(d, 12)); - TEST_DO(verifyRight(d, 10)); -} - -TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/eval/src/tests/tensor/dense_fast_rename_optimizer/CMakeLists.txt b/eval/src/tests/tensor/dense_fast_rename_optimizer/CMakeLists.txt deleted file mode 100644 index 32cf6c45d1e..00000000000 --- a/eval/src/tests/tensor/dense_fast_rename_optimizer/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -vespa_add_executable(eval_dense_fast_rename_optimizer_test_app TEST - SOURCES - dense_fast_rename_optimizer_test.cpp - DEPENDS - vespaeval -) -vespa_add_test(NAME eval_dense_fast_rename_optimizer_test_app COMMAND eval_dense_fast_rename_optimizer_test_app) diff --git a/eval/src/tests/tensor/dense_fast_rename_optimizer/dense_fast_rename_optimizer_test.cpp b/eval/src/tests/tensor/dense_fast_rename_optimizer/dense_fast_rename_optimizer_test.cpp deleted file mode 100644 index 52afde0e92c..00000000000 --- a/eval/src/tests/tensor/dense_fast_rename_optimizer/dense_fast_rename_optimizer_test.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include <vespa/vespalib/testkit/test_kit.h> -#include <vespa/eval/eval/tensor_function.h> -#include <vespa/eval/tensor/dense/dense_replace_type_function.h> -#include <vespa/eval/tensor/dense/dense_fast_rename_optimizer.h> -#include <vespa/eval/eval/test/tensor_model.hpp> -#include <vespa/eval/eval/test/eval_fixture.h> - -#include <vespa/vespalib/util/stringfmt.h> -#include <vespa/vespalib/util/stash.h> - -using namespace vespalib; -using namespace vespalib::eval; -using namespace vespalib::eval::test; -using namespace vespalib::tensor; -using namespace vespalib::eval::tensor_function; - -const ValueBuilderFactory &prod_factory = FastValueBuilderFactory::get(); - -EvalFixture::ParamRepo make_params() { - return EvalFixture::ParamRepo() - .add("x5", spec({x(5)}, N())) - .add("x5f", spec(float_cells({x(5)}), N())) - .add("x_m", spec({x({"a", "b", "c"})}, N())) - .add("x5y3", spec({x(5),y(3)}, N())); -} -EvalFixture::ParamRepo param_repo = make_params(); - -void verify_optimized(const vespalib::string &expr) { - EvalFixture fixture(prod_factory, expr, param_repo, true); - EXPECT_EQUAL(fixture.result(), EvalFixture::ref(expr, param_repo)); - auto info = fixture.find_all<DenseReplaceTypeFunction>(); - EXPECT_EQUAL(info.size(), 1u); -} - -void verify_not_optimized(const vespalib::string &expr) { - EvalFixture fixture(prod_factory, expr, param_repo, true); - EXPECT_EQUAL(fixture.result(), EvalFixture::ref(expr, param_repo)); - auto info = fixture.find_all<DenseReplaceTypeFunction>(); - EXPECT_TRUE(info.empty()); -} - -TEST("require that non-transposing dense renames are optimized") { - TEST_DO(verify_optimized("rename(x5,x,y)")); - TEST_DO(verify_optimized("rename(x5,x,a)")); - TEST_DO(verify_optimized("rename(x5y3,y,z)")); - TEST_DO(verify_optimized("rename(x5y3,x,a)")); - TEST_DO(verify_optimized("rename(x5y3,(x,y),(a,b))")); - TEST_DO(verify_optimized("rename(x5y3,(x,y),(z,zz))")); - TEST_DO(verify_optimized("rename(x5y3,(x,y),(y,z))")); - TEST_DO(verify_optimized("rename(x5y3,(y,x),(b,a))")); -} - -TEST("require that transposing dense renames are not optimized") { - TEST_DO(verify_not_optimized("rename(x5y3,x,z)")); - TEST_DO(verify_not_optimized("rename(x5y3,y,a)")); - TEST_DO(verify_not_optimized("rename(x5y3,(x,y),(y,x))")); - TEST_DO(verify_not_optimized("rename(x5y3,(x,y),(b,a))")); - TEST_DO(verify_not_optimized("rename(x5y3,(y,x),(a,b))")); -} - -TEST("require that non-dense renames are not optimized") { - TEST_DO(verify_not_optimized("rename(x_m,x,y)")); -} - -TEST("require that chained optimized renames are compacted into a single operation") { - TEST_DO(verify_optimized("rename(rename(x5,x,y),y,z)")); -} - -TEST("require that optimization works for float cells") { - TEST_DO(verify_optimized("rename(x5f,x,y)")); -} - -TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/eval/src/tests/tensor/dense_inplace_join_function/CMakeLists.txt b/eval/src/tests/tensor/dense_inplace_join_function/CMakeLists.txt deleted file mode 100644 index 2808675bc78..00000000000 --- a/eval/src/tests/tensor/dense_inplace_join_function/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -vespa_add_executable(eval_dense_inplace_join_function_test_app TEST - SOURCES - dense_inplace_join_function_test.cpp - DEPENDS - vespaeval -) -vespa_add_test(NAME eval_dense_inplace_join_function_test_app COMMAND eval_dense_inplace_join_function_test_app) diff --git a/eval/src/tests/tensor/dense_inplace_join_function/dense_inplace_join_function_test.cpp b/eval/src/tests/tensor/dense_inplace_join_function/dense_inplace_join_function_test.cpp deleted file mode 100644 index 853607ae76d..00000000000 --- a/eval/src/tests/tensor/dense_inplace_join_function/dense_inplace_join_function_test.cpp +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include <vespa/vespalib/testkit/test_kit.h> -#include <vespa/eval/eval/tensor_function.h> -#include <vespa/eval/eval/test/tensor_model.hpp> -#include <vespa/eval/eval/test/eval_fixture.h> - -#include <vespa/vespalib/util/stringfmt.h> -#include <vespa/vespalib/util/stash.h> - -using namespace vespalib; -using namespace vespalib::eval; -using namespace vespalib::eval::test; -using namespace vespalib::tensor; -using namespace vespalib::eval::tensor_function; - -const ValueBuilderFactory &prod_factory = FastValueBuilderFactory::get(); - -double seq_value = 0.0; - -struct GlobalSequence : public Sequence { - GlobalSequence() {} - double operator[](size_t) const override { - seq_value += 1.0; - return seq_value; - } - ~GlobalSequence() {} -}; -GlobalSequence seq; - -EvalFixture::ParamRepo make_params() { - return EvalFixture::ParamRepo() - .add("con_x5_A", spec({x(5)}, seq)) - .add("con_x5_B", spec({x(5)}, seq)) - .add("con_x5_C", spec({x(5)}, seq)) - .add("con_x5y3_A", spec({x(5),y(3)}, seq)) - .add("con_x5y3_B", spec({x(5),y(3)}, seq)) - .add_mutable("mut_dbl_A", spec(1.5)) - .add_mutable("mut_dbl_B", spec(2.5)) - .add_mutable("mut_x5_A", spec({x(5)}, seq)) - .add_mutable("mut_x5_B", spec({x(5)}, seq)) - .add_mutable("mut_x5_C", spec({x(5)}, seq)) - .add_mutable("mut_x5f_D", spec(float_cells({x(5)}), seq)) - .add_mutable("mut_x5f_E", spec(float_cells({x(5)}), seq)) - .add_mutable("mut_x5y3_A", spec({x(5),y(3)}, seq)) - .add_mutable("mut_x5y3_B", spec({x(5),y(3)}, seq)) - .add_mutable("mut_x_sparse", spec({x({"a", "b", "c"})}, seq)); -} -EvalFixture::ParamRepo param_repo = make_params(); - -void verify_optimized(const vespalib::string &expr, size_t param_idx) { - EvalFixture fixture(prod_factory, expr, param_repo, true, true); - EXPECT_EQUAL(fixture.result(), EvalFixture::ref(expr, param_repo)); - for (size_t i = 0; i < fixture.num_params(); ++i) { - TEST_STATE(vespalib::make_string("param %zu", i).c_str()); - if (i == param_idx) { - EXPECT_EQUAL(fixture.get_param(i), fixture.result()); - } else { - EXPECT_NOT_EQUAL(fixture.get_param(i), fixture.result()); - } - } -} - -void verify_p0_optimized(const vespalib::string &expr) { - verify_optimized(expr, 0); -} - -void verify_p1_optimized(const vespalib::string &expr) { - verify_optimized(expr, 1); -} - -void verify_p2_optimized(const vespalib::string &expr) { - verify_optimized(expr, 2); -} - -void verify_not_optimized(const vespalib::string &expr) { - EvalFixture fixture(prod_factory, expr, param_repo, true, true); - EXPECT_EQUAL(fixture.result(), EvalFixture::ref(expr, param_repo)); - for (size_t i = 0; i < fixture.num_params(); ++i) { - EXPECT_NOT_EQUAL(fixture.get_param(i), fixture.result()); - } -} - -TEST("require that mutable dense concrete tensors are optimized") { - TEST_DO(verify_p1_optimized("mut_x5_A-mut_x5_B")); - TEST_DO(verify_p0_optimized("mut_x5_A-con_x5_B")); - TEST_DO(verify_p1_optimized("con_x5_A-mut_x5_B")); - TEST_DO(verify_p1_optimized("mut_x5y3_A-mut_x5y3_B")); - TEST_DO(verify_p0_optimized("mut_x5y3_A-con_x5y3_B")); - TEST_DO(verify_p1_optimized("con_x5y3_A-mut_x5y3_B")); -} - -TEST("require that self-join operations can be optimized") { - TEST_DO(verify_p0_optimized("mut_x5_A+mut_x5_A")); -} - -TEST("require that join(tensor,scalar) operations are optimized") { - TEST_DO(verify_p0_optimized("mut_x5_A-mut_dbl_B")); - TEST_DO(verify_p1_optimized("mut_dbl_A-mut_x5_B")); -} - -TEST("require that join with different tensor shapes are optimized") { - TEST_DO(verify_p1_optimized("mut_x5_A*mut_x5y3_B")); -} - -TEST("require that inplace join operations can be chained") { - TEST_DO(verify_p2_optimized("mut_x5_A+(mut_x5_B+mut_x5_C)")); - TEST_DO(verify_p0_optimized("(mut_x5_A+con_x5_B)+con_x5_C")); - TEST_DO(verify_p1_optimized("con_x5_A+(mut_x5_B+con_x5_C)")); - TEST_DO(verify_p2_optimized("con_x5_A+(con_x5_B+mut_x5_C)")); -} - -TEST("require that non-mutable tensors are not optimized") { - TEST_DO(verify_not_optimized("con_x5_A+con_x5_B")); -} - -TEST("require that scalar values are not optimized") { - TEST_DO(verify_not_optimized("mut_dbl_A+mut_dbl_B")); - TEST_DO(verify_not_optimized("mut_dbl_A+5")); - TEST_DO(verify_not_optimized("5+mut_dbl_B")); -} - -TEST("require that mapped tensors are not optimized") { - TEST_DO(verify_not_optimized("mut_x_sparse+mut_x_sparse")); -} - -TEST("require that optimization works with float cells") { - TEST_DO(verify_p1_optimized("mut_x5f_D-mut_x5f_E")); -} - -TEST("require that overwritten value must have same cell type as result") { - TEST_DO(verify_p0_optimized("mut_x5_A-mut_x5f_D")); - TEST_DO(verify_p1_optimized("mut_x5f_D-mut_x5_A")); - TEST_DO(verify_not_optimized("con_x5_A-mut_x5f_D")); - TEST_DO(verify_not_optimized("mut_x5f_D-con_x5_A")); -} - -TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/eval/src/tests/tensor/dense_pow_as_map_optimizer/CMakeLists.txt b/eval/src/tests/tensor/dense_pow_as_map_optimizer/CMakeLists.txt deleted file mode 100644 index d6ce9f1924c..00000000000 --- a/eval/src/tests/tensor/dense_pow_as_map_optimizer/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -vespa_add_executable(eval_dense_pow_as_map_optimizer_test_app TEST - SOURCES - dense_pow_as_map_optimizer_test.cpp - DEPENDS - vespaeval - GTest::GTest -) -vespa_add_test(NAME eval_dense_pow_as_map_optimizer_test_app COMMAND eval_dense_pow_as_map_optimizer_test_app) diff --git a/eval/src/tests/tensor/dense_pow_as_map_optimizer/dense_pow_as_map_optimizer_test.cpp b/eval/src/tests/tensor/dense_pow_as_map_optimizer/dense_pow_as_map_optimizer_test.cpp deleted file mode 100644 index d00744bcfaf..00000000000 --- a/eval/src/tests/tensor/dense_pow_as_map_optimizer/dense_pow_as_map_optimizer_test.cpp +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include <vespa/eval/eval/fast_value.h> -#include <vespa/eval/eval/tensor_function.h> -#include <vespa/eval/tensor/dense/dense_simple_map_function.h> -#include <vespa/eval/eval/test/eval_fixture.h> -#include <vespa/eval/eval/test/tensor_model.hpp> -#include <vespa/vespalib/gtest/gtest.h> - -using namespace vespalib::eval::operation; -using namespace vespalib::eval::tensor_function; -using namespace vespalib::eval::test; -using namespace vespalib::eval; -using namespace vespalib::tensor; -//using namespace vespalib; - -const ValueBuilderFactory &prod_factory = FastValueBuilderFactory::get(); - -EvalFixture::ParamRepo make_params() { - return EvalFixture::ParamRepo() - .add("a", spec(1.5)) - .add("b", spec(2.5)) - .add("sparse", spec({x({"a"})}, N())) - .add("mixed", spec({x({"a"}),y(5)}, N())) - .add_matrix("x", 5, "y", 3); -} -EvalFixture::ParamRepo param_repo = make_params(); - -void verify_optimized(const vespalib::string &expr, op1_t op1, bool inplace = false) { - EvalFixture slow_fixture(prod_factory, expr, param_repo, false); - EvalFixture fixture(prod_factory, expr, param_repo, true, true); - EXPECT_EQ(fixture.result(), EvalFixture::ref(expr, param_repo)); - EXPECT_EQ(fixture.result(), slow_fixture.result()); - auto info = fixture.find_all<DenseSimpleMapFunction>(); - ASSERT_EQ(info.size(), 1u); - EXPECT_TRUE(info[0]->result_is_mutable()); - EXPECT_EQ(info[0]->function(), op1); - EXPECT_EQ(info[0]->inplace(), inplace); - ASSERT_EQ(fixture.num_params(), 1); - if (inplace) { - EXPECT_EQ(fixture.get_param(0), fixture.result()); - } else { - EXPECT_TRUE(!(fixture.get_param(0) == fixture.result())); - } -} - -void verify_not_optimized(const vespalib::string &expr) { - EvalFixture slow_fixture(prod_factory, expr, param_repo, false); - EvalFixture fixture(prod_factory, expr, param_repo, true); - EXPECT_EQ(fixture.result(), EvalFixture::ref(expr, param_repo)); - EXPECT_EQ(fixture.result(), slow_fixture.result()); - auto info = fixture.find_all<Map>(); - EXPECT_TRUE(info.empty()); -} - -TEST(PowAsMapTest, squared_dense_tensor_is_optimized) { - verify_optimized("x5y3^2.0", Square::f); - verify_optimized("pow(x5y3,2.0)", Square::f); - verify_optimized("join(x5y3,2.0,f(x,y)(x^y))", Square::f); - verify_optimized("join(x5y3,2.0,f(x,y)(pow(x,y)))", Square::f); - verify_optimized("join(x5y3f,2.0,f(x,y)(pow(x,y)))", Square::f); - verify_optimized("join(@x5y3,2.0,f(x,y)(pow(x,y)))", Square::f, true); - verify_optimized("join(@x5y3f,2.0,f(x,y)(pow(x,y)))", Square::f, true); -} - -TEST(PowAsMapTest, cubed_dense_tensor_is_optimized) { - verify_optimized("x5y3^3.0", Cube::f); - verify_optimized("pow(x5y3,3.0)", Cube::f); - verify_optimized("join(x5y3,3.0,f(x,y)(x^y))", Cube::f); - verify_optimized("join(x5y3,3.0,f(x,y)(pow(x,y)))", Cube::f); - verify_optimized("join(x5y3f,3.0,f(x,y)(pow(x,y)))", Cube::f); - verify_optimized("join(@x5y3,3.0,f(x,y)(pow(x,y)))", Cube::f, true); - verify_optimized("join(@x5y3f,3.0,f(x,y)(pow(x,y)))", Cube::f, true); -} - -TEST(PowAsMapTest, hypercubed_dense_tensor_is_not_optimized) { - verify_not_optimized("join(x5y3,4.0,f(x,y)(pow(x,y)))"); -} - -TEST(PowAsMapTest, scalar_join_is_not_optimized) { - verify_not_optimized("join(a,2.0,f(x,y)(pow(x,y)))"); -} - -TEST(PowAsMapTest, sparse_join_is_not_optimized) { - verify_not_optimized("join(sparse,2.0,f(x,y)(pow(x,y)))"); -} - -TEST(PowAsMapTest, mixed_join_is_not_optimized) { - verify_not_optimized("join(mixed,2.0,f(x,y)(pow(x,y)))"); -} - -GTEST_MAIN_RUN_ALL_TESTS() diff --git a/eval/src/tests/tensor/dense_remove_dimension_optimizer/CMakeLists.txt b/eval/src/tests/tensor/dense_remove_dimension_optimizer/CMakeLists.txt deleted file mode 100644 index c945bd31609..00000000000 --- a/eval/src/tests/tensor/dense_remove_dimension_optimizer/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -vespa_add_executable(eval_dense_remove_dimension_optimizer_test_app TEST - SOURCES - dense_remove_dimension_optimizer_test.cpp - DEPENDS - vespaeval -) -vespa_add_test(NAME eval_dense_remove_dimension_optimizer_test_app COMMAND eval_dense_remove_dimension_optimizer_test_app) diff --git a/eval/src/tests/tensor/dense_remove_dimension_optimizer/dense_remove_dimension_optimizer_test.cpp b/eval/src/tests/tensor/dense_remove_dimension_optimizer/dense_remove_dimension_optimizer_test.cpp deleted file mode 100644 index 69910e27b4b..00000000000 --- a/eval/src/tests/tensor/dense_remove_dimension_optimizer/dense_remove_dimension_optimizer_test.cpp +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include <vespa/vespalib/testkit/test_kit.h> -#include <vespa/eval/eval/tensor_function.h> -#include <vespa/eval/tensor/dense/dense_replace_type_function.h> -#include <vespa/eval/tensor/dense/dense_fast_rename_optimizer.h> -#include <vespa/eval/eval/test/tensor_model.hpp> -#include <vespa/eval/eval/test/eval_fixture.h> - -#include <vespa/vespalib/util/stringfmt.h> -#include <vespa/vespalib/util/stash.h> - -using namespace vespalib; -using namespace vespalib::eval; -using namespace vespalib::eval::test; -using namespace vespalib::tensor; -using namespace vespalib::eval::tensor_function; - -const ValueBuilderFactory &prod_factory = FastValueBuilderFactory::get(); - -EvalFixture::ParamRepo make_params() { - return EvalFixture::ParamRepo() - .add("x1y5z1", spec({x(1),y(5),z(1)}, N())) - .add("x1y5z1f", spec(float_cells({x(1),y(5),z(1)}), N())) - .add("x1y1z1", spec({x(1),y(1),z(1)}, N())) - .add("x1y5z_m", spec({x(1),y(5),z({"a"})}, N())); -} -EvalFixture::ParamRepo param_repo = make_params(); - -void verify_optimized(const vespalib::string &expr) { - EvalFixture fixture(prod_factory, expr, param_repo, true); - EXPECT_EQUAL(fixture.result(), EvalFixture::ref(expr, param_repo)); - auto info = fixture.find_all<DenseReplaceTypeFunction>(); - EXPECT_EQUAL(info.size(), 1u); -} - -void verify_not_optimized(const vespalib::string &expr) { - EvalFixture fixture(prod_factory, expr, param_repo, true); - EXPECT_EQUAL(fixture.result(), EvalFixture::ref(expr, param_repo)); - auto info = fixture.find_all<DenseReplaceTypeFunction>(); - EXPECT_TRUE(info.empty()); -} - -TEST("require that dimension removal can be optimized for appropriate aggregators") { - TEST_DO(verify_optimized("reduce(x1y5z1,avg,x)")); - TEST_DO(verify_not_optimized("reduce(x1y5z1,count,x)")); // NB - TEST_DO(verify_optimized("reduce(x1y5z1,prod,x)")); - TEST_DO(verify_optimized("reduce(x1y5z1,sum,x)")); - TEST_DO(verify_optimized("reduce(x1y5z1,max,x)")); - TEST_DO(verify_optimized("reduce(x1y5z1,min,x)")); -} - -TEST("require that multi-dimension removal can be optimized") { - TEST_DO(verify_optimized("reduce(x1y5z1,sum,x,z)")); -} - -TEST("require that chained dimension removal can be optimized (and compacted)") { - TEST_DO(verify_optimized("reduce(reduce(x1y5z1,sum,x),sum,z)")); -} - -TEST("require that reducing non-trivial dimension is not optimized") { - TEST_DO(verify_not_optimized("reduce(x1y5z1,sum,y)")); - TEST_DO(verify_not_optimized("reduce(x1y5z1,sum,x,y)")); - TEST_DO(verify_not_optimized("reduce(x1y5z1,sum,y,z)")); -} - -TEST("require that full reduce is not optimized") { - TEST_DO(verify_not_optimized("reduce(x1y1z1,sum)")); - TEST_DO(verify_not_optimized("reduce(x1y1z1,sum,x,y,z)")); -} - -TEST("require that inappropriate tensor types cannot be optimized") { - TEST_DO(verify_not_optimized("reduce(x1y5z_m,sum,x)")); - TEST_DO(verify_not_optimized("reduce(x1y5z_m,sum,z)")); -} - -TEST("require that optimization works for float cells") { - TEST_DO(verify_optimized("reduce(x1y5z1f,avg,x)")); -} - -TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/eval/src/tests/tensor/dense_replace_type_function/CMakeLists.txt b/eval/src/tests/tensor/dense_replace_type_function/CMakeLists.txt deleted file mode 100644 index dd4a8a58082..00000000000 --- a/eval/src/tests/tensor/dense_replace_type_function/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -vespa_add_executable(eval_dense_replace_type_function_test_app TEST - SOURCES - dense_replace_type_function_test.cpp - DEPENDS - vespaeval -) -vespa_add_test(NAME eval_dense_replace_type_function_test_app COMMAND eval_dense_replace_type_function_test_app) diff --git a/eval/src/tests/tensor/dense_replace_type_function/dense_replace_type_function_test.cpp b/eval/src/tests/tensor/dense_replace_type_function/dense_replace_type_function_test.cpp deleted file mode 100644 index 2612869e72f..00000000000 --- a/eval/src/tests/tensor/dense_replace_type_function/dense_replace_type_function_test.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include <vespa/vespalib/testkit/test_kit.h> -#include <vespa/eval/eval/fast_value.h> -#include <vespa/eval/eval/value_codec.h> -#include <vespa/eval/eval/interpreted_function.h> -#include <vespa/eval/tensor/dense/dense_replace_type_function.h> -#include <vespa/eval/eval/test/tensor_model.hpp> - -using namespace vespalib::eval::tensor_function; -using namespace vespalib::eval::test; -using namespace vespalib::eval; -using namespace vespalib::tensor; -using namespace vespalib; - -const ValueBuilderFactory &prod_factory = FastValueBuilderFactory::get(); - -TypedCells getCellsRef(const eval::Value &value) { - return value.cells(); -} - -struct ChildMock : Leaf { - bool is_mutable; - ChildMock(const ValueType &type) : Leaf(type), is_mutable(true) {} - bool result_is_mutable() const override { return is_mutable; } - InterpretedFunction::Instruction compile_self(const ValueBuilderFactory &, Stash &) const override { abort(); } -}; - -struct Fixture { - Value::UP my_value; - ValueType new_type; - ChildMock mock_child; - DenseReplaceTypeFunction my_fun; - std::vector<TensorFunction::Child::CREF> children; - InterpretedFunction::State state; - Fixture() - : my_value(value_from_spec(spec({x(10)}, N()), prod_factory)), - new_type(ValueType::from_spec("tensor(x[5],y[2])")), - mock_child(my_value->type()), - my_fun(new_type, mock_child), - children(), - state(prod_factory) - { - my_fun.push_children(children); - state.stack.push_back(*my_value); - my_fun.compile_self(prod_factory, state.stash).perform(state); - ASSERT_EQUAL(children.size(), 1u); - ASSERT_EQUAL(state.stack.size(), 1u); - ASSERT_TRUE(!new_type.is_error()); - } -}; - -TEST_F("require that DenseReplaceTypeFunction works as expected", Fixture()) { - EXPECT_EQUAL(f1.my_fun.result_type(), f1.new_type); - EXPECT_EQUAL(f1.my_fun.result_is_mutable(), true); - f1.mock_child.is_mutable = false; - EXPECT_EQUAL(f1.my_fun.result_is_mutable(), false); - EXPECT_EQUAL(&f1.children[0].get().get(), &f1.mock_child); - EXPECT_EQUAL(getCellsRef(f1.state.stack[0]).data, getCellsRef(*f1.my_value).data); - EXPECT_EQUAL(getCellsRef(f1.state.stack[0]).size, getCellsRef(*f1.my_value).size); - EXPECT_EQUAL(f1.state.stack[0].get().type(), f1.new_type); - fprintf(stderr, "%s\n", f1.my_fun.as_string().c_str()); -} - -TEST("require that create_compact will collapse duplicate replace operations") { - Stash stash; - ValueType type = ValueType::double_type(); - ChildMock leaf(type); - const DenseReplaceTypeFunction &a = DenseReplaceTypeFunction::create_compact(type, leaf, stash); - const DenseReplaceTypeFunction &b = DenseReplaceTypeFunction::create_compact(type, a, stash); - EXPECT_EQUAL(a.result_type(), type); - EXPECT_EQUAL(&a.child(), &leaf); - EXPECT_EQUAL(b.result_type(), type); - EXPECT_EQUAL(&b.child(), &leaf); -} - -TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/eval/src/tests/tensor/dense_simple_join_function/CMakeLists.txt b/eval/src/tests/tensor/dense_simple_join_function/CMakeLists.txt deleted file mode 100644 index 8a2df392145..00000000000 --- a/eval/src/tests/tensor/dense_simple_join_function/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -vespa_add_executable(eval_dense_simple_join_function_test_app TEST - SOURCES - dense_simple_join_function_test.cpp - DEPENDS - vespaeval -) -vespa_add_test(NAME eval_dense_simple_join_function_test_app COMMAND eval_dense_simple_join_function_test_app) diff --git a/eval/src/tests/tensor/dense_simple_join_function/dense_simple_join_function_test.cpp b/eval/src/tests/tensor/dense_simple_join_function/dense_simple_join_function_test.cpp deleted file mode 100644 index 6ad60d2e3f5..00000000000 --- a/eval/src/tests/tensor/dense_simple_join_function/dense_simple_join_function_test.cpp +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include <vespa/vespalib/testkit/test_kit.h> -#include <vespa/eval/eval/tensor_function.h> -#include <vespa/eval/tensor/dense/dense_simple_join_function.h> -#include <vespa/eval/eval/test/eval_fixture.h> -#include <vespa/eval/eval/test/tensor_model.hpp> - -#include <vespa/vespalib/util/stringfmt.h> - -using namespace vespalib; -using namespace vespalib::eval; -using namespace vespalib::eval::test; -using namespace vespalib::tensor; -using namespace vespalib::eval::tensor_function; - -using vespalib::make_string_short::fmt; - -using Primary = DenseSimpleJoinFunction::Primary; -using Overlap = DenseSimpleJoinFunction::Overlap; - -namespace vespalib::tensor { - -std::ostream &operator<<(std::ostream &os, Primary primary) -{ - switch(primary) { - case Primary::LHS: return os << "LHS"; - case Primary::RHS: return os << "RHS"; - } - abort(); -} - -std::ostream &operator<<(std::ostream &os, Overlap overlap) -{ - switch(overlap) { - case Overlap::FULL: return os << "FULL"; - case Overlap::INNER: return os << "INNER"; - case Overlap::OUTER: return os << "OUTER"; - } - abort(); -} - -} - -const ValueBuilderFactory &prod_factory = FastValueBuilderFactory::get(); - -EvalFixture::ParamRepo make_params() { - return EvalFixture::ParamRepo() - .add("a", spec(1.5)) - .add("b", spec(2.5)) - .add("sparse", spec({x({"a"})}, N())) - .add("mixed", spec({x({"a"}),y(5)}, N())) - .add_cube("a", 1, "b", 1, "c", 1) - .add_cube("x", 1, "y", 1, "z", 1) - .add_cube("x", 3, "y", 5, "z", 3) - .add_vector("x", 5) - .add_dense({{"c", 5}, {"d", 1}}) - .add_dense({{"b", 1}, {"c", 5}}) - .add_matrix("x", 3, "y", 5, [](size_t idx) noexcept { return double((idx * 2) + 3); }) - .add_matrix("x", 3, "y", 5, [](size_t idx) noexcept { return double((idx * 3) + 2); }) - .add_vector("y", 5, [](size_t idx) noexcept { return double((idx * 2) + 3); }) - .add_vector("y", 5, [](size_t idx) noexcept { return double((idx * 3) + 2); }) - .add_matrix("y", 5, "z", 3, [](size_t idx) noexcept { return double((idx * 2) + 3); }) - .add_matrix("y", 5, "z", 3, [](size_t idx) noexcept { return double((idx * 3) + 2); }); -} -EvalFixture::ParamRepo param_repo = make_params(); - -void verify_optimized(const vespalib::string &expr, Primary primary, Overlap overlap, bool pri_mut, size_t factor, int p_inplace = -1) { - EvalFixture slow_fixture(prod_factory, expr, param_repo, false); - EvalFixture fixture(prod_factory, expr, param_repo, true, true); - EXPECT_EQUAL(fixture.result(), EvalFixture::ref(expr, param_repo)); - EXPECT_EQUAL(fixture.result(), slow_fixture.result()); - auto info = fixture.find_all<DenseSimpleJoinFunction>(); - ASSERT_EQUAL(info.size(), 1u); - EXPECT_TRUE(info[0]->result_is_mutable()); - EXPECT_EQUAL(info[0]->primary(), primary); - EXPECT_EQUAL(info[0]->overlap(), overlap); - EXPECT_EQUAL(info[0]->primary_is_mutable(), pri_mut); - EXPECT_EQUAL(info[0]->factor(), factor); - EXPECT_TRUE((p_inplace == -1) || (fixture.num_params() > size_t(p_inplace))); - for (size_t i = 0; i < fixture.num_params(); ++i) { - if (i == size_t(p_inplace)) { - EXPECT_EQUAL(fixture.get_param(i), fixture.result()); - } else { - EXPECT_NOT_EQUAL(fixture.get_param(i), fixture.result()); - } - } -} - -void verify_not_optimized(const vespalib::string &expr) { - EvalFixture slow_fixture(prod_factory, expr, param_repo, false); - EvalFixture fixture(prod_factory, expr, param_repo, true); - EXPECT_EQUAL(fixture.result(), EvalFixture::ref(expr, param_repo)); - EXPECT_EQUAL(fixture.result(), slow_fixture.result()); - auto info = fixture.find_all<DenseSimpleJoinFunction>(); - EXPECT_TRUE(info.empty()); -} - -TEST("require that basic join is optimized") { - TEST_DO(verify_optimized("y5+y5$2", Primary::RHS, Overlap::FULL, false, 1)); -} - -TEST("require that unit join is optimized") { - TEST_DO(verify_optimized("a1b1c1+x1y1z1", Primary::RHS, Overlap::FULL, false, 1)); -} - -TEST("require that trivial dimensions do not affect overlap calculation") { - TEST_DO(verify_optimized("c5d1+b1c5", Primary::RHS, Overlap::FULL, false, 1)); -} - -TEST("require that outer nesting is preferred to inner nesting") { - TEST_DO(verify_optimized("a1b1c1+y5", Primary::RHS, Overlap::OUTER, false, 5)); -} - -TEST("require that non-subset join is not optimized") { - TEST_DO(verify_not_optimized("x5+y5")); -} - -TEST("require that subset join with complex overlap is not optimized") { - TEST_DO(verify_not_optimized("x3y5z3+y5")); -} - -struct LhsRhs { - vespalib::string lhs; - vespalib::string rhs; - size_t lhs_size; - size_t rhs_size; - Overlap overlap; - size_t factor; - LhsRhs(const vespalib::string &lhs_in, const vespalib::string &rhs_in, - size_t lhs_size_in, size_t rhs_size_in, Overlap overlap_in) noexcept - : lhs(lhs_in), rhs(rhs_in), lhs_size(lhs_size_in), rhs_size(rhs_size_in), overlap(overlap_in), factor(1) - { - if (lhs_size > rhs_size) { - ASSERT_EQUAL(lhs_size % rhs_size, 0u); - factor = (lhs_size / rhs_size); - } else { - ASSERT_EQUAL(rhs_size % lhs_size, 0u); - factor = (rhs_size / lhs_size); - } - } -}; - -vespalib::string adjust_param(const vespalib::string &str, bool float_cells, bool mut_cells, bool is_rhs) { - vespalib::string result = str; - if (mut_cells) { - result = "@" + result; - } - if (float_cells) { - result += "f"; - } - if (is_rhs) { - result += "$2"; - } - return result; -} - -TEST("require that various parameter combinations work") { - for (bool left_float: {false, true}) { - for (bool right_float: {false, true}) { - bool float_result = (left_float && right_float); - for (bool left_mut: {false, true}) { - for (bool right_mut: {false, true}) { - for (const char *op_pattern: {"%s+%s", "%s-%s", "%s*%s"}) { - for (const LhsRhs ¶ms: - { LhsRhs("y5", "y5", 5, 5, Overlap::FULL), - LhsRhs("y5", "x3y5", 5, 15, Overlap::INNER), - LhsRhs("y5", "y5z3", 5, 15, Overlap::OUTER), - LhsRhs("x3y5", "y5", 15, 5, Overlap::INNER), - LhsRhs("y5z3", "y5", 15, 5, Overlap::OUTER)}) - { - vespalib::string left = adjust_param(params.lhs, left_float, left_mut, false); - vespalib::string right = adjust_param(params.rhs, right_float, right_mut, true); - vespalib::string expr = fmt(op_pattern, left.c_str(), right.c_str()); - TEST_STATE(expr.c_str()); - Primary primary = Primary::RHS; - if (params.overlap == Overlap::FULL) { - bool w_lhs = ((left_float == float_result) && left_mut); - bool w_rhs = ((right_float == float_result) && right_mut); - if (w_lhs && !w_rhs) { - primary = Primary::LHS; - } - } else if (params.lhs_size > params.rhs_size) { - primary = Primary::LHS; - } - bool pri_mut = (primary == Primary::LHS) ? left_mut : right_mut; - bool pri_float = (primary == Primary::LHS) ? left_float : right_float; - int p_inplace = -1; - if (pri_mut && (pri_float == float_result)) { - p_inplace = (primary == Primary::LHS) ? 0 : 1; - } - verify_optimized(expr, primary, params.overlap, pri_mut, params.factor, p_inplace); - } - } - } - } - } - } -} - -TEST("require that scalar values are not optimized") { - TEST_DO(verify_not_optimized("a+b")); - TEST_DO(verify_not_optimized("a+y5")); - TEST_DO(verify_not_optimized("y5+b")); - TEST_DO(verify_not_optimized("a+sparse")); - TEST_DO(verify_not_optimized("sparse+a")); - TEST_DO(verify_not_optimized("a+mixed")); - TEST_DO(verify_not_optimized("mixed+a")); -} - -TEST("require that mapped tensors are not optimized") { - TEST_DO(verify_not_optimized("sparse+sparse")); - TEST_DO(verify_not_optimized("sparse+y5")); - TEST_DO(verify_not_optimized("y5+sparse")); - TEST_DO(verify_not_optimized("sparse+mixed")); - TEST_DO(verify_not_optimized("mixed+sparse")); -} - -TEST("require mixed tensors are not optimized") { - TEST_DO(verify_not_optimized("mixed+mixed")); - TEST_DO(verify_not_optimized("mixed+y5")); - TEST_DO(verify_not_optimized("y5+mixed")); -} - -TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/eval/src/tests/tensor/dense_simple_map_function/CMakeLists.txt b/eval/src/tests/tensor/dense_simple_map_function/CMakeLists.txt deleted file mode 100644 index 8d3bb8c92aa..00000000000 --- a/eval/src/tests/tensor/dense_simple_map_function/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -vespa_add_executable(eval_dense_simple_map_function_test_app TEST - SOURCES - dense_simple_map_function_test.cpp - DEPENDS - vespaeval - GTest::GTest -) -vespa_add_test(NAME eval_dense_simple_map_function_test_app COMMAND eval_dense_simple_map_function_test_app) diff --git a/eval/src/tests/tensor/dense_simple_map_function/dense_simple_map_function_test.cpp b/eval/src/tests/tensor/dense_simple_map_function/dense_simple_map_function_test.cpp deleted file mode 100644 index 53164ad59c8..00000000000 --- a/eval/src/tests/tensor/dense_simple_map_function/dense_simple_map_function_test.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include <vespa/eval/eval/tensor_function.h> -#include <vespa/eval/tensor/dense/dense_simple_map_function.h> -#include <vespa/eval/eval/test/eval_fixture.h> -#include <vespa/eval/eval/test/tensor_model.hpp> -#include <vespa/vespalib/gtest/gtest.h> - -using namespace vespalib; -using namespace vespalib::eval; -using namespace vespalib::eval::test; -using namespace vespalib::eval::tensor_function; -using namespace vespalib::tensor; - -const ValueBuilderFactory &prod_factory = FastValueBuilderFactory::get(); - -EvalFixture::ParamRepo make_params() { - return EvalFixture::ParamRepo() - .add("a", spec(1.5)) - .add("b", spec(2.5)) - .add("sparse", spec({x({"a"})}, N())) - .add("mixed", spec({x({"a"}),y(5)}, N())) - .add_matrix("x", 5, "y", 3); -} -EvalFixture::ParamRepo param_repo = make_params(); - -void verify_optimized(const vespalib::string &expr, bool inplace) { - EvalFixture slow_fixture(prod_factory, expr, param_repo, false); - EvalFixture fixture(prod_factory, expr, param_repo, true, true); - EXPECT_EQ(fixture.result(), EvalFixture::ref(expr, param_repo)); - EXPECT_EQ(fixture.result(), slow_fixture.result()); - auto info = fixture.find_all<DenseSimpleMapFunction>(); - ASSERT_EQ(info.size(), 1u); - EXPECT_TRUE(info[0]->result_is_mutable()); - EXPECT_EQ(info[0]->inplace(), inplace); - ASSERT_EQ(fixture.num_params(), 1); - if (inplace) { - EXPECT_EQ(fixture.get_param(0), fixture.result()); - } else { - EXPECT_TRUE(!(fixture.get_param(0) == fixture.result())); - } -} - -void verify_not_optimized(const vespalib::string &expr) { - EvalFixture slow_fixture(prod_factory, expr, param_repo, false); - EvalFixture fixture(prod_factory, expr, param_repo, true); - EXPECT_EQ(fixture.result(), EvalFixture::ref(expr, param_repo)); - EXPECT_EQ(fixture.result(), slow_fixture.result()); - auto info = fixture.find_all<DenseSimpleMapFunction>(); - EXPECT_TRUE(info.empty()); -} - -TEST(MapTest, dense_map_is_optimized) { - verify_optimized("map(x5y3,f(x)(x+10))", false); - verify_optimized("map(x5y3f,f(x)(x+10))", false); -} - -TEST(MapTest, simple_dense_map_can_be_inplace) { - verify_optimized("map(@x5y3,f(x)(x+10))", true); - verify_optimized("map(@x5y3f,f(x)(x+10))", true); -} - -TEST(MapTest, scalar_map_is_not_optimized) { - verify_not_optimized("map(a,f(x)(x+10))"); -} - -TEST(MapTest, sparse_map_is_not_optimized) { - verify_not_optimized("map(sparse,f(x)(x+10))"); -} - -TEST(MapTest, mixed_map_is_not_optimized) { - verify_not_optimized("map(mixed,f(x)(x+10))"); -} - -GTEST_MAIN_RUN_ALL_TESTS() diff --git a/eval/src/tests/tensor/dense_single_reduce_function/CMakeLists.txt b/eval/src/tests/tensor/dense_single_reduce_function/CMakeLists.txt deleted file mode 100644 index 42b00699c31..00000000000 --- a/eval/src/tests/tensor/dense_single_reduce_function/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -vespa_add_executable(eval_dense_single_reduce_function_test_app TEST - SOURCES - dense_single_reduce_function_test.cpp - DEPENDS - vespaeval -) -vespa_add_test(NAME eval_dense_single_reduce_function_test_app COMMAND eval_dense_single_reduce_function_test_app) diff --git a/eval/src/tests/tensor/dense_single_reduce_function/dense_single_reduce_function_test.cpp b/eval/src/tests/tensor/dense_single_reduce_function/dense_single_reduce_function_test.cpp deleted file mode 100644 index 347228269cf..00000000000 --- a/eval/src/tests/tensor/dense_single_reduce_function/dense_single_reduce_function_test.cpp +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include <vespa/vespalib/testkit/test_kit.h> -#include <vespa/eval/eval/tensor_function.h> -#include <vespa/eval/eval/operation.h> -#include <vespa/eval/tensor/dense/dense_single_reduce_function.h> -#include <vespa/eval/eval/test/tensor_model.hpp> -#include <vespa/eval/eval/test/eval_fixture.h> - -#include <vespa/vespalib/util/stringfmt.h> -#include <vespa/vespalib/util/stash.h> - -using namespace vespalib; -using namespace vespalib::eval; -using namespace vespalib::eval::test; -using namespace vespalib::tensor; -using namespace vespalib::eval::tensor_function; - -const ValueBuilderFactory &prod_factory = FastValueBuilderFactory::get(); - -EvalFixture::ParamRepo make_params() { - return EvalFixture::ParamRepo() - .add_dense({{"a", 2}, {"b", 3}, {"c", 4}, {"d", 5}}) - .add_dense({{"a", 9}, {"b", 9}, {"c", 9}, {"d", 9}}) - .add_cube("a", 2, "b", 1, "c", 1) - .add_cube("a", 1, "b", 2, "c", 1) - .add_cube("a", 1, "b", 1, "c", 2) - .add_cube("a", 1, "b", 1, "c", 1) - .add_vector("a", 10) - .add("xy_mapped", spec({x({"a", "b"}),y({"x", "y"})}, N())) - .add("xyz_mixed", spec({x({"a", "b"}),y({"x", "y"}),z(3)}, N())); -} -EvalFixture::ParamRepo param_repo = make_params(); - -struct ReduceSpec { - size_t outer_size; - size_t reduce_size; - size_t inner_size; - Aggr aggr; -}; - -void verify_optimized_impl(const vespalib::string &expr, const std::vector<ReduceSpec> &spec_list) { - EvalFixture slow_fixture(prod_factory, expr, param_repo, false); - EvalFixture fixture(prod_factory, expr, param_repo, true); - EXPECT_EQUAL(fixture.result(), EvalFixture::ref(expr, param_repo)); - EXPECT_EQUAL(fixture.result(), slow_fixture.result()); - auto info = fixture.find_all<DenseSingleReduceFunction>(); - ASSERT_EQUAL(info.size(), spec_list.size()); - for (size_t i = 0; i < spec_list.size(); ++i) { - EXPECT_TRUE(info[i]->result_is_mutable()); - EXPECT_EQUAL(info[i]->outer_size(), spec_list[i].outer_size); - EXPECT_EQUAL(info[i]->reduce_size(), spec_list[i].reduce_size); - EXPECT_EQUAL(info[i]->inner_size(), spec_list[i].inner_size); - EXPECT_EQUAL(int(info[i]->aggr()), int(spec_list[i].aggr)); - } -} - -void verify_optimized(const vespalib::string &expr, const ReduceSpec &spec) { - verify_optimized_impl(expr, {spec}); -} - -void verify_optimized(const vespalib::string &expr, const ReduceSpec &spec1, const ReduceSpec &spec2) { - verify_optimized_impl(expr, {spec1, spec2}); -} - -void verify_not_optimized(const vespalib::string &expr) { - EvalFixture slow_fixture(prod_factory, expr, param_repo, false); - EvalFixture fixture(prod_factory, expr, param_repo, true); - EXPECT_EQUAL(fixture.result(), EvalFixture::ref(expr, param_repo)); - EXPECT_EQUAL(fixture.result(), slow_fixture.result()); - auto info = fixture.find_all<DenseSingleReduceFunction>(); - EXPECT_TRUE(info.empty()); -} - -TEST("require that reduce to scalar is not optimized") { - TEST_DO(verify_not_optimized("reduce(a10,sum,a)")); - TEST_DO(verify_not_optimized("reduce(a10,sum)")); -} - -TEST("require that sparse reduce is not optimized") { - TEST_DO(verify_not_optimized("reduce(xy_mapped,sum,x)")); - TEST_DO(verify_not_optimized("reduce(xy_mapped,sum,y)")); -} - -TEST("require that mixed reduce is not optimized") { - TEST_DO(verify_not_optimized("reduce(xyz_mixed,sum,x)")); - TEST_DO(verify_not_optimized("reduce(xyz_mixed,sum,y)")); - TEST_DO(verify_not_optimized("reduce(xyz_mixed,sum,z)")); -} - -TEST("require that reducing trivial dimensions is not optimized") { - TEST_DO(verify_not_optimized("reduce(a1b1c1,avg,c)")); - TEST_DO(verify_not_optimized("reduce(a1b1c1,count,c)")); - TEST_DO(verify_not_optimized("reduce(a1b1c1,prod,c)")); - TEST_DO(verify_not_optimized("reduce(a1b1c1,sum,c)")); - TEST_DO(verify_not_optimized("reduce(a1b1c1,max,c)")); - TEST_DO(verify_not_optimized("reduce(a1b1c1,median,c)")); - TEST_DO(verify_not_optimized("reduce(a1b1c1,min,c)")); -} - -TEST("require that atleast_8 dense single reduce works") { - TEST_DO(verify_optimized("reduce(a9b9c9d9,avg,a)", {1, 9, 729, Aggr::AVG})); - TEST_DO(verify_optimized("reduce(a9b9c9d9,avg,b)", {9, 9, 81, Aggr::AVG})); - TEST_DO(verify_optimized("reduce(a9b9c9d9,avg,c)", {81, 9, 9, Aggr::AVG})); - TEST_DO(verify_optimized("reduce(a9b9c9d9,avg,d)", {729, 9, 1, Aggr::AVG})); - TEST_DO(verify_optimized("reduce(a9b9c9d9,sum,c,d)", {81, 81, 1, Aggr::SUM})); -} - -TEST("require that simple aggregators can be decomposed into multiple reduce operations") { - TEST_DO(verify_optimized("reduce(a2b3c4d5,sum,a,c)", {3, 4, 5, Aggr::SUM}, {1, 2, 60, Aggr::SUM})); - TEST_DO(verify_optimized("reduce(a2b3c4d5,min,a,c)", {3, 4, 5, Aggr::MIN}, {1, 2, 60, Aggr::MIN})); - TEST_DO(verify_optimized("reduce(a2b3c4d5,max,a,c)", {3, 4, 5, Aggr::MAX}, {1, 2, 60, Aggr::MAX})); -} - -TEST("require that reduce dimensions can be listed in reverse order") { - TEST_DO(verify_optimized("reduce(a2b3c4d5,sum,c,a)", {3, 4, 5, Aggr::SUM}, {1, 2, 60, Aggr::SUM})); - TEST_DO(verify_optimized("reduce(a2b3c4d5,min,c,a)", {3, 4, 5, Aggr::MIN}, {1, 2, 60, Aggr::MIN})); - TEST_DO(verify_optimized("reduce(a2b3c4d5,max,c,a)", {3, 4, 5, Aggr::MAX}, {1, 2, 60, Aggr::MAX})); -} - -TEST("require that non-simple aggregators cannot be decomposed into multiple reduce operations") { - TEST_DO(verify_not_optimized("reduce(a2b3c4d5,avg,a,c)")); - TEST_DO(verify_not_optimized("reduce(a2b3c4d5,count,a,c)")); - TEST_DO(verify_not_optimized("reduce(a2b3c4d5,median,a,c)")); -} - -vespalib::string make_expr(const vespalib::string &arg, const vespalib::string &dim, bool float_cells, Aggr aggr) { - return make_string("reduce(%s%s,%s,%s)", arg.c_str(), float_cells ? "f" : "", AggrNames::name_of(aggr)->c_str(), dim.c_str()); -} - -void verify_optimized_multi(const vespalib::string &arg, const vespalib::string &dim, size_t outer_size, size_t reduce_size, size_t inner_size) { - for (bool float_cells: {false, true}) { - for (Aggr aggr: Aggregator::list()) { - if (aggr != Aggr::PROD) { - auto expr = make_expr(arg, dim, float_cells, aggr); - TEST_DO(verify_optimized(expr, {outer_size, reduce_size, inner_size, aggr})); - } - } - } -} - -TEST("require that normal dense single reduce works") { - TEST_DO(verify_optimized_multi("a2b3c4d5", "a", 1, 2, 60)); - TEST_DO(verify_optimized_multi("a2b3c4d5", "b", 2, 3, 20)); - TEST_DO(verify_optimized_multi("a2b3c4d5", "c", 6, 4, 5)); - TEST_DO(verify_optimized_multi("a2b3c4d5", "d", 24, 5, 1)); -} - -TEST("require that dimension-combined dense single reduce works") { - TEST_DO(verify_optimized_multi("a2b3c4d5", "a,b", 1, 6, 20)); - TEST_DO(verify_optimized_multi("a2b3c4d5", "b,c", 2, 12, 5)); - TEST_DO(verify_optimized_multi("a2b3c4d5", "c,d", 6, 20, 1)); -} - -TEST("require that minimal dense single reduce works") { - TEST_DO(verify_optimized_multi("a2b1c1", "a", 1, 2, 1)); - TEST_DO(verify_optimized_multi("a1b2c1", "b", 1, 2, 1)); - TEST_DO(verify_optimized_multi("a1b1c2", "c", 1, 2, 1)); -} - -TEST("require that trivial dimensions can be trivially reduced") { - TEST_DO(verify_optimized_multi("a2b1c1", "a,b", 1, 2, 1)); - TEST_DO(verify_optimized_multi("a2b1c1", "a,c", 1, 2, 1)); - TEST_DO(verify_optimized_multi("a1b2c1", "b,a", 1, 2, 1)); - TEST_DO(verify_optimized_multi("a1b2c1", "b,c", 1, 2, 1)); - TEST_DO(verify_optimized_multi("a1b1c2", "c,a", 1, 2, 1)); - TEST_DO(verify_optimized_multi("a1b1c2", "c,b", 1, 2, 1)); -} - -TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/eval/src/tests/tensor/dense_tensor_create_function/CMakeLists.txt b/eval/src/tests/tensor/dense_tensor_create_function/CMakeLists.txt deleted file mode 100644 index 883f331bda8..00000000000 --- a/eval/src/tests/tensor/dense_tensor_create_function/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -vespa_add_executable(eval_dense_tensor_create_function_test_app TEST - SOURCES - dense_tensor_create_function_test.cpp - DEPENDS - vespaeval -) -vespa_add_test(NAME eval_dense_tensor_create_function_test_app COMMAND eval_dense_tensor_create_function_test_app) diff --git a/eval/src/tests/tensor/dense_tensor_create_function/dense_tensor_create_function_test.cpp b/eval/src/tests/tensor/dense_tensor_create_function/dense_tensor_create_function_test.cpp deleted file mode 100644 index edf999e97b3..00000000000 --- a/eval/src/tests/tensor/dense_tensor_create_function/dense_tensor_create_function_test.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include <vespa/vespalib/testkit/test_kit.h> -#include <vespa/eval/eval/tensor_function.h> -#include <vespa/eval/tensor/dense/dense_tensor_create_function.h> -#include <vespa/eval/eval/test/tensor_model.hpp> -#include <vespa/eval/eval/test/eval_fixture.h> - -#include <vespa/vespalib/util/stringfmt.h> -#include <vespa/vespalib/util/stash.h> - -using namespace vespalib; -using namespace vespalib::eval; -using namespace vespalib::eval::test; -using namespace vespalib::tensor; -using namespace vespalib::eval::tensor_function; - -const ValueBuilderFactory &prod_factory = FastValueBuilderFactory::get(); - -EvalFixture::ParamRepo make_params() { - return EvalFixture::ParamRepo() - .add("a", spec(1.0)) - .add("b", spec(2.0)) - .add("c", spec(3.0)); -} -EvalFixture::ParamRepo param_repo = make_params(); - -void verify(const vespalib::string &expr, size_t expect_optimized_cnt, size_t expect_not_optimized_cnt) { - EvalFixture fixture(prod_factory, expr, param_repo, true); - EXPECT_EQUAL(fixture.result(), EvalFixture::ref(expr, param_repo)); - auto info = fixture.find_all<DenseTensorCreateFunction>(); - EXPECT_EQUAL(info.size(), expect_optimized_cnt); - for (size_t i = 0; i < info.size(); ++i) { - EXPECT_TRUE(info[i]->result_is_mutable()); - } - EXPECT_EQUAL(fixture.find_all<Create>().size(), expect_not_optimized_cnt); -} - -//----------------------------------------------------------------------------- - -TEST("require that tensor create can be optimized") { - TEST_DO(verify("tensor(x[3]):{{x:0}:1,{x:1}:2,{x:2}:3}", 0, 0)); // NB: const value - TEST_DO(verify("tensor(x[3]):{{x:0}:a,{x:1}:b,{x:2}:c}", 1, 0)); - TEST_DO(verify("tensor<float>(x[3]):{{x:0}:a,{x:1}:b,{x:2}:c}", 1, 0)); - TEST_DO(verify("tensor(x[3]):{{x:0}:a+b,{x:1}:b-c,{x:2}:c*a}", 1, 0)); -} - -TEST("require that tensor create can be optimized with missing cells (padded with 0.0)") { - TEST_DO(verify("tensor(x[3],y[5]):{{x:0,y:1}:a,{x:1,y:3}:b,{x:2,y:4}:c}", 1, 0)); -} - -TEST("require that tensor create in not optimized for sparse tensor") { - TEST_DO(verify("tensor(x{}):{{x:0}:a,{x:1}:b,{x:2}:c}", 0, 1)); -} - -TEST("require that tensor create in not optimized for mixed tensor") { - TEST_DO(verify("tensor(x{},y[3]):{{x:a,y:0}:a,{x:a,y:1}:b,{x:a,y:2}:c}", 0, 1)); -} - -TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/eval/src/tests/tensor/direct_sparse_tensor_builder/CMakeLists.txt b/eval/src/tests/tensor/direct_sparse_tensor_builder/CMakeLists.txt deleted file mode 100644 index 00ff230fadd..00000000000 --- a/eval/src/tests/tensor/direct_sparse_tensor_builder/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -vespa_add_executable(eval_direct_sparse_tensor_builder_test_app TEST - SOURCES - direct_sparse_tensor_builder_test.cpp - DEPENDS - vespaeval -) -vespa_add_test(NAME eval_direct_sparse_tensor_builder_test_app COMMAND eval_direct_sparse_tensor_builder_test_app) diff --git a/eval/src/tests/tensor/direct_sparse_tensor_builder/direct_sparse_tensor_builder_test.cpp b/eval/src/tests/tensor/direct_sparse_tensor_builder/direct_sparse_tensor_builder_test.cpp deleted file mode 100644 index bcee6471f76..00000000000 --- a/eval/src/tests/tensor/direct_sparse_tensor_builder/direct_sparse_tensor_builder_test.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include <vespa/vespalib/testkit/test_kit.h> -#include <vespa/eval/tensor/sparse/direct_sparse_tensor_builder.h> -#include <vespa/eval/tensor/sparse/sparse_tensor_address_combiner.h> -#include <vespa/vespalib/test/insertion_operators.h> - -using namespace vespalib::tensor; -using namespace vespalib::tensor::sparse; -using vespalib::eval::TensorSpec; -using vespalib::eval::CellType; -using vespalib::eval::ValueType; - -void -assertCellValue(double expValue, const TensorAddress &address, - const ValueType &type, - const SparseTensor &tensor) -{ - SparseTensorAddressBuilder addressBuilder; - auto dimsItr = type.dimensions().cbegin(); - auto dimsItrEnd = type.dimensions().cend(); - for (const auto &element : address.elements()) { - while ((dimsItr < dimsItrEnd) && (dimsItr->name < element.dimension())) { - addressBuilder.add(""); - ++dimsItr; - } - assert((dimsItr != dimsItrEnd) && (dimsItr->name == element.dimension())); - addressBuilder.add(element.label()); - ++dimsItr; - } - while (dimsItr < dimsItrEnd) { - addressBuilder.add(""); - ++dimsItr; - } - SparseTensorAddressRef addressRef(addressBuilder.getAddressRef()); - size_t idx; - bool found = tensor.index().lookup_address(addressRef, idx); - EXPECT_TRUE(found); - auto cells = tensor.cells(); - if (EXPECT_TRUE(cells.type == CellType::DOUBLE)) { - auto arr = cells.typify<double>(); - EXPECT_EQUAL(expValue, arr[idx]); - } -} - -Tensor::UP -buildTensor() -{ - DirectSparseTensorBuilder<double> builder(ValueType::from_spec("tensor(a{},b{},c{},d{})")); - SparseTensorAddressBuilder address; - address.set({"1", "2", "", ""}); - builder.insertCell(address, 10); - address.set({"", "", "3", "4"}); - builder.insertCell(address, 20); - return builder.build(); -} - -TEST("require that tensor can be constructed") -{ - Tensor::UP tensor = buildTensor(); - const SparseTensor &sparseTensor = dynamic_cast<const SparseTensor &>(*tensor); - const ValueType &type = sparseTensor.type(); - const auto & index = sparseTensor.index(); - EXPECT_EQUAL(2u, index.size()); - assertCellValue(10, TensorAddress({{"a","1"},{"b","2"}}), type, sparseTensor); - assertCellValue(20, TensorAddress({{"c","3"},{"d","4"}}), type, sparseTensor); -} - -TEST("require that tensor can be converted to tensor spec") -{ - Tensor::UP tensor = buildTensor(); - TensorSpec expSpec("tensor(a{},b{},c{},d{})"); - expSpec.add({{"a", "1"}, {"b", "2"}, {"c", ""}, {"d", ""}}, 10). - add({{"a", ""},{"b",""},{"c", "3"}, {"d", "4"}}, 20); - TensorSpec actSpec = tensor->toSpec(); - EXPECT_EQUAL(expSpec, actSpec); -} - -TEST("require that dimensions are extracted") -{ - Tensor::UP tensor = buildTensor(); - const SparseTensor &sparseTensor = dynamic_cast<const SparseTensor &>(*tensor); - const auto &dims = sparseTensor.type().dimensions(); - EXPECT_EQUAL(4u, dims.size()); - EXPECT_EQUAL("a", dims[0].name); - EXPECT_EQUAL("b", dims[1].name); - EXPECT_EQUAL("c", dims[2].name); - EXPECT_EQUAL("d", dims[3].name); - EXPECT_EQUAL("tensor(a{},b{},c{},d{})", sparseTensor.type().to_spec()); -} - -void verifyAddressCombiner(const ValueType & a, const ValueType & b, size_t numDim, size_t numOverlapping) { - TensorAddressCombiner combiner(a, b); - EXPECT_EQUAL(numDim, combiner.numDimensions()); - EXPECT_EQUAL(numOverlapping, combiner.numOverlappingDimensions()); -} -TEST("Test sparse tensor address combiner") { - verifyAddressCombiner(ValueType::tensor_type({{"a"}}), ValueType::tensor_type({{"b"}}), 2, 0); - verifyAddressCombiner(ValueType::tensor_type({{"a"}, {"b"}}), ValueType::tensor_type({{"b"}}), 2, 1); - verifyAddressCombiner(ValueType::tensor_type({{"a"}, {"b"}}), ValueType::tensor_type({{"b"}, {"c"}}), 3, 1); - -} - -TEST("Test essential object sizes") { - EXPECT_EQUAL(16u, sizeof(SparseTensorAddressRef)); - EXPECT_EQUAL(24u, sizeof(std::pair<SparseTensorAddressRef, double>)); - EXPECT_EQUAL(32u, sizeof(vespalib::hash_node<std::pair<SparseTensorAddressRef, double>>)); - Tensor::UP tensor = buildTensor(); - size_t used = tensor->get_memory_usage().usedBytes(); - EXPECT_GREATER(used, sizeof(SparseTensor)); - EXPECT_LESS(used, 10000u); - size_t allocated = tensor->get_memory_usage().allocatedBytes(); - EXPECT_GREATER(allocated, used); - EXPECT_LESS(allocated, 50000u); - fprintf(stderr, "tensor using %zu bytes of %zu allocated\n", - used, allocated); -} - -TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/eval/src/tests/tensor/instruction_benchmark/instruction_benchmark.cpp b/eval/src/tests/tensor/instruction_benchmark/instruction_benchmark.cpp index 618715a885f..aa1da07bc91 100644 --- a/eval/src/tests/tensor/instruction_benchmark/instruction_benchmark.cpp +++ b/eval/src/tests/tensor/instruction_benchmark/instruction_benchmark.cpp @@ -48,7 +48,6 @@ using namespace vespalib; using namespace vespalib::eval; -using namespace vespalib::tensor; using namespace vespalib::eval::instruction; using vespalib::make_string_short::fmt; diff --git a/eval/src/tests/tensor/onnx_wrapper/onnx_wrapper_test.cpp b/eval/src/tests/tensor/onnx_wrapper/onnx_wrapper_test.cpp index 7e204f1ea06..b474d2458b9 100644 --- a/eval/src/tests/tensor/onnx_wrapper/onnx_wrapper_test.cpp +++ b/eval/src/tests/tensor/onnx_wrapper/onnx_wrapper_test.cpp @@ -6,7 +6,6 @@ #include <vespa/vespalib/gtest/gtest.h> using namespace vespalib::eval; -using namespace vespalib::tensor; using vespalib::make_string_short::fmt; using TensorInfo = Onnx::TensorInfo; diff --git a/eval/src/tests/tensor/tensor_address/tensor_address_test.cpp b/eval/src/tests/tensor/tensor_address/tensor_address_test.cpp index c12b7071d02..a0a062c4322 100644 --- a/eval/src/tests/tensor/tensor_address/tensor_address_test.cpp +++ b/eval/src/tests/tensor/tensor_address/tensor_address_test.cpp @@ -3,8 +3,6 @@ #include <vespa/vespalib/testkit/test_kit.h> #include <vespa/eval/tensor/tensor_address.h> -using namespace vespalib::tensor; - void assertSortOrder(const TensorAddress::Elements &exp, const TensorAddress::Elements &input) diff --git a/eval/src/tests/tensor/typed_cells/CMakeLists.txt b/eval/src/tests/tensor/typed_cells/CMakeLists.txt deleted file mode 100644 index d57ff33eda6..00000000000 --- a/eval/src/tests/tensor/typed_cells/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -vespa_add_executable(eval_typed_cells_test_app TEST - SOURCES - typed_cells_test.cpp - DEPENDS - vespaeval -) -vespa_add_test(NAME eval_typed_cells_test_app COMMAND eval_typed_cells_test_app) diff --git a/eval/src/tests/tensor/typed_cells/typed_cells_test.cpp b/eval/src/tests/tensor/typed_cells/typed_cells_test.cpp deleted file mode 100644 index ccb522fd496..00000000000 --- a/eval/src/tests/tensor/typed_cells/typed_cells_test.cpp +++ /dev/null @@ -1,622 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include <vespa/vespalib/testkit/test_kit.h> -#include <vespa/vespalib/util/arrayref.h> -#include <memory> - -using namespace vespalib; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// Low-level typed cells reference -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -enum class CellType : char { DOUBLE, FLOAT, INT }; -template <typename T> bool check_type(CellType type); -template <> bool check_type<double>(CellType type) { return (type == CellType::DOUBLE); } -template <> bool check_type<float>(CellType type) { return (type == CellType::FLOAT); } -template <> bool check_type<int>(CellType type) { return (type == CellType::INT); } - -struct TypedCells { - const void *data; - CellType type; - size_t size:56; - explicit TypedCells(ConstArrayRef<double> cells) : data(cells.begin()), type(CellType::DOUBLE), size(cells.size()) {} - explicit TypedCells(ConstArrayRef<float> cells) : data(cells.begin()), type(CellType::FLOAT), size(cells.size()) {} - explicit TypedCells(ConstArrayRef<int> cells) : data(cells.begin()), type(CellType::INT), size(cells.size()) {} - template <typename T> bool check_type() const { return ::check_type<T>(type); } - template <typename T> ConstArrayRef<T> typify() const { - assert(check_type<T>()); - return ConstArrayRef<T>((const T *)data, size); - } - template <typename T> ConstArrayRef<T> unsafe_typify() const { - return ConstArrayRef<T>((const T *)data, size); - } -}; - -TEST("require that structures are of expected size") { - EXPECT_EQUAL(sizeof(void*), 8u); - EXPECT_EQUAL(sizeof(size_t), 8u); - EXPECT_EQUAL(sizeof(CellType), 1u); - EXPECT_EQUAL(sizeof(TypedCells), 16u); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// CASE STUDY: Direct dispatch, minimal runtime type resolving -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -struct CellwiseAdd { - template <typename A, typename B, typename C> - static void call(const ConstArrayRef<A> &a, const ConstArrayRef<B> &b, const ConstArrayRef<C> &c, size_t cnt) __attribute__ ((noinline)); -}; - -template <typename A, typename B, typename C> -void CellwiseAdd::call(const ConstArrayRef<A> &a, const ConstArrayRef<B> &b, const ConstArrayRef<C> &c, size_t cnt) { - auto dst = unconstify(c); - for (size_t i = 0; i < cnt; ++i) { - dst[i] = a[i] + b[i]; - } -} - -//----------------------------------------------------------------------------- - -struct DotProduct { - template <typename A, typename B> - static double call(const ConstArrayRef<A> &a, const ConstArrayRef<B> &b, size_t cnt) __attribute__ ((noinline)); -}; - -template <typename A, typename B> -double DotProduct::call(const ConstArrayRef<A> &a, const ConstArrayRef<B> &b, size_t cnt) { - double result = 0.0; - for (size_t i = 0; i < cnt; ++i) { - result += (a[i] * b[i]); - } - return result; -} - -//----------------------------------------------------------------------------- - -struct Sum { - template <typename A> - static double call(const ConstArrayRef<A> &a) __attribute__ ((noinline)); -}; - -template <typename A> -double Sum::call(const ConstArrayRef<A> &a) { - double result = 0.0; - for (const auto &value: a) { - result += value; - } - return result; -} - -//----------------------------------------------------------------------------- - -template <typename T> -struct Typify { - template <typename... Args> - static auto typify_1(const TypedCells &a, Args &&...args) { - switch(a.type) { - case CellType::DOUBLE: return T::call(a.unsafe_typify<double>(), std::forward<Args>(args)...); - case CellType::FLOAT: return T::call(a.unsafe_typify<float>(), std::forward<Args>(args)...); - case CellType::INT: return T::call(a.unsafe_typify<int>(), std::forward<Args>(args)...); - } - abort(); - } - template <typename A, typename... Args> - static auto typify_2(A &&a, const TypedCells &b, Args &&...args) { - switch(b.type) { - case CellType::DOUBLE: return T::call(std::forward<A>(a), b.unsafe_typify<double>(), std::forward<Args>(args)...); - case CellType::FLOAT: return T::call(std::forward<A>(a), b.unsafe_typify<float>(), std::forward<Args>(args)...); - case CellType::INT: return T::call(std::forward<A>(a), b.unsafe_typify<int>(), std::forward<Args>(args)...); - } - abort(); - } - template <typename A, typename B, typename... Args> - static auto typify_3(A &&a, B &&b, const TypedCells &c, Args &&...args) { - switch(c.type) { - case CellType::DOUBLE: return T::call(std::forward<A>(a), std::forward<B>(b), c.unsafe_typify<double>(), std::forward<Args>(args)...); - case CellType::FLOAT: return T::call(std::forward<A>(a), std::forward<B>(b), c.unsafe_typify<float>(), std::forward<Args>(args)...); - case CellType::INT: return T::call(std::forward<A>(a), std::forward<B>(b), c.unsafe_typify<int>(), std::forward<Args>(args)...); - } - abort(); - } -}; - -template <typename Fun> -struct Dispatch3 { - using Self = Dispatch3<Fun>; - template <typename A, typename B, typename C, typename... Args> - static auto call(const ConstArrayRef<A> &a, const ConstArrayRef<B> &b, const ConstArrayRef<C> &c, Args &&...args) { - return Fun::call(a, b, c, std::forward<Args>(args)...); - } - template <typename A, typename B, typename... Args> - static auto call(const ConstArrayRef<A> &a, const ConstArrayRef<B> &b, const TypedCells &c, Args &&...args) { - return Typify<Self>::typify_3(a, b, c, std::forward<Args>(args)...); - } - template <typename A, typename... Args> - static auto call(const ConstArrayRef<A> &a, const TypedCells &b, const TypedCells &c, Args &&...args) { - return Typify<Self>::typify_2(a, b, c, std::forward<Args>(args)...); - } - template <typename A, typename C, typename... Args> - static auto call(const ConstArrayRef<A> &a, const TypedCells &b, const ConstArrayRef<C> &c, Args &&...args) { - return Typify<Self>::typify_2(a, b, c, std::forward<Args>(args)...); - } - template <typename... Args> - static auto call(const TypedCells &a, const TypedCells &b, const TypedCells &c, Args &&...args) { - return Typify<Self>::typify_1(a, b, c, std::forward<Args>(args)...); - } - template <typename B, typename... Args> - static auto call(const TypedCells &a, const ConstArrayRef<B> &b, const TypedCells &c, Args &&...args) { - return Typify<Self>::typify_1(a, b, c, std::forward<Args>(args)...); - } - template <typename C, typename... Args> - static auto call(const TypedCells &a, const TypedCells &b, const ConstArrayRef<C> &c, Args &&...args) { - return Typify<Self>::typify_1(a, b, c, std::forward<Args>(args)...); - } - template <typename B, typename C, typename... Args> - static auto call(const TypedCells &a, const ConstArrayRef<B> &b, const ConstArrayRef<C> &c, Args &&...args) { - return Typify<Self>::typify_1(a, b, c, std::forward<Args>(args)...); - } -}; - -template <typename Fun> -struct Dispatch2 { - using Self = Dispatch2<Fun>; - template <typename A, typename B, typename... Args> - static auto call(const ConstArrayRef<A> &a, const ConstArrayRef<B> &b, Args &&...args) { - return Fun::call(a, b, std::forward<Args>(args)...); - } - template <typename A, typename... Args> - static auto call(const ConstArrayRef<A> &a, const TypedCells &b, Args &&...args) { - return Typify<Self>::typify_2(a, b, std::forward<Args>(args)...); - } - template <typename... Args> - static auto call(const TypedCells &a, const TypedCells &b, Args &&...args) { - return Typify<Self>::typify_1(a, b, std::forward<Args>(args)...); - } - template <typename B, typename... Args> - static auto call(const TypedCells &a, const ConstArrayRef<B> &b, Args &&...args) { - return Typify<Self>::typify_1(a, b, std::forward<Args>(args)...); - } -}; - -template <typename Fun> -struct Dispatch1 { - using Self = Dispatch1<Fun>; - template <typename A, typename... Args> - static auto call(const ConstArrayRef<A> &a, Args &&...args) { - return Fun::call(a, std::forward<Args>(args)...); - } - template <typename... Args> - static auto call(const TypedCells &a, Args &&...args) { - return Typify<Self>::typify_1(a, std::forward<Args>(args)...); - } -}; - -//----------------------------------------------------------------------------- - -TEST("require that direct dispatch 'a op b -> c' works") { - std::vector<int> a({1,2,3}); - std::vector<float> b({1.5,2.5,3.5}); - std::vector<double> c(3, 0.0); - ConstArrayRef<int> a_ref(a); - ConstArrayRef<float> b_ref(b); - ConstArrayRef<double> c_ref(c); - TypedCells a_cells(a); - TypedCells b_cells(b); - TypedCells c_cells(c); - - Dispatch3<CellwiseAdd>::call(a_cells, b_cells, c_cells, 3); - Dispatch3<CellwiseAdd>::call(a_cells, b_ref, c_cells, 3); - Dispatch3<CellwiseAdd>::call(a_cells, b_cells, c_ref, 3); - Dispatch3<CellwiseAdd>::call(a_cells, b_ref, c_ref, 3); - Dispatch3<CellwiseAdd>::call(a_ref, b_cells, c_cells, 3); - Dispatch3<CellwiseAdd>::call(a_ref, b_cells, c_ref, 3); - Dispatch3<CellwiseAdd>::call(a_ref, b_ref, c_cells, 3); - Dispatch3<CellwiseAdd>::call(a_ref, b_ref, c_ref, 3); - - EXPECT_EQUAL(c[0], 2.5); - EXPECT_EQUAL(c[1], 4.5); - EXPECT_EQUAL(c[2], 6.5); -} - -TEST("require that direct dispatch 'dot product' with return value works") { - std::vector<int> a({1,2,3}); - std::vector<float> b({1.5,2.5,3.5}); - ConstArrayRef<int> a_ref(a); - ConstArrayRef<float> b_ref(b); - TypedCells a_cells(a); - TypedCells b_cells(b); - double expect = 1.5 + (2 * 2.5) + (3 * 3.5); - - EXPECT_EQUAL(expect, Dispatch2<DotProduct>::call(a_cells, b_cells, 3)); - EXPECT_EQUAL(expect, Dispatch2<DotProduct>::call(a_cells, b_ref, 3)); - EXPECT_EQUAL(expect, Dispatch2<DotProduct>::call(a_ref, b_cells, 3)); - EXPECT_EQUAL(expect, Dispatch2<DotProduct>::call(a_ref, b_ref, 3)); -} - -TEST("require that direct dispatch 'sum' with return value works") { - std::vector<int> a({1,2,3}); - ConstArrayRef<int> a_ref(a); - TypedCells a_cells(a); - double expect = (1 + 2 + 3); - - EXPECT_EQUAL(expect, Dispatch1<Sum>::call(a_cells)); - EXPECT_EQUAL(expect, Dispatch1<Sum>::call(a_ref)); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// CASE STUDY: Pre-resolved templated subclass -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -struct CellwiseAdd2 { - virtual void call(const TypedCells &a, const TypedCells &b, const TypedCells &c, size_t cnt) const = 0; - template <typename A, typename B, typename C> - static std::unique_ptr<CellwiseAdd2> create(); - virtual ~CellwiseAdd2() {} -}; - -template <typename A, typename B, typename C> -struct CellwiseAdd2Impl : CellwiseAdd2 { - void call_impl(const ConstArrayRef<A> &a, const ConstArrayRef<B> &b, const ConstArrayRef<C> &c, size_t cnt) const { - auto dst = unconstify(c); - for (size_t i = 0; i < cnt; ++i) { - dst[i] = a[i] + b[i]; - } - } - void call(const TypedCells &a, const TypedCells &b, const TypedCells &c, size_t cnt) const override { - call_impl(a.unsafe_typify<A>(), b.unsafe_typify<B>(), c.unsafe_typify<C>(), cnt); - } -}; - -template <typename A, typename B, typename C> -std::unique_ptr<CellwiseAdd2> CellwiseAdd2::create() { - return std::make_unique<CellwiseAdd2Impl<A, B, C> >(); -} - -//----------------------------------------------------------------------------- - -struct DotProduct2 { - virtual double call(const TypedCells &a, const TypedCells &b, size_t cnt) const = 0; - template <typename A, typename B> - static std::unique_ptr<DotProduct2> create(); - virtual ~DotProduct2() {} -}; - -template <typename A, typename B> -struct DotProduct2Impl : DotProduct2 { - double call_impl(const ConstArrayRef<A> &a, const ConstArrayRef<B> &b, size_t cnt) const { - double result = 0.0; - for (size_t i = 0; i < cnt; ++i) { - result += (a[i] * b[i]); - } - return result; - } - double call(const TypedCells &a, const TypedCells &b, size_t cnt) const override { - return call_impl(a.unsafe_typify<A>(), b.unsafe_typify<B>(), cnt); - } -}; - -template <typename A, typename B> -std::unique_ptr<DotProduct2> DotProduct2::create() { - return std::make_unique<DotProduct2Impl<A, B> >(); -} - -//----------------------------------------------------------------------------- - -struct Sum2 { - virtual double call(const TypedCells &a) const = 0; - template <typename A> - static std::unique_ptr<Sum2> create(); - virtual ~Sum2() {} -}; - -template <typename A> -struct Sum2Impl : Sum2 { - double call_impl(const ConstArrayRef<A> &a) const { - double result = 0.0; - for (const auto &value: a) { - result += value; - } - return result; - } - double call(const TypedCells &a) const override { - return call_impl(a.unsafe_typify<A>()); - } -}; - -template <typename A> -std::unique_ptr<Sum2> Sum2::create() { - return std::make_unique<Sum2Impl<A> >(); -} - -//----------------------------------------------------------------------------- - -template <typename T, typename... Args> -std::unique_ptr<T> create(CellType a_type) { - switch(a_type) { - case CellType::DOUBLE: return T::template create<double, Args...>(); - case CellType::FLOAT: return T::template create<float, Args...>(); - case CellType::INT: return T::template create<int, Args...>(); - } - abort(); -} - -template <typename T, typename... Args> -std::unique_ptr<T> create(CellType a_type, CellType b_type) { - switch(b_type) { - case CellType::DOUBLE: return create<T, double, Args...>(a_type); - case CellType::FLOAT: return create<T, float, Args...>(a_type); - case CellType::INT: return create<T, int, Args...>(a_type); - } - abort(); -} - -template <typename T> -std::unique_ptr<T> create(CellType a_type, CellType b_type, CellType c_type) { - switch(c_type) { - case CellType::DOUBLE: return create<T, double>(a_type, b_type); - case CellType::FLOAT: return create<T, float>(a_type, b_type); - case CellType::INT: return create<T, int>(a_type, b_type); - } - abort(); -} - -//----------------------------------------------------------------------------- - -TEST("require that pre-resolved subclass 'a op b -> c' works") { - std::vector<int> a({1,2,3}); - std::vector<float> b({1.5,2.5,3.5}); - std::vector<double> c(3, 0.0); - TypedCells a_cells(a); - TypedCells b_cells(b); - TypedCells c_cells(c); - - auto op = create<CellwiseAdd2>(a_cells.type, b_cells.type, c_cells.type); - op->call(a_cells, b_cells, c_cells, 3); - - EXPECT_EQUAL(c[0], 2.5); - EXPECT_EQUAL(c[1], 4.5); - EXPECT_EQUAL(c[2], 6.5); -} - -TEST("require that pre-resolved subclass 'dot product' with return value works") { - std::vector<int> a({1,2,3}); - std::vector<float> b({1.5,2.5,3.5}); - TypedCells a_cells(a); - TypedCells b_cells(b); - double expect = 1.5 + (2 * 2.5) + (3 * 3.5); - - auto op = create<DotProduct2>(a_cells.type, b_cells.type); - - EXPECT_EQUAL(expect, op->call(a_cells, b_cells, 3)); -} - -TEST("require that pre-resolved subclass 'sum' with return value works") { - std::vector<int> a({1,2,3}); - TypedCells a_cells(a); - double expect = (1 + 2 + 3); - - auto op = create<Sum2>(a_cells.type); - - EXPECT_EQUAL(expect, op->call(a_cells)); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// CASE STUDY: self-updating cached function pointer -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -template <typename T, typename... Args> -auto get_fun(CellType a_type) { - switch(a_type) { - case CellType::DOUBLE: return T::template get_fun<double, Args...>(); - case CellType::FLOAT: return T::template get_fun<float, Args...>(); - case CellType::INT: return T::template get_fun<int, Args...>(); - } - abort(); -} - -template <typename T, typename... Args> -auto get_fun(CellType a_type, CellType b_type) { - switch(b_type) { - case CellType::DOUBLE: return get_fun<T, double, Args...>(a_type); - case CellType::FLOAT: return get_fun<T, float, Args...>(a_type); - case CellType::INT: return get_fun<T, int, Args...>(a_type); - } - abort(); -} - -template <typename T> -auto get_fun(CellType a_type, CellType b_type, CellType c_type) { - switch(c_type) { - case CellType::DOUBLE: return get_fun<T, double>(a_type, b_type); - case CellType::FLOAT: return get_fun<T, float>(a_type, b_type); - case CellType::INT: return get_fun<T, int>(a_type, b_type); - } - abort(); -} - -//----------------------------------------------------------------------------- - -struct CellwiseAdd3 { - struct Self; - using fun_type = void (*)(const TypedCells &x, const TypedCells &y, const TypedCells &z, size_t cnt, Self &self); - template <typename A, typename B, typename C> - static fun_type get_fun(); - struct Self { - fun_type my_fun; - Self(); - }; - Self self; - void call(const TypedCells &x, const TypedCells &y, const TypedCells &z, size_t cnt) { - self.my_fun(x, y, z, cnt, self); - } -}; - -template <typename A, typename B, typename C> -void cellwise_add(const TypedCells &x, const TypedCells &y, const TypedCells &z, size_t cnt, CellwiseAdd3::Self &self) { - if (!x.check_type<A>() || !y.check_type<B>() || !z.check_type<C>()) { - auto new_fun = get_fun<CellwiseAdd3>(x.type, y.type, z.type); - self.my_fun = new_fun; - return new_fun(x, y, z, cnt, self); - } - auto a = x.unsafe_typify<A>(); - auto b = y.unsafe_typify<B>(); - auto c = z.unsafe_typify<C>(); - auto dst = unconstify(c); - for (size_t i = 0; i < cnt; ++i) { - dst[i] = a[i] + b[i]; - } -}; - -template <typename A, typename B, typename C> -CellwiseAdd3::fun_type CellwiseAdd3::get_fun() { - return cellwise_add<A, B, C>; -} - -CellwiseAdd3::Self::Self() - : my_fun(cellwise_add<double, double, double>) -{ -} - -//----------------------------------------------------------------------------- - -struct DotProduct3 { - struct Self; - using fun_type = double (*)(const TypedCells &x, const TypedCells &y, size_t cnt, Self &self); - template <typename A, typename B> - static fun_type get_fun(); - struct Self { - fun_type my_fun; - Self(); - }; - Self self; - double call(const TypedCells &x, const TypedCells &y, size_t cnt) { - return self.my_fun(x, y, cnt, self); - } -}; - -template <typename A, typename B> -double dot_product(const TypedCells &x, const TypedCells &y, size_t cnt, DotProduct3::Self &self) { - if (!x.check_type<A>() || !y.check_type<B>()) { - auto new_fun = get_fun<DotProduct3>(x.type, y.type); - self.my_fun = new_fun; - return new_fun(x, y, cnt, self); - } - auto a = x.unsafe_typify<A>(); - auto b = y.unsafe_typify<B>(); - double result = 0.0; - for (size_t i = 0; i < cnt; ++i) { - result += (a[i] * b[i]); - } - return result; -} - -template <typename A, typename B> -DotProduct3::fun_type DotProduct3::get_fun() { - return dot_product<A, B>; -} - -DotProduct3::Self::Self() - : my_fun(dot_product<double, double>) -{ -} - -//----------------------------------------------------------------------------- - -struct Sum3 { - struct Self; - using fun_type = double (*)(const TypedCells &x, Self &self); - template <typename A> - static fun_type get_fun(); - struct Self { - fun_type my_fun; - Self(); - }; - Self self; - double call(const TypedCells &x) { - return self.my_fun(x, self); - } -}; - -template <typename A> -double sum(const TypedCells &x, Sum3::Self &self) { - if (!x.check_type<A>()) { - auto new_fun = get_fun<Sum3>(x.type); - self.my_fun = new_fun; - return new_fun(x, self); - } - auto a = x.unsafe_typify<A>(); - double result = 0.0; - for (const auto &value: a) { - result += value; - } - return result; -} - -template <typename A> -Sum3::fun_type Sum3::get_fun() { - return sum<A>; -} - -Sum3::Self::Self() - : my_fun(sum<double>) -{ -} - -//----------------------------------------------------------------------------- - -TEST("require that self-updating cached function pointer 'a op b -> c' works") { - std::vector<int> a({1,2,3}); - std::vector<float> b({1.5,2.5,3.5}); - std::vector<double> c(3, 0.0); - TypedCells a_cells(a); - TypedCells b_cells(b); - TypedCells c_cells(c); - - CellwiseAdd3 op; - EXPECT_EQUAL(op.self.my_fun, (&cellwise_add<double,double,double>)); - op.call(a_cells, b_cells, c_cells, 3); - EXPECT_EQUAL(op.self.my_fun, (&cellwise_add<int,float,double>)); - EXPECT_NOT_EQUAL(op.self.my_fun, (&cellwise_add<double,double,double>)); - - EXPECT_EQUAL(c[0], 2.5); - EXPECT_EQUAL(c[1], 4.5); - EXPECT_EQUAL(c[2], 6.5); -} - -TEST("require that self-updating cached function pointer 'dot product' with return value works") { - std::vector<int> a({1,2,3}); - std::vector<float> b({1.5,2.5,3.5}); - TypedCells a_cells(a); - TypedCells b_cells(b); - double expect = 1.5 + (2 * 2.5) + (3 * 3.5); - - DotProduct3 op; - EXPECT_EQUAL(op.self.my_fun, (&dot_product<double,double>)); - EXPECT_EQUAL(expect, op.call(a_cells, b_cells, 3)); - EXPECT_EQUAL(op.self.my_fun, (&dot_product<int,float>)); - EXPECT_NOT_EQUAL(op.self.my_fun, (&dot_product<double,double>)); -} - -TEST("require that self-updating cached function pointer 'sum' with return value works") { - std::vector<int> a({1,2,3}); - TypedCells a_cells(a); - double expect = (1 + 2 + 3); - - Sum3 op; - EXPECT_EQUAL(op.self.my_fun, (&sum<double>)); - EXPECT_EQUAL(expect, op.call(a_cells)); - EXPECT_EQUAL(op.self.my_fun, (&sum<int>)); - EXPECT_NOT_EQUAL(op.self.my_fun, (&sum<double>)); -} - -TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/eval/src/tests/tensor/vector_from_doubles_function/CMakeLists.txt b/eval/src/tests/tensor/vector_from_doubles_function/CMakeLists.txt deleted file mode 100644 index 5b2e47ec498..00000000000 --- a/eval/src/tests/tensor/vector_from_doubles_function/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -vespa_add_executable(eval_vector_from_doubles_function_test_app TEST - SOURCES - vector_from_doubles_function_test.cpp - DEPENDS - vespaeval -) -vespa_add_test(NAME eval_vector_from_doubles_function_test_app COMMAND eval_vector_from_doubles_function_test_app) diff --git a/eval/src/tests/tensor/vector_from_doubles_function/vector_from_doubles_function_test.cpp b/eval/src/tests/tensor/vector_from_doubles_function/vector_from_doubles_function_test.cpp deleted file mode 100644 index c3e1f2f248e..00000000000 --- a/eval/src/tests/tensor/vector_from_doubles_function/vector_from_doubles_function_test.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include <vespa/vespalib/testkit/test_kit.h> -#include <vespa/eval/eval/tensor_function.h> -#include <vespa/eval/tensor/dense/vector_from_doubles_function.h> -#include <vespa/eval/eval/test/tensor_model.hpp> -#include <vespa/eval/eval/test/eval_fixture.h> - -#include <vespa/vespalib/util/stringfmt.h> -#include <vespa/vespalib/util/stash.h> - -using namespace vespalib; -using namespace vespalib::eval; -using namespace vespalib::eval::test; -using namespace vespalib::tensor; -using namespace vespalib::eval::tensor_function; - -const ValueBuilderFactory &prod_factory = FastValueBuilderFactory::get(); - -EvalFixture::ParamRepo make_params() { - return EvalFixture::ParamRepo() - .add("a", spec(1.0)) - .add("b", spec(2.0)) - .add("c", spec(3.0)) - .add("d", spec(4.0)) - .add("x5", spec({x(5)}, N())); -} -EvalFixture::ParamRepo param_repo = make_params(); - -void verify(const vespalib::string &expr, size_t expect_optimized_cnt, size_t expect_not_optimized_cnt) { - EvalFixture fixture(prod_factory, expr, param_repo, true); - EXPECT_EQUAL(fixture.result(), EvalFixture::ref(expr, param_repo)); - auto info = fixture.find_all<VectorFromDoublesFunction>(); - EXPECT_EQUAL(info.size(), expect_optimized_cnt); - for (size_t i = 0; i < info.size(); ++i) { - EXPECT_TRUE(info[i]->result_is_mutable()); - } - EXPECT_EQUAL(fixture.find_all<Concat>().size(), expect_not_optimized_cnt); -} - -//----------------------------------------------------------------------------- - -TEST("require that multiple concats are optimized") { - TEST_DO(verify("concat(a,b,x)", 1, 0)); - TEST_DO(verify("concat(a,concat(b,concat(c,d,x),x),x)", 1, 0)); - TEST_DO(verify("concat(concat(concat(a,b,x),c,x),d,x)", 1, 0)); - TEST_DO(verify("concat(concat(a,b,x),concat(c,d,x),x)", 1, 0)); -} - -TEST("require that concat along different dimension is not optimized") { - TEST_DO(verify("concat(concat(a,b,x),concat(c,d,x),y)", 2, 1)); -} - -TEST("require that concat of vector and double is not optimized") { - TEST_DO(verify("concat(a,x5,x)", 0, 1)); - TEST_DO(verify("concat(x5,b,x)", 0, 1)); -} - -TEST_MAIN() { TEST_RUN_ALL(); } |