summaryrefslogtreecommitdiffstats
path: root/eval/src
diff options
context:
space:
mode:
authorGeir Storli <geirst@verizonmedia.com>2019-02-25 12:29:02 +0100
committerGitHub <noreply@github.com>2019-02-25 12:29:02 +0100
commit3148c6dc8e5d7911ccf0bbb533edaa4ceb3b7c5d (patch)
tree278c853c894ad13cdd77f91f90f42525ecaf71a5 /eval/src
parent09ce7c318f03a73f4b6972677765b7a600c757e8 (diff)
parent3167155f4ab0beaef9436bacb0b8a6fdb7764dac (diff)
Merge pull request #8593 from vespa-engine/geirst/add-operation-on-mixed-tensors
Geirst/add operation on mixed tensors
Diffstat (limited to 'eval/src')
-rw-r--r--eval/src/tests/tensor/tensor_add_operation/CMakeLists.txt1
-rw-r--r--eval/src/tests/tensor/tensor_add_operation/tensor_add_operation_test.cpp55
-rw-r--r--eval/src/tests/tensor/tensor_modify_operation/CMakeLists.txt1
-rw-r--r--eval/src/tests/tensor/tensor_modify_operation/tensor_modify_operation_test.cpp68
-rw-r--r--eval/src/tests/tensor/tensor_remove_operation/CMakeLists.txt1
-rw-r--r--eval/src/tests/tensor/tensor_remove_operation/tensor_remove_operation_test.cpp10
-rw-r--r--eval/src/vespa/eval/tensor/wrapped_simple_tensor.cpp29
7 files changed, 122 insertions, 43 deletions
diff --git a/eval/src/tests/tensor/tensor_add_operation/CMakeLists.txt b/eval/src/tests/tensor/tensor_add_operation/CMakeLists.txt
index 6c19b13db7e..e511b23c5ec 100644
--- a/eval/src/tests/tensor/tensor_add_operation/CMakeLists.txt
+++ b/eval/src/tests/tensor/tensor_add_operation/CMakeLists.txt
@@ -4,5 +4,6 @@ vespa_add_executable(eval_tensor_add_operation_test_app TEST
tensor_add_operation_test.cpp
DEPENDS
vespaeval
+ gtest
)
vespa_add_test(NAME eval_tensor_add_operation_test_app COMMAND eval_tensor_add_operation_test_app)
diff --git a/eval/src/tests/tensor/tensor_add_operation/tensor_add_operation_test.cpp b/eval/src/tests/tensor/tensor_add_operation/tensor_add_operation_test.cpp
index 5ac1c503b5d..4c92dc717a7 100644
--- a/eval/src/tests/tensor/tensor_add_operation/tensor_add_operation_test.cpp
+++ b/eval/src/tests/tensor/tensor_add_operation/tensor_add_operation_test.cpp
@@ -4,7 +4,7 @@
#include <vespa/eval/tensor/default_tensor_engine.h>
#include <vespa/eval/tensor/sparse/sparse_tensor.h>
#include <vespa/eval/tensor/test/test_utils.h>
-#include <vespa/vespalib/testkit/test_kit.h>
+#include <vespa/vespalib/gtest/gtest.h>
using vespalib::eval::Value;
using vespalib::eval::TensorSpec;
@@ -18,10 +18,19 @@ assertAdd(const TensorSpec &source, const TensorSpec &arg, const TensorSpec &exp
auto argTensor = makeTensor<Tensor>(arg);
auto resultTensor = sourceTensor->add(*argTensor);
auto actual = resultTensor->toSpec();
- EXPECT_EQUAL(actual, expected);
+ EXPECT_EQ(actual, expected);
}
-TEST("require that cells can be added to a sparse tensor")
+void
+assertNullTensor(const TensorSpec &source, const TensorSpec &arg)
+{
+ auto sourceTensor = makeTensor<Tensor>(source);
+ auto argTensor = makeTensor<Tensor>(arg);
+ auto resultTensor = sourceTensor->add(*argTensor);
+ EXPECT_FALSE(resultTensor);
+}
+
+TEST(TensorAddTest, cells_can_be_added_to_a_sparse_tensor)
{
assertAdd(TensorSpec("tensor(x{},y{})")
.add({{"x","a"},{"y","b"}}, 2)
@@ -35,4 +44,42 @@ TEST("require that cells can be added to a sparse tensor")
.add({{"x","e"},{"y","f"}}, 7));
}
-TEST_MAIN() { TEST_RUN_ALL(); }
+TEST(TensorAddTest, cells_can_be_added_to_a_mixed_tensor)
+{
+ assertAdd(TensorSpec("tensor(x{},y[2])")
+ .add({{"x","a"},{"y",0}}, 2)
+ .add({{"x","a"},{"y",1}}, 3)
+ .add({{"x","b"},{"y",0}}, 4)
+ .add({{"x","b"},{"y",1}}, 5),
+ TensorSpec("tensor(x{},y[2])")
+ .add({{"x","b"},{"y",0}}, 6)
+ .add({{"x","b"},{"y",1}}, 7)
+ .add({{"x","c"},{"y",0}}, 8)
+ .add({{"x","c"},{"y",1}}, 9),
+ TensorSpec("tensor(x{},y[2])")
+ .add({{"x","a"},{"y",0}}, 2)
+ .add({{"x","a"},{"y",1}}, 3)
+ .add({{"x","b"},{"y",0}}, 6)
+ .add({{"x","b"},{"y",1}}, 7)
+ .add({{"x","c"},{"y",0}}, 8)
+ .add({{"x","c"},{"y",1}}, 9));
+}
+
+TEST(TensorAddTest, cells_can_be_added_to_empty_mixed_tensor)
+{
+ assertAdd(TensorSpec("tensor(x{},y[2])"),
+ TensorSpec("tensor(x{},y[2])")
+ .add({{"x","b"},{"y",0}}, 6)
+ .add({{"x","b"},{"y",1}}, 7),
+ TensorSpec("tensor(x{},y[2])")
+ .add({{"x","b"},{"y",0}}, 6)
+ .add({{"x","b"},{"y",1}}, 7));
+}
+
+TEST(TensorAddTest, tensors_of_different_types_cannot_be_added_together)
+{
+ assertNullTensor(TensorSpec("tensor(x{},y[2])"), TensorSpec("tensor(x{},y{})"));
+ assertNullTensor(TensorSpec("tensor(x{},y[2])"), TensorSpec("tensor(x{},y[3])"));
+}
+
+GTEST_MAIN_RUN_ALL_TESTS
diff --git a/eval/src/tests/tensor/tensor_modify_operation/CMakeLists.txt b/eval/src/tests/tensor/tensor_modify_operation/CMakeLists.txt
index b0ffa48eb3b..481a0aac7fb 100644
--- a/eval/src/tests/tensor/tensor_modify_operation/CMakeLists.txt
+++ b/eval/src/tests/tensor/tensor_modify_operation/CMakeLists.txt
@@ -4,5 +4,6 @@ vespa_add_executable(eval_tensor_modify_operation_test_app TEST
tensor_modify_operation_test.cpp
DEPENDS
vespaeval
+ gtest
)
vespa_add_test(NAME eval_tensor_modify_operation_test_app COMMAND eval_tensor_modify_operation_test_app)
diff --git a/eval/src/tests/tensor/tensor_modify_operation/tensor_modify_operation_test.cpp b/eval/src/tests/tensor/tensor_modify_operation/tensor_modify_operation_test.cpp
index 5cacff1881b..ff59b28d60c 100644
--- a/eval/src/tests/tensor/tensor_modify_operation/tensor_modify_operation_test.cpp
+++ b/eval/src/tests/tensor/tensor_modify_operation/tensor_modify_operation_test.cpp
@@ -1,12 +1,12 @@
// 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/vespalib/util/stringfmt.h>
+#include <vespa/eval/eval/tensor_spec.h>
#include <vespa/eval/tensor/cell_values.h>
+#include <vespa/eval/tensor/default_tensor_engine.h>
#include <vespa/eval/tensor/sparse/sparse_tensor.h>
#include <vespa/eval/tensor/test/test_utils.h>
-#include <vespa/eval/tensor/default_tensor_engine.h>
-#include <vespa/eval/eval/tensor_spec.h>
+#include <vespa/vespalib/gtest/gtest.h>
+#include <vespa/vespalib/util/stringfmt.h>
using vespalib::eval::Value;
using vespalib::eval::TensorSpec;
@@ -34,53 +34,57 @@ checkUpdate(const TensorSpec &source, const TensorSpec &update, const TensorSpec
auto actual = actualTensor->toSpec();
auto expectTensor = makeTensor<Tensor>(expect);
auto expectPadded = expectTensor->toSpec();
- EXPECT_EQUAL(actual, expectPadded);
+ EXPECT_EQ(actual, expectPadded);
}
-TEST("require that sparse tensors can be modified") {
+TEST(TensorModifyTest, sparse_tensors_can_be_modified)
+{
checkUpdate(TensorSpec("tensor(x{},y{})")
- .add({{"x","8"},{"y","9"}}, 11)
- .add({{"x","9"},{"y","9"}}, 11),
+ .add({{"x","8"},{"y","9"}}, 11)
+ .add({{"x","9"},{"y","9"}}, 11),
TensorSpec("tensor(x{},y{})")
- .add({{"x","8"},{"y","9"}}, 2),
+ .add({{"x","8"},{"y","9"}}, 2),
TensorSpec("tensor(x{},y{})")
- .add({{"x","8"},{"y","9"}}, 2)
- .add({{"x","9"},{"y","9"}}, 11));
+ .add({{"x","8"},{"y","9"}}, 2)
+ .add({{"x","9"},{"y","9"}}, 11));
}
-TEST("require that dense tensors can be modified") {
+TEST(TensorModifyTest, dense_tensors_can_be_modified)
+{
checkUpdate(TensorSpec("tensor(x[10],y[10])")
- .add({{"x",8},{"y",9}}, 11)
- .add({{"x",9},{"y",9}}, 11),
+ .add({{"x",8},{"y",9}}, 11)
+ .add({{"x",9},{"y",9}}, 11),
TensorSpec("tensor(x{},y{})")
- .add({{"x","8"},{"y","9"}}, 2),
+ .add({{"x","8"},{"y","9"}}, 2),
TensorSpec("tensor(x[10],y[10])")
- .add({{"x",8},{"y",9}}, 2)
- .add({{"x",9},{"y",9}}, 11));
+ .add({{"x",8},{"y",9}}, 2)
+ .add({{"x",9},{"y",9}}, 11));
}
-TEST("require that sparse tensors ignore updates to missing cells") {
+TEST(TensorModifyTest, sparse_tensors_ignore_updates_to_missing_cells)
+{
checkUpdate(TensorSpec("tensor(x{},y{})")
- .add({{"x","8"},{"y","9"}}, 11)
- .add({{"x","9"},{"y","9"}}, 11),
+ .add({{"x","8"},{"y","9"}}, 11)
+ .add({{"x","9"},{"y","9"}}, 11),
TensorSpec("tensor(x{},y{})")
- .add({{"x","7"},{"y","9"}}, 2)
- .add({{"x","8"},{"y","9"}}, 2),
+ .add({{"x","7"},{"y","9"}}, 2)
+ .add({{"x","8"},{"y","9"}}, 2),
TensorSpec("tensor(x{},y{})")
- .add({{"x","8"},{"y","9"}}, 2)
- .add({{"x","9"},{"y","9"}}, 11));
+ .add({{"x","8"},{"y","9"}}, 2)
+ .add({{"x","9"},{"y","9"}}, 11));
}
-TEST("require that dense tensors ignore updates to out of range cells") {
+TEST(TensorModifyTest, dense_tensors_ignore_updates_to_out_of_range_cells)
+{
checkUpdate(TensorSpec("tensor(x[10],y[10])")
- .add({{"x",8},{"y",9}}, 11)
- .add({{"x",9},{"y",9}}, 11),
+ .add({{"x",8},{"y",9}}, 11)
+ .add({{"x",9},{"y",9}}, 11),
TensorSpec("tensor(x{},y{})")
- .add({{"x","8"},{"y","9"}}, 2)
- .add({{"x","10"},{"y","9"}}, 2),
+ .add({{"x","8"},{"y","9"}}, 2)
+ .add({{"x","10"},{"y","9"}}, 2),
TensorSpec("tensor(x[10],y[10])")
- .add({{"x",8},{"y",9}}, 2)
- .add({{"x",9},{"y",9}}, 11));
+ .add({{"x",8},{"y",9}}, 2)
+ .add({{"x",9},{"y",9}}, 11));
}
-TEST_MAIN() { TEST_RUN_ALL(); }
+GTEST_MAIN_RUN_ALL_TESTS
diff --git a/eval/src/tests/tensor/tensor_remove_operation/CMakeLists.txt b/eval/src/tests/tensor/tensor_remove_operation/CMakeLists.txt
index 8dfb8181f2b..ffc71563107 100644
--- a/eval/src/tests/tensor/tensor_remove_operation/CMakeLists.txt
+++ b/eval/src/tests/tensor/tensor_remove_operation/CMakeLists.txt
@@ -4,5 +4,6 @@ vespa_add_executable(eval_tensor_remove_operation_test_app TEST
tensor_remove_operation_test.cpp
DEPENDS
vespaeval
+ gtest
)
vespa_add_test(NAME eval_tensor_remove_operation_test_app COMMAND eval_tensor_remove_operation_test_app)
diff --git a/eval/src/tests/tensor/tensor_remove_operation/tensor_remove_operation_test.cpp b/eval/src/tests/tensor/tensor_remove_operation/tensor_remove_operation_test.cpp
index 8b0c44a6e06..cb28019c4ee 100644
--- a/eval/src/tests/tensor/tensor_remove_operation/tensor_remove_operation_test.cpp
+++ b/eval/src/tests/tensor/tensor_remove_operation/tensor_remove_operation_test.cpp
@@ -5,7 +5,7 @@
#include <vespa/eval/tensor/default_tensor_engine.h>
#include <vespa/eval/tensor/sparse/sparse_tensor.h>
#include <vespa/eval/tensor/test/test_utils.h>
-#include <vespa/vespalib/testkit/test_kit.h>
+#include <vespa/vespalib/gtest/gtest.h>
using vespalib::eval::Value;
using vespalib::eval::TensorSpec;
@@ -19,10 +19,10 @@ assertRemove(const TensorSpec &source, const TensorSpec &arg, const TensorSpec &
auto argTensor = makeTensor<SparseTensor>(arg);
auto resultTensor = sourceTensor->remove(CellValues(*argTensor));
auto actual = resultTensor->toSpec();
- EXPECT_EQUAL(actual, expected);
+ EXPECT_EQ(actual, expected);
}
-TEST("require that cells can be removed from a sparse tensor")
+TEST(TensorRemoveTest, cells_can_be_removed_from_a_sparse_tensor)
{
assertRemove(TensorSpec("tensor(x{},y{})")
.add({{"x","a"},{"y","b"}}, 2)
@@ -34,7 +34,7 @@ TEST("require that cells can be removed from a sparse tensor")
.add({{"x","a"},{"y","b"}}, 2));
}
-TEST("require that all cells can be removed from a sparse tensor")
+TEST(TensorRemoveTest, all_cells_can_be_removed_from_a_sparse_tensor)
{
assertRemove(TensorSpec("tensor(x{},y{})")
.add({{"x","a"},{"y","b"}}, 2),
@@ -43,4 +43,4 @@ TEST("require that all cells can be removed from a sparse tensor")
TensorSpec("tensor(x{},y{})"));
}
-TEST_MAIN() { TEST_RUN_ALL(); }
+GTEST_MAIN_RUN_ALL_TESTS
diff --git a/eval/src/vespa/eval/tensor/wrapped_simple_tensor.cpp b/eval/src/vespa/eval/tensor/wrapped_simple_tensor.cpp
index 9df59a63873..1268d6fa9cb 100644
--- a/eval/src/vespa/eval/tensor/wrapped_simple_tensor.cpp
+++ b/eval/src/vespa/eval/tensor/wrapped_simple_tensor.cpp
@@ -12,6 +12,9 @@ LOG_SETUP(".eval.tensor.wrapped_simple_tensor");
namespace vespalib::tensor {
+using eval::SimpleTensor;
+using eval::TensorSpec;
+
bool
WrappedSimpleTensor::equals(const Tensor &arg) const
{
@@ -84,9 +87,31 @@ WrappedSimpleTensor::modify(join_fun_t, const CellValues &) const
}
std::unique_ptr<Tensor>
-WrappedSimpleTensor::add(const Tensor &) const
+WrappedSimpleTensor::add(const Tensor &arg) const
{
- LOG_ABORT("should not be reached");
+ const auto *rhs = dynamic_cast<const WrappedSimpleTensor *>(&arg);
+ if (!rhs || type() != rhs->type()) {
+ return Tensor::UP();
+ }
+
+ TensorSpec oldTensor = toSpec();
+ TensorSpec argTensor = rhs->toSpec();
+ TensorSpec result(type().to_spec());
+ for (const auto &cell : oldTensor.cells()) {
+ auto argItr = argTensor.cells().find(cell.first);
+ if (argItr != argTensor.cells().end()) {
+ result.add(argItr->first, argItr->second);
+ } else {
+ result.add(cell.first, cell.second);
+ }
+ }
+ for (const auto &cell : argTensor.cells()) {
+ auto resultItr = result.cells().find(cell.first);
+ if (resultItr == result.cells().end()) {
+ result.add(cell.first, cell.second);
+ }
+ }
+ return std::make_unique<WrappedSimpleTensor>(SimpleTensor::create(result));
}
std::unique_ptr<Tensor>