diff options
9 files changed, 53 insertions, 3 deletions
diff --git a/searchlib/abi-spec.json b/searchlib/abi-spec.json index e8e3a3cb133..2468fd0c5c7 100644 --- a/searchlib/abi-spec.json +++ b/searchlib/abi-spec.json @@ -1034,6 +1034,7 @@ "public static final int LDEXP", "public static final int POW", "public static final int BIT", + "public static final int HAMMING", "public static final int MAP", "public static final int REDUCE", "public static final int JOIN", @@ -1389,7 +1390,8 @@ "public static final enum com.yahoo.searchlib.rankingexpression.rule.Function max", "public static final enum com.yahoo.searchlib.rankingexpression.rule.Function min", "public static final enum com.yahoo.searchlib.rankingexpression.rule.Function pow", - "public static final enum com.yahoo.searchlib.rankingexpression.rule.Function bit" + "public static final enum com.yahoo.searchlib.rankingexpression.rule.Function bit", + "public static final enum com.yahoo.searchlib.rankingexpression.rule.Function hamming" ] }, "com.yahoo.searchlib.rankingexpression.rule.FunctionNode": { diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/TensorValue.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/TensorValue.java index e41732f9d16..33ba3c6ef4b 100644 --- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/TensorValue.java +++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/TensorValue.java @@ -157,6 +157,7 @@ public class TensorValue extends Value { case fmod: return value.fmod(argument); case ldexp: return value.ldexp(argument); case bit: return value.bit(argument); + case hamming: return value.hamming(argument); default: throw new UnsupportedOperationException("Cannot combine two tensors using " + function); } } diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/Function.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/Function.java index 16aa947986d..3958711f74b 100644 --- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/Function.java +++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/Function.java @@ -46,7 +46,8 @@ public enum Function implements Serializable { max(2) { public double evaluate(double x, double y) { return max(x,y); } }, min(2) { public double evaluate(double x, double y) { return min(x,y); } }, pow(2) { public double evaluate(double x, double y) { return pow(x,y); } }, - bit(2) { public double evaluate(double x, double y) { return ((int)y < 8 && (int)y >= 0 && ((int)x & (1 << (int)y)) != 0) ? 1.0 : 0.0; } }; + bit(2) { public double evaluate(double x, double y) { return ((int)y < 8 && (int)y >= 0 && ((int)x & (1 << (int)y)) != 0) ? 1.0 : 0.0; } }, + hamming(2) { public double evaluate(double x, double y) { return ScalarFunctions.Hamming.hamming(x, y); } }; private final int arity; diff --git a/searchlib/src/main/javacc/RankingExpressionParser.jj b/searchlib/src/main/javacc/RankingExpressionParser.jj index 99eff010628..7bfbfd6c005 100755 --- a/searchlib/src/main/javacc/RankingExpressionParser.jj +++ b/searchlib/src/main/javacc/RankingExpressionParser.jj @@ -124,6 +124,7 @@ TOKEN : // MIN <POW: "pow"> | <BIT: "bit"> | + <HAMMING: "hamming"> | <MAP: "map"> | <REDUCE: "reduce"> | @@ -735,7 +736,8 @@ Function binaryFunctionName() : { } <MAX> { return Function.max; } | <MIN> { return Function.min; } | <POW> { return Function.pow; } | - <BIT> { return Function.bit; } + <BIT> { return Function.bit; } | + <HAMMING> { return Function.hamming; } } List<ExpressionNode> expressionList() : diff --git a/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/evaluation/EvaluationTestCase.java b/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/evaluation/EvaluationTestCase.java index 4a3c4b248be..246dbcb2b1e 100644 --- a/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/evaluation/EvaluationTestCase.java +++ b/searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/evaluation/EvaluationTestCase.java @@ -288,6 +288,8 @@ public class EvaluationTestCase { tester.assertEvaluates("{ {h:0}:1.5, {h:1}:1.5 }", "0.5 + tensor0", "{ {h:0}:1.0,{h:1}:1.0 }"); tester.assertEvaluates("{ {x:0,y:0}:0, {x:1,y:0}:0 }", "atan2(tensor0, tensor1)", "{ {x:0}:0, {x:1}:0 }", "{ {y:0}:1 }"); + tester.assertEvaluates("{ {x:0,y:0}:2, {x:1,y:0}:7 }", + "hamming(tensor0, tensor1)", "{ {x:0}:97, {x:1}:-1 }", "{ {y:0}:1 }"); tester.assertEvaluates("{ {x:0,y:0}:0, {x:1,y:0}:1 }", "tensor0 > tensor1", "{ {x:0}:3, {x:1}:7 }", "{ {y:0}:5 }"); tester.assertEvaluates("{ {x:0,y:0}:1, {x:1,y:0}:0 }", diff --git a/searchlib/src/tests/rankingexpression/rankingexpressionlist b/searchlib/src/tests/rankingexpression/rankingexpressionlist index 77b2294c668..d41570732d9 100644 --- a/searchlib/src/tests/rankingexpression/rankingexpressionlist +++ b/searchlib/src/tests/rankingexpression/rankingexpressionlist @@ -87,6 +87,7 @@ floor(10) relu(10) sigmoid(10) atan2(10, 20); atan2(10,20) +hamming(42, -16); hamming(42,-16) ldexp(10, 20); ldexp(10,20) pow(10, 20); pow(10,20) fmod(10, 20); fmod(10,20) diff --git a/vespajlib/abi-spec.json b/vespajlib/abi-spec.json index e5d5b8ba5b6..e68a37b15b6 100644 --- a/vespajlib/abi-spec.json +++ b/vespajlib/abi-spec.json @@ -1203,6 +1203,7 @@ "public com.yahoo.tensor.Tensor notEqual(com.yahoo.tensor.Tensor)", "public com.yahoo.tensor.Tensor approxEqual(com.yahoo.tensor.Tensor)", "public com.yahoo.tensor.Tensor bit(com.yahoo.tensor.Tensor)", + "public com.yahoo.tensor.Tensor hamming(com.yahoo.tensor.Tensor)", "public com.yahoo.tensor.Tensor avg()", "public com.yahoo.tensor.Tensor avg(java.lang.String)", "public com.yahoo.tensor.Tensor avg(java.util.List)", @@ -2189,6 +2190,22 @@ ], "fields": [] }, + "com.yahoo.tensor.functions.ScalarFunctions$Hamming": { + "superClass": "java.lang.Object", + "interfaces": [ + "java.util.function.DoubleBinaryOperator" + ], + "attributes": [ + "public" + ], + "methods": [ + "public void <init>()", + "public static double hamming(double, double)", + "public double applyAsDouble(double, double)", + "public java.lang.String toString()" + ], + "fields": [] + }, "com.yahoo.tensor.functions.ScalarFunctions$LeakyRelu": { "superClass": "java.lang.Object", "interfaces": [ @@ -2557,6 +2574,7 @@ "public static java.util.function.DoubleBinaryOperator pow()", "public static java.util.function.DoubleBinaryOperator squareddifference()", "public static java.util.function.DoubleBinaryOperator subtract()", + "public static java.util.function.DoubleBinaryOperator hamming()", "public static java.util.function.DoubleUnaryOperator abs()", "public static java.util.function.DoubleUnaryOperator acos()", "public static java.util.function.DoubleUnaryOperator asin()", diff --git a/vespajlib/src/main/java/com/yahoo/tensor/Tensor.java b/vespajlib/src/main/java/com/yahoo/tensor/Tensor.java index ab475e25387..3d4536d9249 100644 --- a/vespajlib/src/main/java/com/yahoo/tensor/Tensor.java +++ b/vespajlib/src/main/java/com/yahoo/tensor/Tensor.java @@ -36,6 +36,7 @@ import java.util.function.Function; import java.util.stream.Collectors; import static com.yahoo.text.Ascii7BitMatcher.charsAndNumbers; +import static com.yahoo.tensor.functions.ScalarFunctions.Hamming; /** * A multidimensional array which can be used in computations. @@ -241,6 +242,7 @@ public interface Tensor { default Tensor notEqual(Tensor argument) { return join(argument, (a, b) -> ( a != b ? 1.0 : 0.0)); } default Tensor approxEqual(Tensor argument) { return join(argument, (a, b) -> ( approxEquals(a,b) ? 1.0 : 0.0)); } default Tensor bit(Tensor argument) { return join(argument, (a,b) -> ((int)b < 8 && (int)b >= 0 && ((int)a & (1 << (int)b)) != 0) ? 1.0 : 0.0); } + default Tensor hamming(Tensor argument) { return join(argument, (a,b) -> Hamming.hamming(a,b)); } default Tensor avg() { return avg(Collections.emptyList()); } default Tensor avg(String dimension) { return avg(Collections.singletonList(dimension)); } diff --git a/vespajlib/src/main/java/com/yahoo/tensor/functions/ScalarFunctions.java b/vespajlib/src/main/java/com/yahoo/tensor/functions/ScalarFunctions.java index 3ee9e67cdd6..d6fcd17b8fb 100644 --- a/vespajlib/src/main/java/com/yahoo/tensor/functions/ScalarFunctions.java +++ b/vespajlib/src/main/java/com/yahoo/tensor/functions/ScalarFunctions.java @@ -33,6 +33,7 @@ public class ScalarFunctions { public static DoubleBinaryOperator pow() { return new Pow(); } public static DoubleBinaryOperator squareddifference() { return new SquaredDifference(); } public static DoubleBinaryOperator subtract() { return new Subtract(); } + public static DoubleBinaryOperator hamming() { return new Hamming(); } public static DoubleUnaryOperator abs() { return new Abs(); } public static DoubleUnaryOperator acos() { return new Acos(); } @@ -152,6 +153,26 @@ public class ScalarFunctions { public String toString() { return "f(a,b)(a - b)"; } } + + public static class Hamming implements DoubleBinaryOperator { + public static double hamming(double left, double right) { + double distance = 0; + byte a = (byte) left; + byte b = (byte) right; + for (int i = 0; i < 8; i++) { + byte bit = (byte) (1 << i); + if ((a & bit) != (b & bit)) { + distance += 1; + } + } + return distance; + } + @Override + public double applyAsDouble(double left, double right) { return hamming(left, right); } + @Override + public String toString() { return "f(a,b)(hamming(a,b))"; } + } + // Unary operators ------------------------------------------------------------------------------ |