diff options
author | Håvard Pettersen <havardpe@oath.com> | 2021-03-12 09:09:40 +0000 |
---|---|---|
committer | Håvard Pettersen <havardpe@oath.com> | 2021-03-12 11:19:34 +0000 |
commit | bcbf0018e423910c10217a4ce71cc07053f5b6e4 (patch) | |
tree | 2085765f9825199bbe62c2668d677cdf4aa63a4b | |
parent | cdf52990f001826004b52b39acf99647c7f7b0f7 (diff) |
add new way to make a GenSpec based on a textual description
-rw-r--r-- | eval/src/tests/eval/gen_spec/gen_spec_test.cpp | 22 | ||||
-rw-r--r-- | eval/src/vespa/eval/eval/test/gen_spec.cpp | 62 | ||||
-rw-r--r-- | eval/src/vespa/eval/eval/test/gen_spec.h | 21 |
3 files changed, 104 insertions, 1 deletions
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 9d8eb419a67..30ef42d7ebb 100644 --- a/eval/src/tests/eval/gen_spec/gen_spec_test.cpp +++ b/eval/src/tests/eval/gen_spec/gen_spec_test.cpp @@ -32,11 +32,13 @@ TEST(DimSpecTest, mapped_dimension) { TEST(DimSpecTest, simple_dictionary_creation) { auto dict = DimSpec::make_dict(5, 1, ""); std::vector<vespalib::string> expect = {"0", "1", "2", "3", "4"}; + EXPECT_EQ(dict, expect); } 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"}; + EXPECT_EQ(dict, expect); } //----------------------------------------------------------------------------- @@ -234,4 +236,24 @@ TEST(GenSpecTest, gen_spec_can_be_implicitly_converted_to_tensor_spec) { //----------------------------------------------------------------------------- +TEST(GenSpecFromDescTest, dim_spec_and_gen_spec_can_be_created_from_desc) { + // 'a2b3#7c5#' + auto expect = GenSpec().idx("a", 2).map("b", 3, 7).map("c", 5).gen(); + auto dim_desc = GenSpec().desc("a2").desc("b3#7").desc("c5#").gen(); + auto gen_desc = GenSpec::from_desc("a2b3#7c5#").gen(); + EXPECT_EQ(dim_desc, expect); + EXPECT_EQ(gen_desc, expect); +} + +TEST(GenSpecFromDescTest, multi_character_sizes_work) { + // 'a13b1' + auto expect = GenSpec().idx("a", 13).idx("b", 1).gen(); + auto dim_desc = GenSpec().desc("a13").desc("b1").gen(); + auto gen_desc = GenSpec::from_desc("a13b1").gen(); + EXPECT_EQ(dim_desc, expect); + EXPECT_EQ(gen_desc, expect); +} + +//----------------------------------------------------------------------------- + GTEST_MAIN_RUN_ALL_TESTS() diff --git a/eval/src/vespa/eval/eval/test/gen_spec.cpp b/eval/src/vespa/eval/eval/test/gen_spec.cpp index a308cbeff46..87e49c376d1 100644 --- a/eval/src/vespa/eval/eval/test/gen_spec.cpp +++ b/eval/src/vespa/eval/eval/test/gen_spec.cpp @@ -53,6 +53,68 @@ DimSpec::make_dict(size_t size, size_t stride, const vespalib::string &prefix) return dict; } +// 'a2' -> DimSpec("a", 2); +// 'b2#' -> DimSpec("b", make_dict(2, 1, "")); +// 'c2#3' -> DimSpec("c", make_dict(2, 3, "")); +DimSpec +DimSpec::from_desc(const vespalib::string &desc) +{ + size_t idx = 0; + vespalib::string name; + auto is_num = [](char c) { return ((c >= '0') && (c <= '9')); }; + auto as_num = [](char c) { return size_t(c - '0'); }; + auto is_map_tag = [](char c) { return (c == '#'); }; + auto is_dim_name = [](char c) { return ((c >= 'a') && (c <= 'z')); }; + auto extract_number = [&]() { + assert(idx < desc.size()); + assert(is_num(desc[idx])); + size_t num = as_num(desc[idx++]); + assert(num != 0); // catch leading zeroes/zero size + while ((idx < desc.size()) && is_num(desc[idx])) { + num = (num * 10) + as_num(desc[idx++]); + } + return num; + }; + assert(!desc.empty()); + assert(is_dim_name(desc[idx])); + name.push_back(desc[idx++]); + size_t size = extract_number(); + if (idx < desc.size()) { + // mapped + assert(is_map_tag(desc[idx++])); + size_t stride = 1; + if (idx < desc.size()) { + stride = extract_number(); + assert(idx == desc.size()); + } + return {name, make_dict(size, stride, "")}; + } else { + // indexed + return {name, size}; + } +} + +// 'a2b12c5' -> GenSpec().idx("a", 2).idx("b", 12).idx("c", 5); +// 'a2#b3#2c5#' -> GenSpec().map("a", 2).map("b", 3, 2).map("c", 5); +GenSpec +GenSpec::from_desc(const vespalib::string &desc) +{ + size_t idx = 0; + vespalib::string dim_desc; + std::vector<DimSpec> dim_list; + auto is_dim_name = [](char c) { return ((c >= 'a') && (c <= 'z')); }; + while (idx < desc.size()) { + dim_desc.clear(); + assert(is_dim_name(desc[idx])); + dim_desc.push_back(desc[idx++]); + while ((idx < desc.size()) && !is_dim_name(desc[idx])) { + dim_desc.push_back(desc[idx++]); + } + dim_list.push_back(DimSpec::from_desc(dim_desc)); + } + return {std::move(dim_list)}; +} + GenSpec::GenSpec(GenSpec &&other) = default; GenSpec::GenSpec(const GenSpec &other) = default; GenSpec &GenSpec::operator=(GenSpec &&other) = default; diff --git a/eval/src/vespa/eval/eval/test/gen_spec.h b/eval/src/vespa/eval/eval/test/gen_spec.h index bbc1663a11f..6943ba6c98a 100644 --- a/eval/src/vespa/eval/eval/test/gen_spec.h +++ b/eval/src/vespa/eval/eval/test/gen_spec.h @@ -76,6 +76,14 @@ public: assert(idx < size()); return _size ? TensorSpec::Label{idx} : TensorSpec::Label{_dict[idx]}; } + + // Make a DimSpec object from a textual description + // (first character is used as dimension name) + // + // 'a2' -> DimSpec("a", 2); + // 'b2#' -> DimSpec("b", make_dict(2, 1, "")); + // 'c2#3' -> DimSpec("c", make_dict(2, 3, "")); + static DimSpec from_desc(const vespalib::string &desc); }; /** @@ -95,7 +103,14 @@ private: public: GenSpec() : _dims(), _cells(CellType::DOUBLE), _seq(N()) {} GenSpec(double bias) : _dims(), _cells(CellType::DOUBLE), _seq(N(bias)) {} - GenSpec(const std::vector<DimSpec> &dims_in) : _dims(dims_in), _cells(CellType::DOUBLE), _seq(N()) {} + GenSpec(std::vector<DimSpec> dims_in) : _dims(std::move(dims_in)), _cells(CellType::DOUBLE), _seq(N()) {} + + // Make a GenSpec object from a textual description + // (dimension names must be single characters a-z) + // + // 'a2b12c5' -> GenSpec().idx("a", 2).idx("b", 12).idx("c", 5); + // 'a2#b3#2c5#' -> GenSpec().map("a", 2).map("b", 3, 2).map("c", 5); + static GenSpec from_desc(const vespalib::string &desc); GenSpec(GenSpec &&other); GenSpec(const GenSpec &other); @@ -118,6 +133,10 @@ public: _dims.emplace_back(name, std::move(dict)); return *this; } + GenSpec &desc(const vespalib::string &dim_desc) { + _dims.push_back(DimSpec::from_desc(dim_desc)); + return *this; + } GenSpec &cells(CellType cell_type) { _cells = cell_type; return *this; |