rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
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 <cmath>
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
24float interpolateClampedWithValidation(float x1, float y1, float x2, float y2, float x);
25float interpolateClamped(float x1, float y1, float x2, float y2, float x);
26float 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
31template<typename TValue, int TSize>
32void 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
42template<typename TValue, int TSize>
43void 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 */
56template<typename kType>
57int 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 */
114template<typename VType, typename kType>
115void 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