summaryrefslogtreecommitdiffstats
path: root/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/Value.java
blob: 5de2138147e951eaccf95ac7983f749049b45a72 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.searchlib.rankingexpression.evaluation;

import com.yahoo.searchlib.rankingexpression.rule.Function;
import com.yahoo.tensor.Tensor;
import com.yahoo.tensor.TensorAddress;
import com.yahoo.tensor.TensorType;

/**
 * The result of a ranking expression evaluation.
 * Concrete subclasses of this provides implementations of these methods or throws
 * UnsupportedOperationException if the operation is not supported.
 *
 * @author bratseth
 */
public abstract class Value {

    private boolean frozen = false;

    /** Returns the type of this value */
    public abstract TensorType type();

    /** Returns this value as a double, or throws UnsupportedOperationException if it cannot be represented as a double */
    public abstract double asDouble();

    /** Returns this value as a double value, or throws UnsupportedOperationException if it cannot be represented as a double */
    public DoubleValue asDoubleValue() {
        return new DoubleValue(asDouble());
    }

    /** Returns true if this has a double value which is NaN */
    public boolean isNaN() {
        return hasDouble() && Double.isNaN(asDouble());
    }

    /** Returns this as a tensor value */
    public abstract Tensor asTensor();

    /** A utility method for wrapping a double in a rank 0 tensor */
    protected Tensor doubleAsTensor(double value) {
        return Tensor.Builder.of(TensorType.empty).cell(TensorAddress.of(), value).build();
    }

    /** Returns true if this value can return itself as a double, i.e asDoubleValue will return a value and not throw */
    public abstract boolean hasDouble();

    /** Returns this value as a boolean. */
    public abstract boolean asBoolean();

    public abstract Value negate();

    public abstract Value not();

    public abstract Value or(Value value);
    public abstract Value and(Value value);
    public abstract Value largerOrEqual(Value value);
    public abstract Value larger(Value value);
    public abstract Value smallerOrEqual(Value value);
    public abstract Value smaller(Value value);
    public abstract Value approxEqual(Value value);
    public abstract Value notEqual(Value value);
    public abstract Value equal(Value value);
    public abstract Value add(Value value);
    public abstract Value subtract(Value value);
    public abstract Value multiply(Value value);
    public abstract Value divide(Value value);
    public abstract Value modulo(Value value);
    public abstract Value power(Value value);

    /** Perform the given binary function on this value and the given value */
    public abstract Value function(Function function, Value value);

    /**
     * Irreversibly makes this immutable. Overriders must always call super.freeze() and return this
     *
     * @return this for convenience
     */
    public Value freeze() {
        frozen = true;
        return this;
    }

    /** Returns true if this is immutable, false otherwise */
    public final boolean isFrozen() { return frozen; }

    /** Returns this is mutable, or a mutable copy otherwise */
    public abstract Value asMutable();

    @Override
    public abstract String toString();

    @Override
    public abstract boolean equals(Object other);

    /** Returns a hash which only depends on the content of this value. */
    @Override
    public abstract int hashCode();

    /**
     * Parses the given string to a value and returns it.
     * Different subtypes of Value will be returned depending on the string.
     *
     * @return a mutable Value
     * @throws IllegalArgumentException if the given string is not parseable as a value
     */
    public static Value parse(String value) {
        if (value.equals("true"))
            return new BooleanValue(true);
        else if (value.equals("false"))
            return new BooleanValue(false);
        else if (value.startsWith("\"") || value.startsWith("'"))
            return new StringValue(value);
        else if (value.startsWith("{"))
            return new TensorValue(Tensor.from(value));
        else if ((value.indexOf('.') == -1) && (value.indexOf('e') == -1) && (value.indexOf('E') == -1))
            return new LongValue(Long.parseLong(value));
         else
             return new DoubleValue(Double.parseDouble(value));
    }

    public static Value of(Tensor tensor) {
        return new TensorValue(tensor);
    }

    public static Value of(double scalar) {
        return new DoubleValue(scalar);
    }

}