GCC Code Coverage Report


Directory: src/
File: src/Interpolation.cpp
Date: 2026-09-03 17:04:53
Exec Total Coverage
Lines: 65 74 87.8%
Branches: 51 107 47.7%

Line Branch Exec Source
1 /*****************************************************************************
2 *
3 * Copyright (C) 2021 Jonathan Grahl <jonathan.grahl@igh.de>
4 * 2021 Florian Pose <florian.pose@igh.de>
5 *
6 * This file is part of the reta library (realtime-automation).
7 *
8 * The reta library is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published
10 * by the Free Software Foundation, either version 3 of the License, or (at
11 * your option) any later version.
12 *
13 * The reta library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with the reta library. If not, see <http://www.gnu.org/licenses/>.
20 *
21 ****************************************************************************/
22
23 #include "reta/Interpolation.h"
24
25 #include "Base.h"
26
27 #include <iostream>
28 #include <map>
29 #include <sstream>
30 #include <stdexcept>
31
32 using std::function;
33 using std::invalid_argument;
34 using std::lower_bound;
35 using std::make_unique;
36 using std::map;
37 using std::shared_ptr;
38 using std::string;
39 using std::stringstream;
40 using std::vector;
41
42 using std::cout;
43 using std::endl;
44
45 using namespace Reta;
46
47 /****************************************************************************/
48
49 32 struct RETA_LOCAL Interpolation::Impl : public Base
50 {
51 Impl(shared_ptr<Task> task,
52 const string &prefix,
53 const double tableInit[][2],
54 unsigned int tableRows,
55 unsigned int width);
56
57 void update(const vector<double> &);
58
59 86 unsigned int size() const { return output.size(); }
60
61 shared_ptr<Task> task;
62
63 map<double, double> table;
64 unsigned int tableRows;
65
66 vector<double> input;
67 vector<double> output;
68 };
69
70 /****************************************************************************/
71
72 34 Interpolation::Impl::Impl(
73 shared_ptr<Task> task,
74 const string &prefix,
75 const double tableInit[][2],
76 unsigned int tableRows,
77 34 unsigned int width) :
78 Base {prefix},
79 task {task},
80 tableRows {tableRows},
81 input(width, 0.0),
82
2/4
✓ Branch 5 taken 34 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 34 times.
✗ Branch 11 not taken.
36 output(width, 0.0)
83 {
84
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 checkZeroWidth(width);
85
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 32 times.
34 if (tableRows < 2) {
86
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
4 stringstream str;
87 str << __PRETTY_FUNCTION__ << " : " << prefix
88
4/8
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
2 << " Need at least 2 rows for the table!";
89
2/4
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
2 throw invalid_argument(str.str());
90 }
91
92
1/2
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
32 pdserv *pdserv {task->getPdServ()};
93
1/2
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
32 pdtask *pdtask {task->getPdTask()};
94
95
1/2
✓ Branch 3 taken 32 times.
✗ Branch 4 not taken.
64 pdserv_signal(
96
1/2
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
64 pdtask, 1, (prefix + "/Input").c_str(), pd_double_T, input.data(),
97 input.size(), NULL);
98
1/2
✓ Branch 3 taken 32 times.
✗ Branch 4 not taken.
64 pdserv_signal(
99
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
64 pdtask, 1, (prefix + "/Output").c_str(), pd_double_T,
100 32 output.data(), output.size(), NULL);
101
102
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 32 times.
160 for (unsigned int i = 0; i < tableRows; i++) {
103
1/2
✓ Branch 1 taken 128 times.
✗ Branch 2 not taken.
128 table[tableInit[i][0]] = tableInit[i][1];
104
105 {
106
2/4
✓ Branch 2 taken 128 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 128 times.
✗ Branch 7 not taken.
256 stringstream parameterPath, signalPath;
107
3/6
✓ Branch 1 taken 128 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 128 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 128 times.
✗ Branch 8 not taken.
128 parameterPath << prefix << "/Value/" << i;
108
3/6
✓ Branch 1 taken 128 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 128 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 128 times.
✗ Branch 8 not taken.
128 signalPath << prefix << "/ValueSignal/" << i;
109
110
1/2
✓ Branch 2 taken 128 times.
✗ Branch 3 not taken.
128 pdserv_parameter(
111
1/2
✓ Branch 1 taken 128 times.
✗ Branch 2 not taken.
256 pdserv, parameterPath.str().c_str(), 0666, pd_double_T,
112
1/2
✓ Branch 1 taken 128 times.
✗ Branch 2 not taken.
128 &table[tableInit[i][0]], 1, NULL, NULL, NULL);
113
114
1/2
✓ Branch 2 taken 128 times.
✗ Branch 3 not taken.
128 pdserv_signal(
115
1/2
✓ Branch 1 taken 128 times.
✗ Branch 2 not taken.
256 pdtask, 1, signalPath.str().c_str(), pd_double_T,
116
1/2
✓ Branch 1 taken 128 times.
✗ Branch 2 not taken.
128 &table[tableInit[i][0]], 1, NULL);
117 }
118 }
119 32 }
120
121 /****************************************************************************/
122
123 32 Interpolation::~Interpolation()
124 32 {}
125
126 /****************************************************************************/
127
128 /** Interpolation.
129 * In the update method, the associated y-value is calculated for a given
130 * x-value. Extrapolation is not possible. In case of a value outside the
131 * given table limits, the respective limit value is returned.
132 */
133 26 void Interpolation::Impl::update(const vector<double> &inputValueIn)
134 {
135 26 checkSize(inputValueIn, input);
136 24 input = inputValueIn;
137
138
2/2
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 24 times.
72 for (unsigned int i = 0; i < size(); i++) {
139
2/4
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 48 times.
✗ Branch 5 not taken.
48 auto iterator = table.lower_bound(input.at(i));
140
141
2/2
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 35 times.
61 if (iterator == table.begin()) {
142
1/2
✓ Branch 3 taken 13 times.
✗ Branch 4 not taken.
13 output.at(i) = table.begin()->second;
143 27 continue;
144 }
145
146
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 34 times.
36 if (iterator == table.end()) {
147
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 output.at(i) = table.rbegin()->second;
148 1 continue;
149 }
150
151
152 34 auto upperValue = iterator;
153 34 auto lowerValue = --iterator;
154
155 34 double dx = upperValue->first - lowerValue->first;
156 34 double dy = upperValue->second - lowerValue->second;
157
158
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 if (dx > 0.0) {
159
1/2
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
68 output.at(i) = lowerValue->second
160
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 + dy / dx * (input.at(i) - lowerValue->first);
161 }
162 }
163 24 }
164
165 /****************************************************************************/
166
167 34 Interpolation::Interpolation(
168 shared_ptr<Task> task,
169 const string &prefix,
170 const double tableInit[][2],
171 unsigned int tableRows,
172 34 unsigned int width) :
173 34 impl {make_unique<Impl>(task, prefix, tableInit, tableRows, width)}
174 32 {}
175
176 /****************************************************************************/
177
178 14 void Interpolation::update(double input)
179 {
180
2/4
✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 14 times.
✗ Branch 7 not taken.
14 impl->update(vector<double> {input});
181 14 }
182
183 /****************************************************************************/
184
185 12 void Interpolation::update(const vector<double> &input)
186 {
187 12 impl->update(input);
188 10 }
189
190 /****************************************************************************/
191
192 void Interpolation::update(function<double(unsigned int)> input)
193 {
194 vector<double> inputVector(size());
195
196 for (unsigned int i = 0; i < size(); i++) {
197 inputVector.at(i) = input(i);
198 }
199
200 impl->update(inputVector);
201 }
202
203 /****************************************************************************/
204
205 53 double Interpolation::getOutput(unsigned int i) const
206 {
207 53 return impl->output.at(i);
208 }
209
210 /****************************************************************************/
211
212 vector<double> Interpolation::getOutputVector() const
213 {
214 return impl->output;
215 }
216
217 /****************************************************************************/
218
219 14 unsigned int Interpolation::size() const
220 {
221 14 return impl->size();
222 }
223
224 /****************************************************************************/
225
226 unsigned int Interpolation::rows() const
227 {
228 return impl->tableRows;
229 6 }
230
231 /****************************************************************************/
232