25
25
26
26
using namespace correction ;
27
27
28
+ // ! helper function for parsing flow behavior from string
29
+ _FlowBehavior parse_flowbehavior (const rapidjson::Value& flowbehavior) {
30
+ if ( flowbehavior == " clamp" ) {
31
+ return _FlowBehavior::clamp;
32
+ }
33
+ else if ( flowbehavior == " error" ) {
34
+ return _FlowBehavior::error;
35
+ }
36
+ else if ( flowbehavior == " wrap" ) {
37
+ return _FlowBehavior::wrap;
38
+ }
39
+ else {
40
+ return _FlowBehavior::value;
41
+ }
42
+ }
43
+
28
44
class correction ::JSONObject {
29
45
public:
30
46
JSONObject (rapidjson::Value::ConstObject&& json) : json_(json) { }
@@ -149,20 +165,33 @@ namespace {
149
165
return bins->n ; // the default value is stored at the end of the content array, after the last bin
150
166
case _FlowBehavior::clamp:
151
167
return value < bins->low ? 0 : bins->n - 1 ; // assuming we always have at least 1 bin
168
+ case _FlowBehavior::wrap:
169
+ break ;
152
170
case _FlowBehavior::error:
153
171
const std::string belowOrAbove = value < bins->low ? " below" : " above" ;
154
172
auto msg = " Index " + belowOrAbove + " bounds in " + name + " for input argument " + std::to_string (variableIdx) + " value: " + std::to_string (value);
155
173
throw std::runtime_error (std::move (msg));
156
174
}
157
175
}
158
176
159
- std::size_t binIdx = bins->n * ((value - bins->low ) / (bins->high - bins->low ));
177
+ double norm_value = ((value - bins->low ) / (bins->high - bins->low ));
178
+ if (flow == _FlowBehavior::wrap) {
179
+ norm_value -= std::floor (norm_value);
180
+ }
181
+ std::size_t binIdx = bins->n * norm_value;
160
182
return binIdx;
161
183
}
162
184
163
185
// otherwise we have non-uniform binning
164
186
using namespace std ::string_literals;
165
187
const auto bins = std::get<_NonUniformBins>(bins_);
188
+ if ( flow == _FlowBehavior::wrap ) {
189
+ double low = bins[0 ];
190
+ double high = bins[bins.size () - 1 ];
191
+ double norm_value = (value - low) / (high - low);
192
+ norm_value -= std::floor (norm_value);
193
+ value = low + norm_value * (high - low);
194
+ }
166
195
167
196
auto it = std::upper_bound (std::begin (bins), std::end (bins), value);
168
197
if ( it == std::begin (bins) ) { // underflow
@@ -172,6 +201,9 @@ namespace {
172
201
else if ( flow == _FlowBehavior::error ) {
173
202
throw std::runtime_error (" Index below bounds in " s + name + " for input argument " + std::to_string (variableIdx) + " value: " + std::to_string (value));
174
203
}
204
+ else if ( flow == _FlowBehavior::wrap ) {
205
+ throw std::logic_error (" I should not have ever seen an underflow" );
206
+ }
175
207
else { // clamp
176
208
it++;
177
209
}
@@ -183,6 +215,9 @@ namespace {
183
215
else if ( flow == _FlowBehavior::error ) {
184
216
throw std::runtime_error (" Index above bounds in " s + name + " for input argument " + std::to_string (variableIdx) + " value: " + std::to_string (value));
185
217
}
218
+ else if ( flow == _FlowBehavior::wrap ) {
219
+ throw std::logic_error (" I should not have ever seen an overflow" );
220
+ }
186
221
else { // clamp
187
222
it--;
188
223
}
@@ -461,15 +496,9 @@ Binning::Binning(const JSONObject& json, const Correction& context)
461
496
}
462
497
Content default_value{0 .};
463
498
const auto & flowbehavior = json.getRequiredValue (" flow" );
464
- if ( flowbehavior == " clamp" ) {
465
- flow_ = _FlowBehavior::clamp;
466
- }
467
- else if ( flowbehavior == " error" ) {
468
- flow_ = _FlowBehavior::error;
469
- }
470
- else {
471
- flow_ = _FlowBehavior::value;
472
- default_value = resolve_content (flowbehavior, context);
499
+ flow_ = parse_flowbehavior (flowbehavior);
500
+ if (flow_ == _FlowBehavior::value) {
501
+ default_value = resolve_content (flowbehavior, context);
473
502
}
474
503
475
504
// set bin contents
@@ -540,16 +569,9 @@ MultiBinning::MultiBinning(const JSONObject& json, const Correction& context)
540
569
}
541
570
542
571
const auto & flowbehavior = json.getRequiredValue (" flow" );
543
- if ( flowbehavior == " clamp" ) {
544
- flow_ = _FlowBehavior::clamp;
545
- }
546
- else if ( flowbehavior == " error" ) {
547
- flow_ = _FlowBehavior::error;
548
- }
549
- else {
550
- flow_ = _FlowBehavior::value;
551
- // store default value at end of content array
552
- content_.push_back (resolve_content (flowbehavior, context));
572
+ flow_ = parse_flowbehavior (flowbehavior);
573
+ if (flow_ == _FlowBehavior::value) {
574
+ content_.push_back (resolve_content (flowbehavior, context));
553
575
}
554
576
}
555
577
0 commit comments