Skip to content

Commit 327fa09

Browse files
committed
final edits
1 parent 027c6ed commit 327fa09

8 files changed

Lines changed: 209 additions & 144 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
88

99
## [0.3.0] - 2026-02-23
1010
- fix #13, allow size to be 65535 (uint16_t)
11-
- fix math overflow when using int result types.
12-
- add multi type **multiMapCache<T1, T2>** to have all options.
11+
- add patch for mixed math signed / unsigned multiMap.
12+
- add multi type **multiMapCache<T1, T2>** as it was missing.
1313
- update readme.md
1414
- update GitHub actions
1515
- minor edits

MultiMap.h

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ T multiMap(T value, T* _in, T* _out, uint16_t size)
3636
if (value == _in[pos]) return _out[pos];
3737

3838
// interpolate in the right segment for the rest
39-
return T(float(value - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1])) + _out[pos-1];
39+
return (value - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1]) + _out[pos-1];
40+
// if interpolation overflows use this line
41+
// return T(float(value - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1])) + _out[pos-1];
4042
}
4143

4244

@@ -83,7 +85,9 @@ T multiMapCache(T value, T* _in, T* _out, uint16_t size)
8385
else
8486
{
8587
// interpolate in the right segment for the rest
86-
cache = T(float(value - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1])) + _out[pos-1];
88+
cache = (value - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1]) + _out[pos-1];
89+
// if interpolation overflows use this line
90+
// cache = T(float(value - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1])) + _out[pos-1];
8791
}
8892
}
8993
return cache;
@@ -114,7 +118,10 @@ T multiMapBS(T value, T* _in, T* _out, uint16_t size)
114118
if (value >= _in[mid]) lower = mid;
115119
else upper = mid;
116120
}
117-
return T(float(value - _in[lower]) * (_out[upper] - _out[lower]) / (_in[upper] - _in[lower])) + _out[lower];
121+
// interpolate in the right segment for the rest
122+
return (value - _in[lower]) * (_out[upper] - _out[lower]) / (_in[upper] - _in[lower]) + _out[lower];
123+
// if interpolation overflows use this line
124+
// return T(float(value - _in[lower]) * (_out[upper] - _out[lower]) / (_in[upper] - _in[lower])) + _out[lower];
118125
}
119126

120127

@@ -138,7 +145,9 @@ T2 multiMap(T1 value, T1* _in, T2* _out, uint16_t size)
138145
if (value == _in[pos]) return _out[pos];
139146

140147
// interpolate in the right segment for the rest
141-
return T2(float(value - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1])) + _out[pos-1];
148+
return (value - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1]) + _out[pos-1];
149+
// if interpolation overflows use this line
150+
// return T2(float(value - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1])) + _out[pos-1];
142151
}
143152

144153

@@ -185,7 +194,9 @@ T2 multiMapCache(T1 value, T1* _in, T2* _out, uint16_t size)
185194
else
186195
{
187196
// interpolate in the right segment for the rest
188-
cache = T2(float(value - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1])) + _out[pos-1];
197+
cache = (value - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1]) + _out[pos-1];
198+
// if interpolation overflows use this line
199+
// return T2(float(value - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1])) + _out[pos-1];
189200
}
190201
}
191202
return cache;
@@ -215,8 +226,10 @@ T2 multiMapBS(T1 value, T1* _in, T2* _out, uint16_t size)
215226
if (value >= _in[mid]) lower = mid;
216227
else upper = mid;
217228
}
218-
219-
return T2(float(value - _in[lower]) * (_out[upper] - _out[lower]) / (_in[upper] - _in[lower])) + _out[lower];
229+
// interpolate in the right segment for the rest
230+
return (value - _in[lower]) * (_out[upper] - _out[lower]) / (_in[upper] - _in[lower]) + _out[lower];
231+
// if interpolation overflows use this line
232+
// return T2(float(value - _in[lower]) * (_out[upper] - _out[lower]) / (_in[upper] - _in[lower])) + _out[lower];
220233
}
221234

222235

