summaryrefslogtreecommitdiffstats
path: root/eval/src/tests/tensor
diff options
context:
space:
mode:
Diffstat (limited to 'eval/src/tests/tensor')
-rw-r--r--eval/src/tests/tensor/dense_matmul_function/dense_matmul_function_test.cpp2
-rw-r--r--eval/src/tests/tensor/dense_multi_matmul_function/dense_multi_matmul_function_test.cpp2
-rw-r--r--eval/src/tests/tensor/dense_pow_as_map_optimizer/CMakeLists.txt9
-rw-r--r--eval/src/tests/tensor/dense_pow_as_map_optimizer/dense_pow_as_map_optimizer_test.cpp92
-rw-r--r--eval/src/tests/tensor/dense_simple_expand_function/CMakeLists.txt9
-rw-r--r--eval/src/tests/tensor/dense_simple_expand_function/dense_simple_expand_function_test.cpp130
-rw-r--r--eval/src/tests/tensor/dense_xw_product_function/dense_xw_product_function_test.cpp2
7 files changed, 243 insertions, 3 deletions
diff --git a/eval/src/tests/tensor/dense_matmul_function/dense_matmul_function_test.cpp b/eval/src/tests/tensor/dense_matmul_function/dense_matmul_function_test.cpp
index a571837b8e9..92fdbfade46 100644
--- a/eval/src/tests/tensor/dense_matmul_function/dense_matmul_function_test.cpp
+++ b/eval/src/tests/tensor/dense_matmul_function/dense_matmul_function_test.cpp
@@ -67,7 +67,6 @@ TEST("require that matmul can be optimized") {
TEST("require that matmul with lambda can be optimized") {
TEST_DO(verify_optimized("reduce(join(a2d3,b5d3,f(x,y)(x*y)),sum,d)", 2, 3, 5, true, true));
- TEST_DO(verify_optimized("reduce(join(a2d3,b5d3,f(x,y)(y*x)),sum,d)", 2, 3, 5, true, true));
}
TEST("require that expressions similar to matmul are not optimized") {
@@ -75,6 +74,7 @@ TEST("require that expressions similar to matmul are not optimized") {
TEST_DO(verify_not_optimized("reduce(a2d3*b5d3,sum,b)"));
TEST_DO(verify_not_optimized("reduce(a2d3*b5d3,prod,d)"));
TEST_DO(verify_not_optimized("reduce(a2d3*b5d3,sum)"));
+ TEST_DO(verify_not_optimized("reduce(join(a2d3,b5d3,f(x,y)(y*x)),sum,d)"));
TEST_DO(verify_not_optimized("reduce(join(a2d3,b5d3,f(x,y)(x+y)),sum,d)"));
TEST_DO(verify_not_optimized("reduce(join(a2d3,b5d3,f(x,y)(x*x)),sum,d)"));
TEST_DO(verify_not_optimized("reduce(join(a2d3,b5d3,f(x,y)(y*y)),sum,d)"));
diff --git a/eval/src/tests/tensor/dense_multi_matmul_function/dense_multi_matmul_function_test.cpp b/eval/src/tests/tensor/dense_multi_matmul_function/dense_multi_matmul_function_test.cpp
index c0823248538..f9c563c9bf8 100644
--- a/eval/src/tests/tensor/dense_multi_matmul_function/dense_multi_matmul_function_test.cpp
+++ b/eval/src/tests/tensor/dense_multi_matmul_function/dense_multi_matmul_function_test.cpp
@@ -78,7 +78,6 @@ TEST("require that single multi matmul can be optimized") {
TEST("require that multi matmul with lambda can be optimized") {
TEST_DO(verify_optimized("reduce(join(A2B1C3a2d3,A2B1C3b5d3,f(x,y)(x*y)),sum,d)", 2, 3, 5, 6, true, true));
- TEST_DO(verify_optimized("reduce(join(A2B1C3a2d3,A2B1C3b5d3,f(x,y)(y*x)),sum,d)", 2, 3, 5, 6, true, true));
}
TEST("require that expressions similar to multi matmul are not optimized") {
@@ -86,6 +85,7 @@ TEST("require that expressions similar to multi matmul are not optimized") {
TEST_DO(verify_not_optimized("reduce(A2B1C3a2d3*A2B1C3b5d3,sum,b)"));
TEST_DO(verify_not_optimized("reduce(A2B1C3a2d3*A2B1C3b5d3,prod,d)"));
TEST_DO(verify_not_optimized("reduce(A2B1C3a2d3*A2B1C3b5d3,sum)"));
+ TEST_DO(verify_not_optimized("reduce(join(A2B1C3a2d3,A2B1C3b5d3,f(x,y)(y*x)),sum,d)"));
TEST_DO(verify_not_optimized("reduce(join(A2B1C3a2d3,A2B1C3b5d3,f(x,y)(x+y)),sum,d)"));
TEST_DO(verify_not_optimized("reduce(join(A2B1C3a2d3,A2B1C3b5d3,f(x,y)(x*x)),sum,d)"));
TEST_DO(verify_not_optimized("reduce(join(A2B1C3a2d3,A2B1C3b5d3,f(x,y)(y*y)),sum,d)"));
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
new file mode 100644
index 00000000000..cf5103f8b4f
--- /dev/null
+++ b/eval/src/tests/tensor/dense_pow_as_map_optimizer/CMakeLists.txt
@@ -0,0 +1,9 @@
+# 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
+)
+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
new file mode 100644
index 00000000000..38d9ac8aeef
--- /dev/null
+++ b/eval/src/tests/tensor/dense_pow_as_map_optimizer/dense_pow_as_map_optimizer_test.cpp
@@ -0,0 +1,92 @@
+// 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/default_tensor_engine.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 TensorEngine &prod_engine = DefaultTensorEngine::ref();
+
+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_engine, expr, param_repo, false);
+ EvalFixture fixture(prod_engine, 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_engine, expr, param_repo, false);
+ EvalFixture fixture(prod_engine, 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_simple_expand_function/CMakeLists.txt b/eval/src/tests/tensor/dense_simple_expand_function/CMakeLists.txt
new file mode 100644
index 00000000000..4e7409a6139
--- /dev/null
+++ b/eval/src/tests/tensor/dense_simple_expand_function/CMakeLists.txt
@@ -0,0 +1,9 @@
+# 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_expand_function_test_app TEST
+ SOURCES
+ dense_simple_expand_function_test.cpp
+ DEPENDS
+ vespaeval
+ gtest
+)
+vespa_add_test(NAME eval_dense_simple_expand_function_test_app COMMAND eval_dense_simple_expand_function_test_app)
diff --git a/eval/src/tests/tensor/dense_simple_expand_function/dense_simple_expand_function_test.cpp b/eval/src/tests/tensor/dense_simple_expand_function/dense_simple_expand_function_test.cpp
new file mode 100644
index 00000000000..4b870bc0153
--- /dev/null
+++ b/eval/src/tests/tensor/dense_simple_expand_function/dense_simple_expand_function_test.cpp
@@ -0,0 +1,130 @@
+// 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/eval/simple_tensor.h>
+#include <vespa/eval/eval/simple_tensor_engine.h>
+#include <vespa/eval/tensor/default_tensor_engine.h>
+#include <vespa/eval/tensor/dense/dense_simple_expand_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;
+
+using Inner = DenseSimpleExpandFunction::Inner;
+
+const TensorEngine &prod_engine = DefaultTensorEngine::ref();
+
+EvalFixture::ParamRepo make_params() {
+ return EvalFixture::ParamRepo()
+ .add("a", spec(1.5))
+ .add("sparse", spec({x({"a"})}, N()))
+ .add("mixed", spec({y({"a"}),z(5)}, N()))
+ .add_vector("a", 5)
+ .add_vector("b", 3)
+ .add_cube("A", 1, "a", 5, "c", 1)
+ .add_cube("B", 1, "b", 3, "c", 1)
+ .add_matrix("a", 5, "c", 3)
+ .add_matrix("x", 3, "y", 2)
+ .add_cube("a", 1, "b", 1, "c", 1)
+ .add_cube("x", 1, "y", 1, "z", 1);
+}
+
+EvalFixture::ParamRepo param_repo = make_params();
+
+void verify_optimized(const vespalib::string &expr, Inner inner) {
+ EvalFixture slow_fixture(prod_engine, expr, param_repo, false);
+ EvalFixture fixture(prod_engine, 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<DenseSimpleExpandFunction>();
+ ASSERT_EQ(info.size(), 1u);
+ EXPECT_TRUE(info[0]->result_is_mutable());
+ EXPECT_EQ(info[0]->inner(), inner);
+ ASSERT_EQ(fixture.num_params(), 2);
+ EXPECT_TRUE(!(fixture.get_param(0) == fixture.result()));
+ EXPECT_TRUE(!(fixture.get_param(1) == fixture.result()));
+}
+
+void verify_not_optimized(const vespalib::string &expr) {
+ EvalFixture slow_fixture(prod_engine, expr, param_repo, false);
+ EvalFixture fixture(prod_engine, 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<DenseSimpleExpandFunction>();
+ EXPECT_TRUE(info.empty());
+}
+
+TEST(ExpandTest, simple_expand_is_optimized) {
+ verify_optimized("join(a5,b3,f(x,y)(x*y))", Inner::RHS);
+ verify_optimized("join(b3,a5,f(x,y)(x*y))", Inner::LHS);
+}
+
+TEST(ExpandTest, multiple_dimensions_are_supported) {
+ verify_optimized("join(a5,x3y2,f(x,y)(x*y))", Inner::RHS);
+ verify_optimized("join(x3y2,a5,f(x,y)(x*y))", Inner::LHS);
+ verify_optimized("join(a5c3,x3y2,f(x,y)(x*y))", Inner::RHS);
+ verify_optimized("join(x3y2,a5c3,f(x,y)(x*y))", Inner::LHS);
+}
+
+TEST(ExpandTest, trivial_dimensions_are_ignored) {
+ verify_optimized("join(A1a5c1,B1b3c1,f(x,y)(x*y))", Inner::RHS);
+ verify_optimized("join(B1b3c1,A1a5c1,f(x,y)(x*y))", Inner::LHS);
+}
+
+TEST(ExpandTest, simple_expand_handles_asymmetric_operations_correctly) {
+ verify_optimized("join(a5,b3,f(x,y)(x-y))", Inner::RHS);
+ verify_optimized("join(b3,a5,f(x,y)(x-y))", Inner::LHS);
+ verify_optimized("join(a5,b3,f(x,y)(x/y))", Inner::RHS);
+ verify_optimized("join(b3,a5,f(x,y)(x/y))", Inner::LHS);
+}
+
+TEST(ExpandTest, simple_expand_can_have_various_cell_types) {
+ verify_optimized("join(a5,b3f,f(x,y)(x*y))", Inner::RHS);
+ verify_optimized("join(a5f,b3,f(x,y)(x*y))", Inner::RHS);
+ verify_optimized("join(a5f,b3f,f(x,y)(x*y))", Inner::RHS);
+ verify_optimized("join(b3,a5f,f(x,y)(x*y))", Inner::LHS);
+ verify_optimized("join(b3f,a5,f(x,y)(x*y))", Inner::LHS);
+ verify_optimized("join(b3f,a5f,f(x,y)(x*y))", Inner::LHS);
+}
+
+TEST(ExpandTest, simple_expand_is_never_inplace) {
+ verify_optimized("join(@a5,@b3,f(x,y)(x*y))", Inner::RHS);
+ verify_optimized("join(@b3,@a5,f(x,y)(x*y))", Inner::LHS);
+}
+
+TEST(ExpandTest, interleaved_dimensions_are_not_optimized) {
+ verify_not_optimized("join(a5c3,b3,f(x,y)(x*y))");
+ verify_not_optimized("join(b3,a5c3,f(x,y)(x*y))");
+}
+
+TEST(ExpandTest, matching_dimensions_are_not_expanding) {
+ verify_not_optimized("join(a5c3,a5,f(x,y)(x*y))");
+ verify_not_optimized("join(a5,a5c3,f(x,y)(x*y))");
+}
+
+TEST(ExpandTest, scalar_is_not_expanding) {
+ verify_not_optimized("join(a5,a,f(x,y)(x*y))");
+}
+
+TEST(ExpandTest, unit_tensor_is_not_expanding) {
+ verify_not_optimized("join(a5,x1y1z1,f(x,y)(x+y))");
+ verify_not_optimized("join(x1y1z1,a5,f(x,y)(x+y))");
+ verify_not_optimized("join(a1b1c1,x1y1z1,f(x,y)(x+y))");
+}
+
+TEST(ExpandTest, sparse_expand_is_not_optimized) {
+ verify_not_optimized("join(a5,sparse,f(x,y)(x*y))");
+ verify_not_optimized("join(sparse,a5,f(x,y)(x*y))");
+}
+
+TEST(ExpandTest, mixed_expand_is_not_optimized) {
+ verify_not_optimized("join(a5,mixed,f(x,y)(x*y))");
+ verify_not_optimized("join(mixed,a5,f(x,y)(x*y))");
+}
+
+GTEST_MAIN_RUN_ALL_TESTS()
diff --git a/eval/src/tests/tensor/dense_xw_product_function/dense_xw_product_function_test.cpp b/eval/src/tests/tensor/dense_xw_product_function/dense_xw_product_function_test.cpp
index 0b924451907..3ecc3f66cda 100644
--- a/eval/src/tests/tensor/dense_xw_product_function/dense_xw_product_function_test.cpp
+++ b/eval/src/tests/tensor/dense_xw_product_function/dense_xw_product_function_test.cpp
@@ -130,13 +130,13 @@ TEST("require that xw product gives same results as reference join/reduce") {
TEST("require that various variants of xw product can be optimized") {
TEST_DO(verify_optimized("reduce(join(y3,x2y3,f(x,y)(x*y)),sum,y)", 3, 2, true));
- TEST_DO(verify_optimized("reduce(join(y3,x2y3,f(x,y)(y*x)),sum,y)", 3, 2, true));
}
TEST("require that expressions similar to xw product are not optimized") {
TEST_DO(verify_not_optimized("reduce(y3*x2y3,sum,x)"));
TEST_DO(verify_not_optimized("reduce(y3*x2y3,prod,y)"));
TEST_DO(verify_not_optimized("reduce(y3*x2y3,sum)"));
+ TEST_DO(verify_not_optimized("reduce(join(y3,x2y3,f(x,y)(y*x)),sum,y)"));
TEST_DO(verify_not_optimized("reduce(join(y3,x2y3,f(x,y)(x+y)),sum,y)"));
TEST_DO(verify_not_optimized("reduce(join(y3,x2y3,f(x,y)(x*x)),sum,y)"));
TEST_DO(verify_not_optimized("reduce(join(y3,x2y3,f(x,y)(y*y)),sum,y)"));