summaryrefslogtreecommitdiffstats
path: root/eval
diff options
context:
space:
mode:
authorHaavard <havardpe@yahoo-inc.com>2017-06-27 07:42:52 +0000
committerHaavard <havardpe@yahoo-inc.com>2017-06-27 07:43:51 +0000
commit5e6cb794607edd4ddb156db7c8f49e0a0fc1bf45 (patch)
treeacdb759458da7184833ded45a664cf4b8b8ea3c5 /eval
parentf7906fd2c5c6d47613ed19cb81bc841726a2ebad (diff)
added modulo operator (%)
Diffstat (limited to 'eval')
-rw-r--r--eval/src/tests/eval/function/function_test.cpp2
-rw-r--r--eval/src/vespa/eval/eval/interpreted_function.cpp5
-rw-r--r--eval/src/vespa/eval/eval/key_gen.cpp73
-rw-r--r--eval/src/vespa/eval/eval/llvm/llvm_wrapper.cpp3
-rw-r--r--eval/src/vespa/eval/eval/node_types.cpp1
-rw-r--r--eval/src/vespa/eval/eval/node_visitor.h2
-rw-r--r--eval/src/vespa/eval/eval/operation.cpp2
-rw-r--r--eval/src/vespa/eval/eval/operation.h2
-rw-r--r--eval/src/vespa/eval/eval/operation_visitor.h4
-rw-r--r--eval/src/vespa/eval/eval/operator_nodes.cpp1
-rw-r--r--eval/src/vespa/eval/eval/operator_nodes.h1
-rw-r--r--eval/src/vespa/eval/eval/test/eval_spec.cpp1
-rw-r--r--eval/src/vespa/eval/eval/test/tensor_conformance.cpp3
13 files changed, 57 insertions, 43 deletions
diff --git a/eval/src/tests/eval/function/function_test.cpp b/eval/src/tests/eval/function/function_test.cpp
index 7b8dc2dc0ee..621f68ffc62 100644
--- a/eval/src/tests/eval/function/function_test.cpp
+++ b/eval/src/tests/eval/function/function_test.cpp
@@ -204,7 +204,7 @@ TEST("require that parenthesis resolves before not/neg") {
TEST("require that operators have appropriate binding order") {
verify_operator_binding_order({ { Operator::Order::RIGHT, { "^" } },
- { Operator::Order::LEFT, { "*", "/" } },
+ { Operator::Order::LEFT, { "*", "/", "%" } },
{ Operator::Order::LEFT, { "+", "-" } },
{ Operator::Order::LEFT, { "==", "!=", "~=", "<", "<=", ">", ">=", "in" } },
{ Operator::Order::LEFT, { "&&" } },
diff --git a/eval/src/vespa/eval/eval/interpreted_function.cpp b/eval/src/vespa/eval/eval/interpreted_function.cpp
index 4fac6f2324d..053dbf0288c 100644
--- a/eval/src/vespa/eval/eval/interpreted_function.cpp
+++ b/eval/src/vespa/eval/eval/interpreted_function.cpp
@@ -355,6 +355,9 @@ struct ProgramBuilder : public NodeVisitor, public NodeTraverser {
void visit(const Div &) override {
program.emplace_back(op_binary<operation::Div>);
}
+ void visit(const Mod &) override {
+ program.emplace_back(op_binary<operation::Mod>);
+ }
void visit(const Pow &) override {
program.emplace_back(op_binary<operation::Pow>);
}
@@ -463,7 +466,7 @@ struct ProgramBuilder : public NodeVisitor, public NodeTraverser {
program.emplace_back(op_binary<operation::Pow>);
}
void visit(const Fmod &) override {
- program.emplace_back(op_binary<operation::Fmod>);
+ program.emplace_back(op_binary<operation::Mod>);
}
void visit(const Min &) override {
program.emplace_back(op_binary<operation::Min>);
diff --git a/eval/src/vespa/eval/eval/key_gen.cpp b/eval/src/vespa/eval/eval/key_gen.cpp
index cf2abc5bf47..65be8d172fd 100644
--- a/eval/src/vespa/eval/eval/key_gen.cpp
+++ b/eval/src/vespa/eval/eval/key_gen.cpp
@@ -42,42 +42,43 @@ struct KeyGen : public NodeVisitor, public NodeTraverser {
void visit(const Sub &) override { add_byte(21); }
void visit(const Mul &) override { add_byte(22); }
void visit(const Div &) override { add_byte(23); }
- void visit(const Pow &) override { add_byte(24); }
- void visit(const Equal &) override { add_byte(25); }
- void visit(const NotEqual &) override { add_byte(26); }
- void visit(const Approx &) override { add_byte(27); }
- void visit(const Less &) override { add_byte(28); }
- void visit(const LessEqual &) override { add_byte(29); }
- void visit(const Greater &) override { add_byte(30); }
- void visit(const GreaterEqual &) override { add_byte(31); }
- void visit(const In &) override { add_byte(32); }
- void visit(const And &) override { add_byte(33); }
- void visit(const Or &) override { add_byte(34); }
- void visit(const Cos &) override { add_byte(35); }
- void visit(const Sin &) override { add_byte(36); }
- void visit(const Tan &) override { add_byte(37); }
- void visit(const Cosh &) override { add_byte(38); }
- void visit(const Sinh &) override { add_byte(39); }
- void visit(const Tanh &) override { add_byte(40); }
- void visit(const Acos &) override { add_byte(41); }
- void visit(const Asin &) override { add_byte(42); }
- void visit(const Atan &) override { add_byte(43); }
- void visit(const Exp &) override { add_byte(44); }
- void visit(const Log10 &) override { add_byte(45); }
- void visit(const Log &) override { add_byte(46); }
- void visit(const Sqrt &) override { add_byte(47); }
- void visit(const Ceil &) override { add_byte(48); }
- void visit(const Fabs &) override { add_byte(49); }
- void visit(const Floor &) override { add_byte(50); }
- void visit(const Atan2 &) override { add_byte(51); }
- void visit(const Ldexp &) override { add_byte(52); }
- void visit(const Pow2 &) override { add_byte(53); }
- void visit(const Fmod &) override { add_byte(54); }
- void visit(const Min &) override { add_byte(55); }
- void visit(const Max &) override { add_byte(56); }
- void visit(const IsNan &) override { add_byte(57); }
- void visit(const Relu &) override { add_byte(58); }
- void visit(const Sigmoid &) override { add_byte(59); }
+ void visit(const Mod &) override { add_byte(24); }
+ void visit(const Pow &) override { add_byte(25); }
+ void visit(const Equal &) override { add_byte(26); }
+ void visit(const NotEqual &) override { add_byte(27); }
+ void visit(const Approx &) override { add_byte(28); }
+ void visit(const Less &) override { add_byte(29); }
+ void visit(const LessEqual &) override { add_byte(30); }
+ void visit(const Greater &) override { add_byte(31); }
+ void visit(const GreaterEqual &) override { add_byte(32); }
+ void visit(const In &) override { add_byte(33); }
+ void visit(const And &) override { add_byte(34); }
+ void visit(const Or &) override { add_byte(35); }
+ void visit(const Cos &) override { add_byte(36); }
+ void visit(const Sin &) override { add_byte(37); }
+ void visit(const Tan &) override { add_byte(38); }
+ void visit(const Cosh &) override { add_byte(39); }
+ void visit(const Sinh &) override { add_byte(40); }
+ void visit(const Tanh &) override { add_byte(41); }
+ void visit(const Acos &) override { add_byte(42); }
+ void visit(const Asin &) override { add_byte(43); }
+ void visit(const Atan &) override { add_byte(44); }
+ void visit(const Exp &) override { add_byte(45); }
+ void visit(const Log10 &) override { add_byte(46); }
+ void visit(const Log &) override { add_byte(47); }
+ void visit(const Sqrt &) override { add_byte(48); }
+ void visit(const Ceil &) override { add_byte(49); }
+ void visit(const Fabs &) override { add_byte(50); }
+ void visit(const Floor &) override { add_byte(51); }
+ void visit(const Atan2 &) override { add_byte(52); }
+ void visit(const Ldexp &) override { add_byte(53); }
+ void visit(const Pow2 &) override { add_byte(54); }
+ void visit(const Fmod &) override { add_byte(55); }
+ void visit(const Min &) override { add_byte(56); }
+ void visit(const Max &) override { add_byte(57); }
+ void visit(const IsNan &) override { add_byte(58); }
+ void visit(const Relu &) override { add_byte(59); }
+ void visit(const Sigmoid &) override { add_byte(60); }
// traverse
bool open(const Node &node) override { node.accept(*this); return true; }
diff --git a/eval/src/vespa/eval/eval/llvm/llvm_wrapper.cpp b/eval/src/vespa/eval/eval/llvm/llvm_wrapper.cpp
index e11a3154821..30c10464a35 100644
--- a/eval/src/vespa/eval/eval/llvm/llvm_wrapper.cpp
+++ b/eval/src/vespa/eval/eval/llvm/llvm_wrapper.cpp
@@ -459,6 +459,9 @@ struct FunctionBuilder : public NodeVisitor, public NodeTraverser {
llvm::Value *a = pop_double();
push(builder.CreateFDiv(a, b, "div_res"));
}
+ void visit(const Mod &) override {
+ make_call_2("fmod");
+ }
void visit(const Pow &) override {
make_call_2(llvm::Intrinsic::pow);
}
diff --git a/eval/src/vespa/eval/eval/node_types.cpp b/eval/src/vespa/eval/eval/node_types.cpp
index ac3894b93db..24dd6196d64 100644
--- a/eval/src/vespa/eval/eval/node_types.cpp
+++ b/eval/src/vespa/eval/eval/node_types.cpp
@@ -181,6 +181,7 @@ struct TypeResolver : public NodeVisitor, public NodeTraverser {
void visit(const Sub &node) override { resolve_op2(node); }
void visit(const Mul &node) override { resolve_op2(node); }
void visit(const Div &node) override { resolve_op2(node); }
+ void visit(const Mod &node) override { resolve_op2(node); }
void visit(const Pow &node) override { resolve_op2(node); }
void visit(const Equal &node) override { resolve_op2(node); }
void visit(const NotEqual &node) override { resolve_op2(node); }
diff --git a/eval/src/vespa/eval/eval/node_visitor.h b/eval/src/vespa/eval/eval/node_visitor.h
index 91b88bb9f6e..1bbcef24107 100644
--- a/eval/src/vespa/eval/eval/node_visitor.h
+++ b/eval/src/vespa/eval/eval/node_visitor.h
@@ -43,6 +43,7 @@ struct NodeVisitor {
virtual void visit(const nodes::Sub &) = 0;
virtual void visit(const nodes::Mul &) = 0;
virtual void visit(const nodes::Div &) = 0;
+ virtual void visit(const nodes::Mod &) = 0;
virtual void visit(const nodes::Pow &) = 0;
virtual void visit(const nodes::Equal &) = 0;
virtual void visit(const nodes::NotEqual &) = 0;
@@ -110,6 +111,7 @@ struct EmptyNodeVisitor : NodeVisitor {
void visit(const nodes::Sub &) override {}
void visit(const nodes::Mul &) override {}
void visit(const nodes::Div &) override {}
+ void visit(const nodes::Mod &) override {}
void visit(const nodes::Pow &) override {}
void visit(const nodes::Equal &) override {}
void visit(const nodes::NotEqual &) override {}
diff --git a/eval/src/vespa/eval/eval/operation.cpp b/eval/src/vespa/eval/eval/operation.cpp
index 0f12df6bd5d..f650f6ae194 100644
--- a/eval/src/vespa/eval/eval/operation.cpp
+++ b/eval/src/vespa/eval/eval/operation.cpp
@@ -55,6 +55,7 @@ double Add::eval(double a, double b) const { return (a + b); }
double Sub::eval(double a, double b) const { return (a - b); }
double Mul::eval(double a, double b) const { return (a * b); }
double Div::eval(double a, double b) const { return (a / b); }
+double Mod::eval(double a, double b) const { return std::fmod(a, b); }
double Pow::eval(double a, double b) const { return std::pow(a, b); }
double Equal::eval(double a, double b) const { return (a == b) ? 1.0 : 0.0; }
double NotEqual::eval(double a, double b) const { return (a != b) ? 1.0 : 0.0; }
@@ -83,7 +84,6 @@ double Fabs::eval(double a) const { return std::fabs(a); }
double Floor::eval(double a) const { return std::floor(a); }
double Atan2::eval(double a, double b) const { return std::atan2(a, b); }
double Ldexp::eval(double a, double b) const { return std::ldexp(a, b); }
-double Fmod::eval(double a, double b) const { return std::fmod(a, b); }
double Min::eval(double a, double b) const { return std::min(a, b); }
double Max::eval(double a, double b) const { return std::max(a, b); }
double IsNan::eval(double a) const { return std::isnan(a) ? 1.0 : 0.0; }
diff --git a/eval/src/vespa/eval/eval/operation.h b/eval/src/vespa/eval/eval/operation.h
index 2f1a3de54b2..f68998218eb 100644
--- a/eval/src/vespa/eval/eval/operation.h
+++ b/eval/src/vespa/eval/eval/operation.h
@@ -110,6 +110,7 @@ struct Add : Op2<Add> { double eval(double a, double b) const override; };
struct Sub : Op2<Sub> { double eval(double a, double b) const override; };
struct Mul : Op2<Mul> { double eval(double a, double b) const override; };
struct Div : Op2<Div> { double eval(double a, double b) const override; };
+struct Mod : Op2<Mod> { double eval(double a, double b) const override; };
struct Pow : Op2<Pow> { double eval(double a, double b) const override; };
struct Equal : Op2<Equal> { double eval(double a, double b) const override; };
struct NotEqual : Op2<NotEqual> { double eval(double a, double b) const override; };
@@ -138,7 +139,6 @@ struct Fabs : Op1<Fabs> { double eval(double a) const override; };
struct Floor : Op1<Floor> { double eval(double a) const override; };
struct Atan2 : Op2<Atan2> { double eval(double a, double b) const override; };
struct Ldexp : Op2<Ldexp> { double eval(double a, double b) const override; };
-struct Fmod : Op2<Fmod> { double eval(double a, double b) const override; };
struct Min : Op2<Min> { double eval(double a, double b) const override; };
struct Max : Op2<Max> { double eval(double a, double b) const override; };
struct IsNan : Op1<IsNan> { double eval(double a) const override; };
diff --git a/eval/src/vespa/eval/eval/operation_visitor.h b/eval/src/vespa/eval/eval/operation_visitor.h
index ea05cc2dcaf..4b61b2fece7 100644
--- a/eval/src/vespa/eval/eval/operation_visitor.h
+++ b/eval/src/vespa/eval/eval/operation_visitor.h
@@ -18,6 +18,7 @@ struct OperationVisitor {
virtual void visit(const operation::Sub &) = 0;
virtual void visit(const operation::Mul &) = 0;
virtual void visit(const operation::Div &) = 0;
+ virtual void visit(const operation::Mod &) = 0;
virtual void visit(const operation::Pow &) = 0;
virtual void visit(const operation::Equal &) = 0;
virtual void visit(const operation::NotEqual &) = 0;
@@ -46,7 +47,6 @@ struct OperationVisitor {
virtual void visit(const operation::Floor &) = 0;
virtual void visit(const operation::Atan2 &) = 0;
virtual void visit(const operation::Ldexp &) = 0;
- virtual void visit(const operation::Fmod &) = 0;
virtual void visit(const operation::Min &) = 0;
virtual void visit(const operation::Max &) = 0;
virtual void visit(const operation::IsNan &) = 0;
@@ -68,6 +68,7 @@ struct DefaultOperationVisitor : OperationVisitor {
virtual void visit(const operation::Sub &op) override { visitDefault(op); }
virtual void visit(const operation::Mul &op) override { visitDefault(op); }
virtual void visit(const operation::Div &op) override { visitDefault(op); }
+ virtual void visit(const operation::Mod &op) override { visitDefault(op); }
virtual void visit(const operation::Pow &op) override { visitDefault(op); }
virtual void visit(const operation::Equal &op) override { visitDefault(op); }
virtual void visit(const operation::NotEqual &op) override { visitDefault(op); }
@@ -96,7 +97,6 @@ struct DefaultOperationVisitor : OperationVisitor {
virtual void visit(const operation::Floor &op) override { visitDefault(op); }
virtual void visit(const operation::Atan2 &op) override { visitDefault(op); }
virtual void visit(const operation::Ldexp &op) override { visitDefault(op); }
- virtual void visit(const operation::Fmod &op) override { visitDefault(op); }
virtual void visit(const operation::Min &op) override { visitDefault(op); }
virtual void visit(const operation::Max &op) override { visitDefault(op); }
virtual void visit(const operation::IsNan &op) override { visitDefault(op); }
diff --git a/eval/src/vespa/eval/eval/operator_nodes.cpp b/eval/src/vespa/eval/eval/operator_nodes.cpp
index f021a67befa..11817630da4 100644
--- a/eval/src/vespa/eval/eval/operator_nodes.cpp
+++ b/eval/src/vespa/eval/eval/operator_nodes.cpp
@@ -28,6 +28,7 @@ OperatorRepo::OperatorRepo() : _map(), _max_size(0) {
add(nodes::Sub());
add(nodes::Mul());
add(nodes::Div());
+ add(nodes::Mod());
add(nodes::Pow());
add(nodes::Equal());
add(nodes::NotEqual());
diff --git a/eval/src/vespa/eval/eval/operator_nodes.h b/eval/src/vespa/eval/eval/operator_nodes.h
index 4e88b070eb4..e4dda484d68 100644
--- a/eval/src/vespa/eval/eval/operator_nodes.h
+++ b/eval/src/vespa/eval/eval/operator_nodes.h
@@ -157,6 +157,7 @@ public:
struct Sub : OperatorHelper<Sub> { Sub() : Helper("-", 101, LEFT) {}};
struct Mul : OperatorHelper<Mul> { Mul() : Helper("*", 102, LEFT) {}};
struct Div : OperatorHelper<Div> { Div() : Helper("/", 102, LEFT) {}};
+struct Mod : OperatorHelper<Mod> { Mod() : Helper("%", 102, LEFT) {}};
struct Pow : OperatorHelper<Pow> { Pow() : Helper("^", 103, RIGHT) {}};
struct Equal : OperatorHelper<Equal> { Equal() : Helper("==", 10, LEFT) {}};
struct NotEqual : OperatorHelper<NotEqual> { NotEqual() : Helper("!=", 10, LEFT) {}};
diff --git a/eval/src/vespa/eval/eval/test/eval_spec.cpp b/eval/src/vespa/eval/eval/test/eval_spec.cpp
index fe20af9c0bc..c4f349c614e 100644
--- a/eval/src/vespa/eval/eval/test/eval_spec.cpp
+++ b/eval/src/vespa/eval/eval/test/eval_spec.cpp
@@ -125,6 +125,7 @@ EvalSpec::add_arithmetic_cases() {
add_rule({"a", -5.0, 5.0}, {"b", -5.0, 5.0}, "(a-b)", [](double a, double b){ return (a - b); });
add_rule({"a", -5.0, 5.0}, {"b", -5.0, 5.0}, "(a*b)", [](double a, double b){ return (a * b); });
add_rule({"a", -5.0, 5.0}, {"b", -5.0, 5.0}, "(a/b)", [](double a, double b){ return (a / b); });
+ add_rule({"a", -1.0, 1.0}, {"b", -1.0, 1.0}, "(a%b)", [](double a, double b){ return std::fmod(a, b); });
add_rule({"a", -5.0, 5.0}, {"b", -5.0, 5.0}, "(a^b)", [](double a, double b){ return std::pow(a,b); });
add_expression({"a", "b", "c", "d"}, "(((a+1)*(b-1))/((c+1)/(d-1)))")
.add_case({0.0, 2.0, 0.0, 2.0}, 1.0)
diff --git a/eval/src/vespa/eval/eval/test/tensor_conformance.cpp b/eval/src/vespa/eval/eval/test/tensor_conformance.cpp
index fcccf0ac73b..4e321083252 100644
--- a/eval/src/vespa/eval/eval/test/tensor_conformance.cpp
+++ b/eval/src/vespa/eval/eval/test/tensor_conformance.cpp
@@ -1115,6 +1115,7 @@ struct TestContext {
TEST_DO(test_apply_op("a-b", operation::Sub(), Div10(N())));
TEST_DO(test_apply_op("a*b", operation::Mul(), Div10(N())));
TEST_DO(test_apply_op("a/b", operation::Div(), Div10(N())));
+ TEST_DO(test_apply_op("a%b", operation::Mod(), Div10(N())));
TEST_DO(test_apply_op("a^b", operation::Pow(), Div10(N())));
TEST_DO(test_apply_op("pow(a,b)", operation::Pow(), Div10(N())));
TEST_DO(test_apply_op("a==b", operation::Equal(), Div10(N())));
@@ -1128,7 +1129,7 @@ struct TestContext {
TEST_DO(test_apply_op("a||b", operation::Or(), Mask2Seq(SkipNth(3))));
TEST_DO(test_apply_op("atan2(a,b)", operation::Atan2(), Div10(N())));
TEST_DO(test_apply_op("ldexp(a,b)", operation::Ldexp(), Div10(N())));
- TEST_DO(test_apply_op("fmod(a,b)", operation::Fmod(), Div10(N())));
+ TEST_DO(test_apply_op("fmod(a,b)", operation::Mod(), Div10(N())));
TEST_DO(test_apply_op("min(a,b)", operation::Min(), Div10(N())));
TEST_DO(test_apply_op("max(a,b)", operation::Max(), Div10(N())));
}