aboutsummaryrefslogtreecommitdiffstats
path: root/searchlib/src/vespa/searchlib/expression/interpolatedlookupfunctionnode.cpp
blob: fbc69a512d3bc60e3132e0ae932d99408abcb942 (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
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "interpolatedlookupfunctionnode.h"
#include "floatresultnode.h"
#include "simple_interpolate.h"
#include <vespa/searchcommon/attribute/iattributecontext.h>
#include <vespa/searchlib/common/converters.h>
#include <vespa/vespalib/util/stringfmt.h>

namespace search::expression {

using vespalib::Serializer;
using vespalib::Deserializer;

IMPLEMENT_EXPRESSIONNODE(InterpolatedLookup, AttributeNode);

InterpolatedLookup::InterpolatedLookup() noexcept
    : AttributeNode(),
      _lookupExpression()
{
}

InterpolatedLookup::~InterpolatedLookup() = default;

InterpolatedLookup::InterpolatedLookup(const vespalib::string &attribute, ExpressionNode::UP arg)
    : AttributeNode(attribute),
      _lookupExpression(std::move(arg))
{
}

InterpolatedLookup::InterpolatedLookup(const attribute::IAttributeVector &attr, ExpressionNode::UP arg)
    : AttributeNode(attr),
      _lookupExpression(std::move(arg))
{
}


InterpolatedLookup::InterpolatedLookup(const InterpolatedLookup &rhs) = default;
InterpolatedLookup & InterpolatedLookup::operator= (const InterpolatedLookup &rhs) = default;

namespace {

class InterpolateHandler : public AttributeNode::Handler {
public:
    InterpolateHandler(FloatResultNode & result, const ExpressionNode * lookupExpression) noexcept
        : AttributeNode::Handler(),
          _lookupExpression(lookupExpression),
          _result(result),
          _values()
    { }
    void handle(const AttributeResult & r) override;
private:
    const ExpressionNode *_lookupExpression;
    FloatResultNode      &_result;
    std::vector<double>   _values;
};

void
InterpolateHandler::handle(const AttributeResult &r) {
    _lookupExpression->execute();
    double lookup = _lookupExpression->getResult()->getFloat();
    size_t numValues = r.getAttribute()->getValueCount(r.getDocId());
    _values.resize(numValues);
    r.getAttribute()->get(r.getDocId(), _values.data(), _values.size());
    _result.set(simple_interpolate(_values, lookup));
}

}

std::pair<std::unique_ptr<ResultNode>, std::unique_ptr<AttributeNode::Handler>>
InterpolatedLookup::createResultHandler(bool, const attribute::IAttributeVector &) const {
    auto result = std::make_unique<FloatResultNode>();
    auto handler = std::make_unique<InterpolateHandler>(*result, _lookupExpression.get());
    return { std::move(result), std::move(handler) };
}

Serializer &
InterpolatedLookup::onSerialize(Serializer & os) const
{
    // Here we are doing a dirty skipping AttributeNode in the inheritance.
    // This is due to refactoring and the need to keep serialization the same.
    FunctionNode::onSerialize(os);
    os << uint32_t(1u) << _lookupExpression; // Simulating a single element vector.
    os << _attributeName;
    return os;
}

Deserializer &
InterpolatedLookup::onDeserialize(Deserializer & is)
{
    // See comment in onSerialize method.
    FunctionNode::onDeserialize(is);
    uint32_t count(0);
    is >> count;
    if (count > 0) {
        is >> _lookupExpression;
    } else {
        _lookupExpression.reset();
    }
    is >> _attributeName;
    return is;
}

void
InterpolatedLookup::visitMembers(vespalib::ObjectVisitor &visitor) const
{
    AttributeNode::visitMembers(visitor);
    visit(visitor, "index", *_lookupExpression);
}

void
InterpolatedLookup::selectMembers(const vespalib::ObjectPredicate & predicate, vespalib::ObjectOperation & operation)
{
    AttributeNode::selectMembers(predicate, operation);
    if (_lookupExpression) {
        _lookupExpression->select(predicate, operation);
    }
}

}