22//
33// FILE: MultiMap.h
44// AUTHOR: Rob Tillaart
5- // VERSION: 0.3 .0
5+ // VERSION: 0.4 .0
66// DATE: 2011-01-26
77// PURPOSE: Arduino library for fast non-linear mapping or interpolation of values
88// URL: https://github.com/RobTillaart/MultiMap
99// URL: http://playground.arduino.cc/Main/MultiMap
1010
1111
1212
13- #define MULTIMAP_LIB_VERSION (F(" 0.3 .0" ))
13+ #define MULTIMAP_LIB_VERSION (F(" 0.4 .0" ))
1414
1515
1616#include " Arduino.h"
@@ -36,7 +36,16 @@ 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 (value - _in[pos-1 ]) * (_out[pos] - _out[pos-1 ]) / (_in[pos] - _in[pos-1 ]) + _out[pos-1 ];
39+ // use a modified formula for decreasing output array segment
40+ // to prevent unsigned "underflow/overflow" (issue #15)
41+ if (_out[pos] >= _out[pos-1 ])
42+ {
43+ return _out[pos-1 ] + (value - _in[pos-1 ]) * (_out[pos] - _out[pos-1 ]) / (_in[pos] - _in[pos-1 ]);
44+ }
45+ else
46+ {
47+ return _out[pos-1 ] - (value - _in[pos-1 ]) * (_out[pos-1 ] - _out[pos]) / (_in[pos] - _in[pos-1 ]);
48+ }
4049 // if interpolation overflows use this line
4150 // return T(float(value - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1])) + _out[pos-1];
4251}
@@ -85,9 +94,16 @@ T multiMapCache(T value, T* _in, T* _out, uint16_t size)
8594 else
8695 {
8796 // interpolate in the right segment for the rest
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];
97+ // use a modified formula for decreasing output array segment
98+ // to prevent unsigned "underflow/overflow" (issue #15)
99+ if (_out[pos] >= _out[pos-1 ])
100+ {
101+ cache = _out[pos-1 ] + (value - _in[pos-1 ]) * (_out[pos] - _out[pos-1 ]) / (_in[pos] - _in[pos-1 ]);
102+ }
103+ else
104+ {
105+ cache = _out[pos-1 ] - (value - _in[pos-1 ]) * (_out[pos-1 ] - _out[pos]) / (_in[pos] - _in[pos-1 ]);
106+ }
91107 }
92108 }
93109 return cache;
@@ -119,7 +135,16 @@ T multiMapBS(T value, T* _in, T* _out, uint16_t size)
119135 else upper = mid;
120136 }
121137 // interpolate in the right segment for the rest
122- return (value - _in[lower]) * (_out[upper] - _out[lower]) / (_in[upper] - _in[lower]) + _out[lower];
138+ // use a modified formula for decreasing output array segment
139+ // to prevent unsigned "underflow/overflow" (issue #15)
140+ if (_out[upper] >= _out[lower])
141+ {
142+ return _out[lower] + (value - _in[lower]) * (_out[upper] - _out[lower]) / (_in[upper] - _in[lower]);
143+ }
144+ else
145+ {
146+ return _out[lower] - (value - _in[lower]) * (_out[lower] - _out[upper]) / (_in[upper] - _in[lower]);
147+ }
123148 // if interpolation overflows use this line
124149 // return T(float(value - _in[lower]) * (_out[upper] - _out[lower]) / (_in[upper] - _in[lower])) + _out[lower];
125150}
@@ -145,7 +170,16 @@ T2 multiMap(T1 value, T1* _in, T2* _out, uint16_t size)
145170 if (value == _in[pos]) return _out[pos];
146171
147172 // interpolate in the right segment for the rest
148- return (value - _in[pos-1 ]) * (_out[pos] - _out[pos-1 ]) / (_in[pos] - _in[pos-1 ]) + _out[pos-1 ];
173+ // use a modified formula for decreasing output array segment
174+ // to prevent unsigned "underflow/overflow" (issue #15)
175+ if (_out[pos] >= _out[pos-1 ])
176+ {
177+ return _out[pos-1 ] + (value - _in[pos-1 ]) * (_out[pos] - _out[pos-1 ]) / (_in[pos] - _in[pos-1 ]);
178+ }
179+ else
180+ {
181+ return _out[pos-1 ] - (value - _in[pos-1 ]) * (_out[pos-1 ] - _out[pos]) / (_in[pos] - _in[pos-1 ]);
182+ }
149183 // if interpolation overflows use this line
150184 // return T2(float(value - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1])) + _out[pos-1];
151185}
@@ -194,7 +228,17 @@ T2 multiMapCache(T1 value, T1* _in, T2* _out, uint16_t size)
194228 else
195229 {
196230 // interpolate in the right segment for the rest
197- cache = (value - _in[pos-1 ]) * (_out[pos] - _out[pos-1 ]) / (_in[pos] - _in[pos-1 ]) + _out[pos-1 ];
231+ // use a modified formula for decreasing output array segment
232+ // to prevent unsigned "underflow/overflow" (issue #15)
233+ if (_out[pos] >= _out[pos-1 ])
234+ {
235+ cache = _out[pos-1 ] + (value - _in[pos-1 ]) * (_out[pos] - _out[pos-1 ]) / (_in[pos] - _in[pos-1 ]);
236+
237+ }
238+ else
239+ {
240+ cache = _out[pos-1 ] - (value - _in[pos-1 ]) * (_out[pos-1 ] - _out[pos]) / (_in[pos] - _in[pos-1 ]);
241+ }
198242 // if interpolation overflows use this line
199243 // return T2(float(value - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1])) + _out[pos-1];
200244 }
@@ -227,7 +271,16 @@ T2 multiMapBS(T1 value, T1* _in, T2* _out, uint16_t size)
227271 else upper = mid;
228272 }
229273 // interpolate in the right segment for the rest
230- return (value - _in[lower]) * (_out[upper] - _out[lower]) / (_in[upper] - _in[lower]) + _out[lower];
274+ // use a modified formula for decreasing output array segment
275+ // to prevent unsigned "underflow/overflow" (issue #15)
276+ if (_out[upper] >= _out[lower])
277+ {
278+ return _out[lower] + (value - _in[lower]) * (_out[upper] - _out[lower]) / (_in[upper] - _in[lower]);
279+ }
280+ else
281+ {
282+ return _out[lower] - (value - _in[lower]) * (_out[lower] - _out[upper]) / (_in[upper] - _in[lower]);
283+ }
231284 // if interpolation overflows use this line
232285 // return T2(float(value - _in[lower]) * (_out[upper] - _out[lower]) / (_in[upper] - _in[lower])) + _out[lower];
233286}
0 commit comments