README.md

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -57,42 +57,40 @@ However there might be more than one input value mapping onto the same output va
5757
See - https://en.wikipedia.org/wiki/Bijection,_injection_and_surjection
5858

5959

60+
### Math problems in interpolation (rare).
61+
62+
In multiMap the interpolation math can fail. This happens when integer types are used
63+
that are too small to handle the multiplication in the interpolation (e.g. 8 or 16 bit)
64+
Also when a mixed signed / unsigned types are used this can happen.
65+
66+
There are two solutions to handle this.
67+
- (preferred) use float (double) as either input or output type.
68+
This forces casting to float in the interpolation solving the math problem.
69+
Drawback is it might take extra memory (e.g. int16_t => float).
70+
- The multiMap.h file contains **commented** code to cast the interpolation
71+
during the interpolation only.
72+
Comment the existing interpolation and uncomment the other line.
73+
This saves memory as the arrays used do not "grow".
74+
75+
Note both solutions have a performance penalty
76+
77+
See the sketch **multimap_demo_fail.ino** (UNO R3) to show the problem.
78+
79+
6080
### 0.3.0 Breaking change
6181

6282
This 0.3.0 version makes the previous versions obsolete.
6383

6484
Since 0.3.0 sizes of multiMap can exceed 256 elements, up to 65535 elements.
6585
This is because the size has changed from an uint8_t => uint16_t.
6686

67-
More important the internal math has an extra float cast as when using int types
68-
there was sometimes an overflow in the interpolation (rare but wrong).
69-
70-
On an UNO R3 this breaking change altered the performance.
71-
Linear search got better, binary search got worse but is still
72-
better than the linear search.
73-
74-
From **multimap_BS_compare.ino** version 0.2.1 versus 0.3.0.
75-
76-
| version | size | t1 | t2 | ratio |
77-
|:----------|:------:|--------:|--------:|----------:|
78-
| 0.2.1 | 10 | 9476 | 9364 | 98.82 |
79-
| 0.2.1 | 15 | 13348 | 12628 | 94.61 |
80-
| 0.2.1 | 20 | 17808 | 15948 | 89.56 |
81-
| 0.2.1 | 30 | 28476 | 22712 | 79.76 |
82-
| 0.2.1 | 40 | 41516 | 29620 | 71.35 |
83-
| 0.2.1 | 50 | 56896 | 36608 | 64.34 |
84-
| 0.2.1 | 70 | 94716 | 50700 | 53.53 |
85-
| 0.2.1 | 90 | 141936 | 65136 | 45.89 |
86-
| | | | | |
87-
| 0.3.0 | 10 | 10592 | 10688 | 100.91 |
88-
| 0.3.0 | 15 | 14528 | 14736 | 101.43 |
89-
| 0.3.0 | 20 | 18808 | 18868 | 100.32 |
90-
| 0.3.0 | 30 | 28412 | 27240 | 95.87 |
91-
| 0.3.0 | 40 | 39396 | 35784 | 90.83 |
92-
| 0.3.0 | 50 | 51764 | 44428 | 85.83 |
93-
| 0.3.0 | 70 | 80648 | 61864 | 76.71 |
94-
| 0.3.0 | 90 | 115068 | 79640 | 69.21 |
95-
| | | | | |
87+
On an UNO R3 the change of the size to uint16_t altered the performance.
88+
Linear search got better, binary search got worse but still performs
89+
better than the linear search in a test.
90+
91+
Run **multimap_BS_compare.ino** to see the differences.
92+
93+
(output logs of UNO R3 are in the example folder).
9694

9795

9896
### Related

examples/multimap_2d/multimap_2d.ino

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
// PURPOSE: demo mapping an angle on a semi-circle (2D {x, y} position)
55
// URL: https://github.com/RobTillaart/MultiMap
66
//
7-
// when printing into a plotter one sees a rough sine and cosine
7+
// when printing into a plotter one sees a very rough sine and cosine
88
// with an amplitude of 5, approximated with interpolation.
99

10+
1011
#include "MultiMap.h"
1112

1213
float in[] = { 0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330, 360 };

