rusEFI
The most advanced open source ECU
efi_interpolation.h
Go to the documentation of this file.
1 /**
2  * @file efi_interpolation.h
3  * See also libfirmware interpolation.h
4  *
5  * @date Oct 17, 2013
6  * @author Andrey Belomutskiy, (c) 2012-2020
7  */
8 
9 #pragma once
10 
11 #include <math.h>
12 #include "datalogging.h"
13 #include "obd_error_codes.h"
14 #include "error_handling.h"
15 
16 #include <type_traits>
17 
18 #ifndef DEBUG_INTERPOLATION
19 #define DEBUG_INTERPOLATION FALSE
20 #endif
21 
22 #define INTERPOLATION_A(x1, y1, x2, y2) ((y1 - y2) / (x1 - x2))
23 
24 float interpolateClampedWithValidation(float x1, float y1, float x2, float y2, float x);
25 float interpolateClamped(float x1, float y1, float x2, float y2, float x);
26 float interpolateMsg(const char *msg, float x1, float y1, float x2, float y2, float x);
27 
28 // _technically_ and _theoretically_ we can support flat line for both bins and values but I am not sure if
29 // such a rare case is something we want to support
30 // see also: setLinearCurve
31 template<typename TValue, int TSize>
32 void ensureArrayIsAscending(const char* msg, const TValue (&values)[TSize]) {
33  for (size_t i = 0; i < TSize - 1; i++) {
34  float cur = values[i];
35  float next = values[i + 1];
36  if (next <= cur) {
37  firmwareError(ObdCode::CUSTOM_ERR_AXIS_ORDER, "Invalid table axis (must be ascending!): %s %f should be below %f at %d", msg, cur, next, i);
38  }
39  }
40 }
41 
42 template<typename TValue, int TSize>
43 void ensureArrayIsAscendingOrDefault(const char* msg, const TValue (&values)[TSize]) {
44  if (values[1] == 0) {
45  return; // looks like default empty array, do not check
46  }
47  ensureArrayIsAscending(msg, values);
48 }
49 
50 /** @brief Binary search
51  * @returns the highest index within sorted array such that array[i] is greater than or equal to the parameter
52  * @note If the parameter is smaller than the first element of the array, -1 is returned.
53  *
54  * See also ensureArrayIsAscending
55  */
56 template<typename kType>
57 int findIndexMsg(const char *msg, const kType array[], int size, kType value) {
58  float fvalue = (float)value;
59  if (std::isnan(fvalue)) {
60  firmwareError(ObdCode::ERROR_NAN_FIND_INDEX, "NaN in findIndex%s", msg);
61  return 0;
62  }
63 
64  if (value < array[0])
65  return -1;
66  int middle;
67 
68  int left = 0;
69  int right = size;
70 
71  // todo: extract binary search as template method?
72  while (true) {
73 #if 0
74  // that's an assertion to make sure we do not loop here
75  size--;
76  efiAssert(ObdCode::CUSTOM_ERR_ASSERT, size > 0, "Unexpected state in binary search", 0);
77 #endif
78 
79  // todo: compare current implementation with
80  // http://eigenjoy.com/2011/01/21/worlds-fastest-binary-search/
81  // ?
82  middle = (left + right) / 2;
83 
84 // print("left=%d middle=%d right=%d: %.2f\r\n", left, middle, right, array[middle]);
85 
86  if (middle == left)
87  break;
88 
89  if (middle != 0 && array[middle - 1] > array[middle]) {
90 #if EFI_UNIT_TEST
91  firmwareError(ObdCode::CUSTOM_ERR_6610, "%s: out of order %.2f %.2f", msg, array[middle - 1], array[middle]);
92 #else
93  warning(ObdCode::CUSTOM_ERR_OUT_OF_ORDER, "%s: out of order %.2f %.2f", msg, array[middle - 1], array[middle]);
94 
95 #endif /* EFI_UNIT_TEST */
96  }
97 
98  if (value < array[middle]) {
99  right = middle;
100  } else if (value > array[middle]) {
101  left = middle;
102  } else {
103  break;
104  }
105  }
106 
107  return middle;
108 }
109 
110 /**
111  * Sets specified value for specified key in a correction curve
112  * see also setLinearCurve()
113  */
114 template<typename VType, typename kType>
115 void setCurveValue(const kType bins[], VType values[], int size, float key, float value) {
116  int index = findIndexMsg("tbVl", bins, size, key);
117  if (index == -1)
118  index = 0;
119  values[index] = value;
120 }
Buffered console output stream header.
float interpolateMsg(const char *msg, float x1, float y1, float x2, float y2, float x)
Linear interpolation by two points.
float interpolateClampedWithValidation(float x1, float y1, float x2, float y2, float x)
float interpolateClamped(float x1, float y1, float x2, float y2, float x)
int findIndexMsg(const char *msg, const kType array[], int size, kType value)
Binary search.
void ensureArrayIsAscendingOrDefault(const char *msg, const TValue(&values)[TSize])
void setCurveValue(const kType bins[], VType values[], int size, float key, float value)
void ensureArrayIsAscending(const char *msg, const TValue(&values)[TSize])
bool warning(ObdCode code, const char *fmt,...)
void firmwareError(ObdCode code, const char *fmt,...)
Standard and custom OBD-II error codes.
@ CUSTOM_ERR_AXIS_ORDER
@ ERROR_NAN_FIND_INDEX
@ CUSTOM_ERR_6610
@ CUSTOM_ERR_ASSERT
@ CUSTOM_ERR_OUT_OF_ORDER
composite packet size