summaryrefslogtreecommitdiff
path: root/matching/include/cell_with_value.hpp
blob: 88b25692fb1df1c77b0b0714f9e00629582e8212 (plain)
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
namespace md {

#ifdef MD_DEBUG
    long long int CellWithValue<Real>::max_id = 0;
#endif

    template<class Real>
    Real CellWithValue<Real>::value_at(ValuePoint vp) const
    {
        switch(vp) {
            case ValuePoint::upper_left :
                return upper_left_value_;
            case ValuePoint::upper_right :
                return upper_right_value_;
            case ValuePoint::lower_left :
                return lower_left_value_;
            case ValuePoint::lower_right :
                return lower_right_value_;
            case ValuePoint::center:
                return central_value_;
        }
        // to shut up compiler warning
        return 1.0 / 0.0;
    }

    template<class Real>
    bool CellWithValue<Real>::has_value_at(ValuePoint vp) const
    {
        switch(vp) {
            case ValuePoint::upper_left :
                return upper_left_value_ >= 0;
            case ValuePoint::upper_right :
                return upper_right_value_ >= 0;
            case ValuePoint::lower_left :
                return lower_left_value_ >= 0;
            case ValuePoint::lower_right :
                return lower_right_value_ >= 0;
            case ValuePoint::center:
                return central_value_ >= 0;
        }
        // to shut up compiler warning
        return 1.0 / 0.0;
    }

    template<class Real>
    DualPoint<Real> CellWithValue<Real>::value_point(md::ValuePoint vp) const
    {
        switch(vp) {
            case ValuePoint::upper_left :
                return dual_box().upper_left();
            case ValuePoint::upper_right :
                return dual_box().upper_right();
            case ValuePoint::lower_left :
                return dual_box().lower_left();
            case ValuePoint::lower_right :
                return dual_box().lower_right();
            case ValuePoint::center:
                return dual_box().center();
        }
        // to shut up compiler warning
        return DualPoint<Real>();
    }

    template<class Real>
    bool CellWithValue<Real>::has_corner_value() const
    {
        return has_lower_left_value() or has_lower_right_value() or has_upper_left_value()
                or has_upper_right_value();
    }

    template<class Real>
    Real CellWithValue<Real>::stored_upper_bound() const
    {
        assert(has_max_possible_value_);
        return max_possible_value_;
    }

    template<class Real>
    Real CellWithValue<Real>::max_corner_value() const
    {
        return std::max({lower_left_value_, lower_right_value_, upper_left_value_, upper_right_value_});
    }

    template<class Real>
    Real CellWithValue<Real>::min_value() const
    {
        Real result = std::numeric_limits<Real>::max();
        for(auto vp : k_all_vps) {
            if (not has_value_at(vp)) {
                continue;
            }
            result = std::min(result, value_at(vp));
        }
        return result;
    }

    template<class Real>
    std::vector<CellWithValue<Real>> CellWithValue<Real>::get_refined_cells() const
    {
        std::vector<CellWithValue<Real>> result;
        result.reserve(4);
        for(const auto& refined_box : dual_box_.refine()) {

            CellWithValue<Real> refined_cell(refined_box, level() + 1);

#ifdef MD_DEBUG
            refined_cell.parent_ids = parent_ids;
            refined_cell.parent_ids.push_back(id);
            refined_cell.id = ++max_id;
#endif

            if (refined_box.lower_left() == dual_box_.lower_left()) {
                // _|_
                // H|_

                refined_cell.set_value_at(ValuePoint::lower_left, lower_left_value_);
                refined_cell.set_value_at(ValuePoint::upper_right, central_value_);

            } else if (refined_box.upper_right() == dual_box_.upper_right()) {
                // _|H
                // _|_

                refined_cell.set_value_at(ValuePoint::lower_left, central_value_);
                refined_cell.set_value_at(ValuePoint::upper_right, upper_right_value_);

            } else if (refined_box.lower_right() == dual_box_.lower_right()) {
                // _|_
                // _|H

                refined_cell.set_value_at(ValuePoint::lower_right, lower_right_value_);
                refined_cell.set_value_at(ValuePoint::upper_left, central_value_);

            } else if (refined_box.upper_left() == dual_box_.upper_left()) {

                // H|_
                // _|_

                refined_cell.set_value_at(ValuePoint::lower_right, central_value_);
                refined_cell.set_value_at(ValuePoint::upper_left, upper_left_value_);
            }
            result.emplace_back(refined_cell);
        }
        return result;
    }

    template<class Real>
    void CellWithValue<Real>::set_value_at(ValuePoint vp, Real new_value)
    {
        if (has_value_at(vp))
            spd::error("CellWithValue<Real>: trying to re-assign value!, this = {}, vp = {}", *this, vp);

        switch(vp) {
            case ValuePoint::upper_left :
                upper_left_value_ = new_value;
                break;
            case ValuePoint::upper_right :
                upper_right_value_ = new_value;
                break;
            case ValuePoint::lower_left :
                lower_left_value_ = new_value;
                break;
            case ValuePoint::lower_right :
                lower_right_value_ = new_value;
                break;
            case ValuePoint::center:
                central_value_ = new_value;
                break;
        }
    }

    template<class Real>
    int CellWithValue<Real>::num_values() const
    {
        int result = 0;
        for(ValuePoint vp : k_all_vps) {
            result += has_value_at(vp);
        }
        return result;
    }


    template<class Real>
    void CellWithValue<Real>::set_max_possible_value(Real new_upper_bound)
    {
        assert(new_upper_bound >= central_value_);
        assert(new_upper_bound >= lower_left_value_);
        assert(new_upper_bound >= lower_right_value_);
        assert(new_upper_bound >= upper_left_value_);
        assert(new_upper_bound >= upper_right_value_);
        has_max_possible_value_ = true;
        max_possible_value_ = new_upper_bound;
    }


    template<class Real>
    std::ostream& operator<<(std::ostream& os, const CellWithValue<Real>& cell)
    {
        os << "CellWithValue(box = " << cell.dual_box() << ", ";

#ifdef MD_DEBUG
        os << "id = " << cell.id;
        if (not cell.parent_ids.empty())
            os << ", parent_ids = " << container_to_string(cell.parent_ids) << ", ";
#endif

        for(ValuePoint vp : k_all_vps) {
            if (cell.has_value_at(vp)) {
                os << "value = " << cell.value_at(vp);
                os << ", at " << vp << " " << cell.value_point(vp);
            }
        }

        os << ", max_corner_value = ";
        if (cell.has_max_possible_value()) {
            os << cell.stored_upper_bound();
        } else {
            os << "-";
        }

        os << ", level = " << cell.level() << ")";
        return os;
    }

} // namespace md