examples/multimap_BS_compare/output_0.3.0.txt

Lines changed: 97 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -6,102 +6,103 @@ Arduino\libraries\MultiMap\examples\multimap_BS_compare\multimap_BS_compare.ino
66
MULTIMAP_LIB_VERSION: 0.3.0
77

88
size t1 t2 ratio
9-
4 6328 5992 94.69
10-
5 7008 6744 96.23
11-
6 7700 7524 97.71
12-
7 8400 8320 99.05
13-
8 9116 9092 99.74
14-
9 9852 9888 100.37
15-
10 10592 10688 100.91
16-
11 11352 11496 101.27
17-
12 12128 12304 101.45
18-
13 12908 13120 101.64
19-
14 13716 13924 101.52
20-
15 14528 14736 101.43
21-
16 15360 15556 101.28
22-
17 16204 16368 101.01
23-
18 17056 17196 100.82
24-
19 17924 18032 100.60
25-
20 18808 18868 100.32
26-
21 19708 19696 99.94
27-
22 20620 20532 99.57
28-
23 21544 21372 99.20
29-
24 22488 22208 98.75
30-
25 23440 23048 98.33
31-
26 24400 23888 97.90
32-
27 25388 24724 97.38
33-
28 26380 25564 96.91
34-
29 27388 26408 96.42
35-
30 28412 27240 95.87
36-
31 29448 28088 95.38
37-
32 30500 28928 94.85
38-
33 31564 29776 94.34
39-
34 32644 30628 93.82
40-
35 33732 31488 93.35
41-
36 34836 32344 92.85
42-
37 35956 33200 92.34
43-
38 37088 34060 91.84
44-
39 38240 34924 91.33
45-
40 39396 35784 90.83
46-
41 40568 36652 90.35
47-
42 41760 37512 89.83
48-
43 42960 38368 89.31
49-
44 44184 39232 88.79
50-
45 45404 40108 88.34
51-
46 46648 40964 87.82
52-
47 47904 41832 87.32
53-
48 49180 42700 86.82
54-
49 50468 43572 86.34
55-
50 51764 44428 85.83
56-
51 53072 45296 85.35
57-
52 54404 46152 84.83
58-
53 55744 47020 84.35
59-
54 57100 47880 83.85
60-
55 58468 48748 83.38
61-
56 59844 49616 82.91
62-
57 61236 50496 82.46
63-
58 62652 51356 81.97
64-
59 64080 52220 81.49
65-
60 65516 53088 81.03
66-
61 66968 53956 80.57
67-
62 68428 54832 80.13
68-
63 69908 55708 79.69
69-
64 71404 56576 79.23
70-
65 72904 57460 78.82
71-
66 74424 58332 78.38
72-
67 75960 59212 77.95
73-
68 77508 60088 77.52
74-
69 79076 60976 77.11
75-
70 80648 61864 76.71
76-
71 82236 62744 76.30
77-
72 83836 63636 75.91
78-
73 85456 64524 75.51
79-
74 87088 65396 75.09
80-
75 88728 66292 74.71
81-
76 90396 67172 74.31
82-
77 92064 68072 73.94
83-
78 93744 68960 73.56
84-
79 95448 69848 73.18
85-
80 97164 70740 72.80
86-
81 98888 71636 72.44
87-
82 100632 72520 72.06
88-
83 102392 73404 71.69
89-
84 104160 74288 71.32
90-
85 105944 75180 70.96
91-
86 107736 76064 70.60
92-
87 109552 76960 70.25
93-
88 111368 77852 69.91
94-
89 113204 78752 69.57
95-
90 115068 79640 69.21
96-
91 116928 80532 68.87
97-
92 118808 81420 68.53
98-
93 120704 82316 68.20
99-
94 122612 83212 67.87
100-
95 122728 83312 67.88
101-
96 122732 83352 67.91
102-
97 122728 83432 67.98
103-
98 122728 83428 67.98
104-
99 122724 83468 68.01
9+
4 5588 5600 100.21
10+
5 6160 6200 100.65
11+
6 6756 6820 100.95
12+
7 7368 7448 101.09
13+
8 7992 8076 101.05
14+
9 8636 8700 100.74
15+
10 9308 9344 100.39
16+
11 9996 9996 100.00
17+
12 10700 10644 99.48
18+
13 11424 11288 98.81
19+
14 12172 11944 98.13
20+
15 12936 12588 97.31
21+
16 13724 13232 96.42
22+
17 14524 13884 95.59
23+
18 15348 14552 94.81
24+
19 16192 15224 94.02
25+
20 17052 15892 93.20
26+
21 17936 16564 92.35
27+
22 18836 17232 91.48
28+
23 19748 17904 90.66
29+
24 20688 18580 89.81
30+
25 21648 19252 88.93
31+
26 22624 19928 88.08
32+
27 23620 20592 87.18
33+
28 24644 21260 86.27
34+
29 25680 21936 85.42
35+
30 26728 22608 84.59
36+
31 27804 23276 83.71
37+
32 28896 23952 82.89
38+
33 30008 24628 82.07
39+
34 31140 25320 81.31
40+
35 32296 26008 80.53
41+
36 33464 26700 79.79
42+
37 34652 27396 79.06
43+
38 35864 28088 78.32
44+
39 37096 28780 77.58
45+
40 38340 29476 76.88
46+
41 39612 30164 76.15
47+
42 40900 30860 75.45
48+
43 42204 31556 74.77
49+
44 43532 32252 74.09
50+
45 44880 32944 73.40
51+
46 46244 33640 72.74
52+
47 47624 34336 72.10
53+
48 49032 35028 71.44
54+
49 50452 35724 70.81
55+
50 51900 36420 70.17
56+
51 53356 37108 69.55
57+
52 54844 37804 68.93
58+
53 56340 38500 68.34
59+
54 57856 39196 67.75
60+
55 59400 39888 67.15
61+
56 60960 40580 66.57
62+
57 62536 41276 66.00
63+
58 64136 41972 65.44
64+
59 65748 42668 64.90
65+
60 67388 43360 64.34
66+
61 69044 44056 63.81
67+
62 70716 44756 63.29
68+
63 72412 45448 62.76
69+
64 74128 46144 62.25
70+
65 75856 46840 61.75
71+
66 77608 47552 61.27
72+
67 79384 48268 60.80
73+
68 81176 48976 60.33
74+
69 82980 49696 59.89
75+
70 84812 50408 59.43
76+
71 86656 51128 59.00
77+
72 88528 51844 58.56
78+
73 90416 52556 58.13
79+
74 92320 53276 57.71
80+
75 94248 53992 57.29
81+
76 96196 54704 56.87
82+
77 98156 55428 56.47
83+
78 100148 56132 56.05
84+
79 102144 56860 55.67
85+
80 104176 57572 55.26
86+
81 106220 58292 54.88
87+
82 108280 59008 54.50
88+
83 110360 59716 54.11
89+
84 112460 60436 53.74
90+
85 114580 61156 53.37
91+
86 116720 61872 53.01
92+
87 118876 62588 52.65
93+
88 121056 63304 52.29
94+
89 123252 64020 51.94
95+
90 125468 64736 51.60
96+
91 127700 65456 51.26
97+
92 129960 66172 50.92
98+
93 132236 66896 50.59
99+
94 134528 67608 50.26
100+
95 134696 67696 50.26
101+
96 134696 67724 50.28
102+
97 134692 67772 50.32
103+
98 134696 67776 50.32
104+
99 134692 67804 50.34
105+
105106

106107

107108

examples/multimap_demo/multimap_demo.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
#include "MultiMap.h"
1111

12-
// not the IN array is not equidistant.
12+
// note the IN array is not equidistant.
1313
// layout is to see the points of the graph.
1414
float in[] = { 0, 20, 40, 50, 60, 80, 90, 100, 105 };
1515
float out[] = { 1, 2.8, 4.5, 7.0, 10.4, 33.5, 57.5, 100, 120 };

0 commit comments

Comments
 (0)