aboutsummaryrefslogtreecommitdiffstats
path: root/eval
diff options
context:
space:
mode:
authorHåvard Pettersen <havardpe@oath.com>2021-02-04 08:28:21 +0000
committerHåvard Pettersen <havardpe@oath.com>2021-02-04 12:19:58 +0000
commit7bfb2536fc656e401469107d4c1dd182be80248b (patch)
tree49f4e5506e5befcb7f7143f314b27d0cad0e05c6 /eval
parent8c8a2061cc06036374ca46971798c35534a6a253 (diff)
rework sequence concept to match GenSpec
Diffstat (limited to 'eval')
-rw-r--r--eval/src/apps/tensor_conformance/generate.cpp8
-rw-r--r--eval/src/tests/eval/gen_spec/gen_spec_test.cpp77
-rw-r--r--eval/src/vespa/eval/eval/test/gen_spec.cpp33
-rw-r--r--eval/src/vespa/eval/eval/test/gen_spec.h44
-rw-r--r--eval/src/vespa/eval/eval/test/tensor_conformance.cpp4
-rw-r--r--eval/src/vespa/eval/eval/test/tensor_model.cpp4
-rw-r--r--eval/src/vespa/eval/eval/test/tensor_model.h61
7 files changed, 132 insertions, 99 deletions
diff --git a/eval/src/apps/tensor_conformance/generate.cpp b/eval/src/apps/tensor_conformance/generate.cpp
index e3d0c3c1063..537e35dee1f 100644
--- a/eval/src/apps/tensor_conformance/generate.cpp
+++ b/eval/src/apps/tensor_conformance/generate.cpp
@@ -183,8 +183,8 @@ void generate_tensor_join(TestBuilder &dst) {
void generate_dot_product(TestBuilder &dst,
double expect,
- const Layout &lhs, const Seq &lhs_seq,
- const Layout &rhs, const Seq &rhs_seq)
+ const Layout &lhs, const Sequence &lhs_seq,
+ const Layout &rhs, const Sequence &rhs_seq)
{
dst.add("reduce(a*b,sum)",
{ {"a", spec(lhs, lhs_seq)},{"b", spec(rhs, rhs_seq)} },
@@ -194,8 +194,8 @@ void generate_dot_product(TestBuilder &dst,
void generate_dot_product(TestBuilder &dst,
double expect,
const Layout &layout,
- const Seq &lhs_seq,
- const Seq &rhs_seq)
+ const Sequence &lhs_seq,
+ const Sequence &rhs_seq)
{
auto fl_lay = float_cells(layout);
generate_dot_product(dst, expect, layout, lhs_seq, layout, rhs_seq);
diff --git a/eval/src/tests/eval/gen_spec/gen_spec_test.cpp b/eval/src/tests/eval/gen_spec/gen_spec_test.cpp
index 0d1a4744e42..9af26e1284d 100644
--- a/eval/src/tests/eval/gen_spec/gen_spec_test.cpp
+++ b/eval/src/tests/eval/gen_spec/gen_spec_test.cpp
@@ -8,7 +8,7 @@ using namespace vespalib::eval::test;
//-----------------------------------------------------------------------------
-TEST(DimSpec, indexed_dimension) {
+TEST(DimSpecTest, indexed_dimension) {
ValueType::Dimension ref("foo", 10);
DimSpec idx("foo", 10);
EXPECT_EQ(idx.type(), ref);
@@ -18,7 +18,7 @@ TEST(DimSpec, indexed_dimension) {
EXPECT_EQ(idx.label(3), TensorSpec::Label(size_t(3)));
}
-TEST(DimSpec, mapped_dimension) {
+TEST(DimSpecTest, mapped_dimension) {
ValueType::Dimension ref("foo");
DimSpec map("foo", {"a", "b", "c", "d"});
EXPECT_EQ(map.type(), ref);
@@ -28,19 +28,19 @@ TEST(DimSpec, mapped_dimension) {
EXPECT_EQ(map.label(2), TensorSpec::Label("c"));
}
-TEST(DimSpec, simple_dictionary_creation) {
+TEST(DimSpecTest, simple_dictionary_creation) {
auto dict = DimSpec::make_dict(5, 1, "");
std::vector<vespalib::string> expect = {"0", "1", "2", "3", "4"};
}
-TEST(DimSpec, advanced_dictionary_creation) {
+TEST(DimSpecTest, advanced_dictionary_creation) {
auto dict = DimSpec::make_dict(5, 3, "str_");
std::vector<vespalib::string> expect = {"str_0", "str_3", "str_6", "str_9", "str_12"};
}
//-----------------------------------------------------------------------------
-TEST(GenSpec, default_spec) {
+TEST(GenSpecTest, default_spec) {
GenSpec spec;
EXPECT_TRUE(spec.dims().empty());
EXPECT_EQ(spec.cells(), CellType::DOUBLE);
@@ -55,29 +55,66 @@ TEST(GenSpec, default_spec) {
TensorSpec scalar_1 = TensorSpec("double").add({}, 1.0);
TensorSpec scalar_5 = TensorSpec("double").add({}, 5.0);
-TEST(GenSpec, scalar_double) {
+TEST(GenSpecTest, scalar_double) {
EXPECT_EQ(GenSpec().gen(), scalar_1);
EXPECT_EQ(GenSpec().seq_bias(5.0).gen(), scalar_5);
}
-TEST(GenSpec, not_scalar_float_just_yet) {
+TEST(GenSpecTest, not_scalar_float_just_yet) {
EXPECT_EQ(GenSpec().cells_float().gen(), scalar_1);
EXPECT_EQ(GenSpec().cells_float().seq_bias(5.0).gen(), scalar_5);
}
//-----------------------------------------------------------------------------
-TEST(Seq, seq_n) {
- GenSpec::seq_t seq = GenSpec().seq_n().seq();
+TEST(SequenceTest, n) {
+ GenSpec::seq_t seq = GenSpec().seq(N()).seq();
for (size_t i = 0; i < 4096; ++i) {
EXPECT_EQ(seq(i), (i + 1.0));
}
}
-TEST(Seq, seq_bias) {
- GenSpec::seq_t seq = GenSpec().seq_bias(13.0).seq();
+TEST(SequenceTest, bias) {
+ GenSpec::seq_t seq = GenSpec().seq(N(13.5)).seq();
for (size_t i = 0; i < 4096; ++i) {
- EXPECT_EQ(seq(i), (i + 13.0));
+ EXPECT_EQ(seq(i), (i + 13.5));
+ }
+}
+
+TEST(SequenceTest, ax_b) {
+ GenSpec::seq_t seq = GenSpec().seq(AX_B(3.5, 2.5)).seq();
+ for (size_t i = 0; i < 4096; ++i) {
+ EXPECT_EQ(seq(i), (i * 3.5) + 2.5);
+ }
+}
+
+TEST(SequenceTest, seq) {
+ std::vector<double> values({1.5, 3.5, 2.5, 10.0});
+ GenSpec::seq_t seq = GenSpec().seq(Seq(values)).seq();
+ for (size_t i = 0; i < 4096; ++i) {
+ EXPECT_EQ(seq(i), values[i % values.size()]);
+ }
+}
+
+TEST(SequenceTest, n_div16_sub2) {
+ GenSpec::seq_t seq = GenSpec().seq(Sub2(Div16(N()))).seq();
+ for (size_t i = 0; i < 4096; ++i) {
+ EXPECT_EQ(seq(i), ((i + 1.0) / 16.0) - 2.0);
+ }
+}
+
+TEST(SequenceTest, n_op_sqrt) {
+ GenSpec::seq_t seq = GenSpec().seq(OpSeq(N(), operation::Sqrt::f)).seq();
+ for (size_t i = 0; i < 4096; ++i) {
+ EXPECT_EQ(seq(i), operation::Sqrt::f(i + 1.0));
+ }
+}
+
+TEST(SequenceTest, n_sigmoidf) {
+ GenSpec::seq_t seq = GenSpec().seq(SigmoidF(N())).seq();
+ for (size_t i = 0; i < 4096; ++i) {
+ EXPECT_EQ(seq(i), double((float)operation::Sigmoid::f(i + 1.0)));
+ EXPECT_TRUE(seq(i) == double((float)operation::Sigmoid::f(i + 1.0)));
}
}
@@ -86,7 +123,7 @@ TEST(Seq, seq_bias) {
GenSpec flt() { return GenSpec().cells_float(); }
GenSpec dbl() { return GenSpec().cells_double(); }
-TEST(GenSpec, value_type) {
+TEST(GenSpecTest, value_type) {
EXPECT_EQ(dbl().type().to_spec(), "double");
EXPECT_EQ(flt().type().to_spec(), "double"); // NB
EXPECT_EQ(dbl().idx("x", 10).type().to_spec(), "tensor(x[10])");
@@ -122,15 +159,15 @@ TensorSpec custom_vector = TensorSpec("tensor(a[5])")
.add({{"a", 3}}, 2.0)
.add({{"a", 4}}, 1.0);
-TEST(GenSpec, generating_basic_vector) {
+TEST(GenSpecTest, generating_basic_vector) {
EXPECT_EQ(GenSpec().idx("a", 5).gen(), basic_vector);
}
-TEST(GenSpec, generating_float_vector) {
+TEST(GenSpecTest, generating_float_vector) {
EXPECT_EQ(GenSpec().idx("a", 5).cells_float().gen(), float_vector);
}
-TEST(GenSpec, generating_custom_vector) {
+TEST(GenSpecTest, generating_custom_vector) {
GenSpec::seq_t my_seq = [](size_t idx) noexcept { return (5.0 - idx); };
EXPECT_EQ(GenSpec().idx("a", 5).seq(my_seq).gen(), custom_vector);
}
@@ -147,14 +184,14 @@ TensorSpec custom_map = TensorSpec("tensor(a{})")
.add({{"a", "s5"}}, 2.0)
.add({{"a", "s10"}}, 3.0);
-TEST(GenSpec, generating_basic_map) {
+TEST(GenSpecTest, generating_basic_map) {
EXPECT_EQ(GenSpec().map("a", 3).gen(), basic_map);
EXPECT_EQ(GenSpec().map("a", 3, 1).gen(), basic_map);
EXPECT_EQ(GenSpec().map("a", 3, 1, "").gen(), basic_map);
EXPECT_EQ(GenSpec().map("a", {"0", "1", "2"}).gen(), basic_map);
}
-TEST(GenSpec, generating_custom_map) {
+TEST(GenSpecTest, generating_custom_map) {
EXPECT_EQ(GenSpec().map("a", 3, 5, "s").gen(), custom_map);
EXPECT_EQ(GenSpec().map("a", {"s0", "s5", "s10"}).gen(), custom_map);
}
@@ -183,11 +220,11 @@ TensorSpec inverted_mixed = TensorSpec("tensor(a{},b[1],c{},d[3])")
.add({{"a", "1"},{"b", 0},{"c", "0"},{"d", 2}}, 8.0)
.add({{"a", "2"},{"b", 0},{"c", "0"},{"d", 2}}, 9.0);
-TEST(GenSpec, generating_basic_mixed) {
+TEST(GenSpecTest, generating_basic_mixed) {
EXPECT_EQ(GenSpec().map("a", 3).idx("b", 1).map("c", 1).idx("d", 3).gen(), basic_mixed);
}
-TEST(GenSpec, generating_inverted_mixed) {
+TEST(GenSpecTest, generating_inverted_mixed) {
EXPECT_EQ(GenSpec().idx("d", 3).map("c", 1).idx("b", 1).map("a", 3).gen(), inverted_mixed);
}
diff --git a/eval/src/vespa/eval/eval/test/gen_spec.cpp b/eval/src/vespa/eval/eval/test/gen_spec.cpp
index c20e9005318..5ef4896d694 100644
--- a/eval/src/vespa/eval/eval/test/gen_spec.cpp
+++ b/eval/src/vespa/eval/eval/test/gen_spec.cpp
@@ -8,6 +8,39 @@ using vespalib::make_string_short::fmt;
namespace vespalib::eval::test {
+//-----------------------------------------------------------------------------
+
+Sequence N(double bias) {
+ return [bias](size_t i) { return (i + bias); };
+}
+
+Sequence AX_B(double a, double b) {
+ return [a,b](size_t i) { return (a * i) + b; };
+}
+
+Sequence Div16(const Sequence &seq) {
+ return [seq](size_t i) { return (seq(i) / 16.0); };
+}
+
+Sequence Sub2(const Sequence &seq) {
+ return [seq](size_t i) { return (seq(i) - 2.0); };
+}
+
+Sequence OpSeq(const Sequence &seq, map_fun_t op) {
+ return [seq,op](size_t i) { return op(seq(i)); };
+}
+
+Sequence SigmoidF(const Sequence &seq) {
+ return [seq](size_t i) { return (float)operation::Sigmoid::f(seq(i)); };
+}
+
+Sequence Seq(const std::vector<double> &seq) {
+ assert(!seq.empty());
+ return [seq](size_t i) { return seq[i % seq.size()]; };
+}
+
+//-----------------------------------------------------------------------------
+
DimSpec::~DimSpec() = default;
std::vector<vespalib::string>
diff --git a/eval/src/vespa/eval/eval/test/gen_spec.h b/eval/src/vespa/eval/eval/test/gen_spec.h
index 36bbd554125..6b9631c66c7 100644
--- a/eval/src/vespa/eval/eval/test/gen_spec.h
+++ b/eval/src/vespa/eval/eval/test/gen_spec.h
@@ -4,11 +4,39 @@
#include <vespa/eval/eval/tensor_spec.h>
#include <vespa/eval/eval/value_type.h>
+#include <vespa/eval/eval/operation.h>
#include <functional>
#include <cassert>
namespace vespalib::eval::test {
+using map_fun_t = vespalib::eval::operation::op1_t;
+using join_fun_t = vespalib::eval::operation::op2_t;
+using Sequence = std::function<double(size_t)>;
+
+// Sequence counting up from 1 (default)
+// bias (starting point) can be adjusted
+// bias = 1.5 -> 1.5, 2.5, 3.5 ...
+Sequence N(double bias = 1.0);
+
+// Sequence of numbers ax + b (where x is the index)
+Sequence AX_B(double a, double b);
+
+// Sequence of another sequence divided by 16
+Sequence Div16(const Sequence &seq);
+
+// Sequence of another sequence minus 2
+Sequence Sub2(const Sequence &seq);
+
+// Sequence of a unary operator applied to a sequence
+Sequence OpSeq(const Sequence &seq, map_fun_t op);
+
+// Sequence of applying sigmoid to another sequence, plus rounding to nearest float
+Sequence SigmoidF(const Sequence &seq);
+
+// pre-defined repeating sequence of numbers
+Sequence Seq(const std::vector<double> &seq);
+
/**
* Type and labels for a single dimension of a TensorSpec to be
* generated. Dimensions are specified independent of each other for
@@ -57,15 +85,15 @@ public:
class GenSpec
{
public:
- using seq_t = std::function<double(size_t)>;
+ using seq_t = Sequence;
+
private:
std::vector<DimSpec> _dims;
CellType _cells;
seq_t _seq;
- static double default_seq(size_t idx) { return (idx + 1.0); }
public:
- GenSpec() : _dims(), _cells(CellType::DOUBLE), _seq(default_seq) {}
+ GenSpec() : _dims(), _cells(CellType::DOUBLE), _seq(N()) {}
GenSpec(GenSpec &&other);
GenSpec(const GenSpec &other);
GenSpec &operator=(GenSpec &&other);
@@ -73,7 +101,7 @@ public:
~GenSpec();
std::vector<DimSpec> dims() const { return _dims; }
CellType cells() const { return _cells; }
- seq_t seq() const { return _seq; }
+ const seq_t &seq() const { return _seq; }
GenSpec cpy() const { return *this; }
GenSpec &idx(const vespalib::string &name, size_t size) {
_dims.emplace_back(name, size);
@@ -93,15 +121,11 @@ public:
}
GenSpec &cells_double() { return cells(CellType::DOUBLE); }
GenSpec &cells_float() { return cells(CellType::FLOAT); }
- GenSpec &seq(seq_t seq_in) {
+ GenSpec &seq(const seq_t &seq_in) {
_seq = seq_in;
return *this;
}
- GenSpec &seq_n() { return seq(default_seq); }
- GenSpec &seq_bias(double bias) {
- seq_t fun = [bias](size_t idx) noexcept { return (idx + bias); };
- return seq(fun);
- }
+ GenSpec &seq_bias(double bias) { return seq(N(bias)); }
ValueType type() const;
TensorSpec gen() const;
};
diff --git a/eval/src/vespa/eval/eval/test/tensor_conformance.cpp b/eval/src/vespa/eval/eval/test/tensor_conformance.cpp
index bd203b42ef1..1e9afde3cb9 100644
--- a/eval/src/vespa/eval/eval/test/tensor_conformance.cpp
+++ b/eval/src/vespa/eval/eval/test/tensor_conformance.cpp
@@ -503,8 +503,8 @@ struct TestContext {
}
void test_dot_product(double expect,
- const Layout &lhs, const Seq &lhs_seq,
- const Layout &rhs, const Seq &rhs_seq)
+ const Layout &lhs, const Sequence &lhs_seq,
+ const Layout &rhs, const Sequence &rhs_seq)
{
TEST_DO(test_dot_product(expect, spec(lhs, lhs_seq), spec(rhs, rhs_seq)));
TEST_DO(test_dot_product(expect, spec(float_cells(lhs), lhs_seq), spec(rhs, rhs_seq)));
diff --git a/eval/src/vespa/eval/eval/test/tensor_model.cpp b/eval/src/vespa/eval/eval/test/tensor_model.cpp
index 98470388eb5..7860563bccd 100644
--- a/eval/src/vespa/eval/eval/test/tensor_model.cpp
+++ b/eval/src/vespa/eval/eval/test/tensor_model.cpp
@@ -5,8 +5,6 @@
namespace vespalib::eval::test {
-Seq::~Seq() = default;
-
Domain::Domain(const Domain &) = default;
Domain::~Domain() = default;
@@ -63,7 +61,7 @@ private:
void generate(size_t layout_idx) {
if (layout_idx == _source.layout.size()) {
- _spec.add(_addr, _source.seq[_idx++]);
+ _spec.add(_addr, _source.seq(_idx++));
} else {
const Domain &domain = _source.layout[layout_idx];
if (domain.size > 0) { // indexed
diff --git a/eval/src/vespa/eval/eval/test/tensor_model.h b/eval/src/vespa/eval/eval/test/tensor_model.h
index 28b9bfd4c6e..56504795cee 100644
--- a/eval/src/vespa/eval/eval/test/tensor_model.h
+++ b/eval/src/vespa/eval/eval/test/tensor_model.h
@@ -2,69 +2,10 @@
#pragma once
-#include <vespa/eval/eval/tensor_spec.h>
-#include <vespa/eval/eval/operation.h>
-#include <vespa/eval/eval/cell_type.h>
-#include <cassert>
-#include <vector>
+#include "gen_spec.h"
namespace vespalib::eval::test {
-using map_fun_t = vespalib::eval::operation::op1_t;
-using join_fun_t = vespalib::eval::operation::op2_t;
-
-// Random access sequence of numbers
-struct Sequence {
- virtual double operator[](size_t i) const = 0;
- virtual ~Sequence() {}
-};
-
-// Sequence of natural numbers (starting at 1)
-struct N : Sequence {
- double operator[](size_t i) const override { return (1.0 + i); }
-};
-
-// Sequence of another sequence divided by 16
-struct Div16 : Sequence {
- const Sequence &seq;
- Div16(const Sequence &seq_in) : seq(seq_in) {}
- double operator[](size_t i) const override { return (seq[i] / 16.0); }
-};
-
-// Sequence of another sequence minus 2
-struct Sub2 : Sequence {
- const Sequence &seq;
- Sub2(const Sequence &seq_in) : seq(seq_in) {}
- double operator[](size_t i) const override { return (seq[i] - 2.0); }
-};
-
-// Sequence of a unary operator applied to a sequence
-struct OpSeq : Sequence {
- const Sequence &seq;
- map_fun_t op;
- OpSeq(const Sequence &seq_in, map_fun_t op_in) : seq(seq_in), op(op_in) {}
- double operator[](size_t i) const override { return op(seq[i]); }
-};
-
-// Sequence of applying sigmoid to another sequence, plus rounding to nearest float
-struct SigmoidF : Sequence {
- const Sequence &seq;
- SigmoidF(const Sequence &seq_in) : seq(seq_in) {}
- double operator[](size_t i) const override { return (float)operation::Sigmoid::f(seq[i]); }
-};
-
-// pre-defined repeating sequence of numbers
-struct Seq : Sequence {
- std::vector<double> seq;
- Seq() : seq() {}
- Seq(const std::vector<double> &seq_in)
- : seq(seq_in) { assert(!seq_in.empty()); }
- ~Seq() override;
- double operator[](size_t i) const override {
- return seq[i % seq.size()];
- }
-};
-
// custom op1
struct MyOp {
static double f(double a) {