aboutsummaryrefslogtreecommitdiffstats
path: root/searchlib/src/vespa/searchlib/attribute/loadedvalue.h
blob: 70a125305331bd4e44510b0f5206c5693c470c4a (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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#pragma once

#include "i_enum_store.h"
#include <vespa/searchcommon/common/undefinedvalues.h>
#include <vespa/vespalib/datastore/entryref.h>

namespace search
{

namespace attribute
{

/*
 * Temporary representation of enumerated attribute loaded from non-enumerated
 * save file (i.e. old save format).
 */
template <typename T>
class LoadedValue
{
public:
    LoadedValue()
        : _docId(0),
          _idx(0),
          _pidx(0),
          _weight(1)
    {
        memset(&_value, 0, sizeof(_value));
    }

    class DocRadix
    {
    public:
        uint64_t
        operator() (const LoadedValue<T> & v) const
        {
            uint64_t tmp(v._docId);
            return tmp << 32 | v._idx;
        }
    };

    class DocOrderCompare
    {
    public:
        bool
        operator()(const LoadedValue<T> &x,
                   const LoadedValue<T> &y) const
        {
            int32_t diff(x._docId - y._docId);
            if (diff == 0) {
                diff = x._idx - y._idx;
            }
            return diff < 0;
        }
    };

    IEnumStore::Index
    getEidx() const
    {
        return IEnumStore::Index(vespalib::datastore::EntryRef(_value._eidx));
    }

    void
    setEidx(IEnumStore::Index v)
    {
        _value._eidx = v.ref();
    }

    T
    getValue() const
    {
        return _value._value;
    }

    inline void
    setValue(T v)
    {
        _value._value = v;
    }

    int32_t
    getWeight() const
    {
        return _weight;
    }

    void
    setWeight(int32_t v)
    {
        _weight = v;
    }

    inline bool
    operator<(const LoadedValue<T> &rhs) const
    {
        return _value._value < rhs._value._value;
    }

    union Value {
        T        _value;
        uint32_t _eidx;
    };

    uint32_t                         _docId;
    uint32_t                         _idx;
    vespalib::datastore::EntryRef    _pidx;
private:
    int32_t                          _weight;
    Value                            _value;
};


template <>
inline void
LoadedValue<float>::setValue(float v)
{
    // Consolidate nans during load to avoid sort order issues
    _value._value = isUndefined<float>(v) ? getUndefined<float>() : v;
}

template <>
inline void
LoadedValue<double>::setValue(double v)
{
    // Consolidate nans during load to avoid sort order issues
    _value._value = isUndefined<double>(v) ? getUndefined<double>() : v;
}


template <>
inline bool
LoadedValue<float>::operator<(const LoadedValue<float> &rhs) const
{
    if (std::isnan(_value._value)) {
        return !std::isnan(rhs._value._value);
    }
    if (std::isnan(rhs._value._value)) {
        return false;
    }
    return _value._value < rhs._value._value;
}


template <>
inline bool
LoadedValue<double>::operator<(const LoadedValue<double> &rhs) const
{
    if (std::isnan(_value._value)) {
        return !std::isnan(rhs._value._value);
    }
    if (std::isnan(rhs._value._value)) {
        return false;
    }
    return _value._value < rhs._value._value;
}


} // namespace attribute

} // namespace search