22//
33// FILE: MultiMap.h
44// AUTHOR: Rob Tillaart
5- // VERSION: 0.2.1
5+ // VERSION: 0.3.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.2.1 " ))
13+ #define MULTIMAP_LIB_VERSION (F(" 0.3.0 " ))
1414
1515
1616#include " Arduino.h"
2222//
2323// note: the in array must have increasing values
2424template <typename T>
25- T multiMap (T value, T* _in, T* _out, uint8_t size)
25+ T multiMap (T value, T* _in, T* _out, uint16_t size)
2626{
2727 // output is constrained to out array
2828 if (value <= _in[0 ]) return _out[0 ];
2929 if (value >= _in[size-1 ]) return _out[size-1 ];
3030
3131 // search right interval
32- uint8_t pos = 1 ; // _in[0] already tested
32+ uint16_t pos = 1 ; // _in[0] already tested
3333 while (value > _in[pos]) pos++;
3434
3535 // this will handle all exact "points" in the _in array
3636 if (value == _in[pos]) return _out[pos];
3737
3838 // interpolate in the right segment for the rest
3939 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
@@ -49,7 +51,7 @@ T multiMap(T value, T* _in, T* _out, uint8_t size)
4951// e.g. 2 2 2 2 2 3 3 3 3 5 5 5 5 5 5 8 8 8 8 5 5 5 5 5
5052// implements a minimal cache of the lastValue.
5153template <typename T>
52- T multiMapCache (T value, T* _in, T* _out, uint8_t size)
54+ T multiMapCache (T value, T* _in, T* _out, uint16_t size)
5355{
5456 static T lastValue = -1 ; // possible bug for 1st call
5557 static T cache = -1 ;
@@ -72,7 +74,7 @@ T multiMapCache(T value, T* _in, T* _out, uint8_t size)
7274 else
7375 {
7476 // search right interval; index 0 _in[0] already tested
75- uint8_t pos = 1 ;
77+ uint16_t pos = 1 ;
7678 while (value > _in[pos]) pos++;
7779
7880 // this will handle all exact "points" in the _in array
@@ -84,6 +86,8 @@ T multiMapCache(T value, T* _in, T* _out, uint8_t size)
8486 {
8587 // interpolate in the right segment for the rest
8688 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;
@@ -99,7 +103,7 @@ T multiMapCache(T value, T* _in, T* _out, uint8_t size)
99103//
100104// note: the in array must have increasing values
101105template <typename T>
102- T multiMapBS (T value, T* _in, T* _out, uint8_t size)
106+ T multiMapBS (T value, T* _in, T* _out, uint16_t size)
103107{
104108 // output is constrained to out array
105109 if (value <= _in[0 ]) return _out[0 ];
@@ -110,12 +114,14 @@ T multiMapBS(T value, T* _in, T* _out, uint8_t size)
110114 uint16_t upper = size - 1 ;
111115 while (lower < upper - 1 )
112116 {
113- uint8_t mid = (lower + upper) / 2 ;
117+ uint16_t mid = (lower + upper) / 2 ;
114118 if (value >= _in[mid]) lower = mid;
115119 else upper = mid;
116120 }
117-
121+ // interpolate in the right segment for the rest
118122 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];
119125}
120126
121127
@@ -125,7 +131,7 @@ T multiMapBS(T value, T* _in, T* _out, uint8_t size)
125131//
126132// note: the in array must have increasing values
127133template <typename T1, typename T2>
128- T2 multiMap (T1 value, T1* _in, T2* _out, uint8_t size)
134+ T2 multiMap (T1 value, T1* _in, T2* _out, uint16_t size)
129135{
130136 // output is constrained to out array
131137 if (value <= _in[0 ]) return _out[0 ];
@@ -140,6 +146,60 @@ T2 multiMap(T1 value, T1* _in, T2* _out, uint8_t size)
140146
141147 // interpolate in the right segment for the rest
142148 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];
151+ }
152+
153+
154+ // //////////////////////////////////////////////////////////////////////
155+ //
156+ // MULTITYPE TYPE MULTIMAP CACHE - LINEAR SEARCH
157+ //
158+ // note: the in array must have increasing values
159+ // performance optimized version if inputs do not change often
160+ // e.g. 2 2 2 2 2 3 3 3 3 5 5 5 5 5 5 8 8 8 8 5 5 5 5 5
161+ // implements a minimal cache of the lastValue.
162+ template <typename T1, typename T2>
163+ T2 multiMapCache (T1 value, T1* _in, T2* _out, uint16_t size)
164+ {
165+ static T1 lastValue = -1 ; // possible bug for 1st call
166+ static T2 cache = -1 ;
167+
168+ if (value == lastValue)
169+ {
170+ return cache;
171+ }
172+ lastValue = value;
173+
174+ // output is constrained to out array
175+ if (value <= _in[0 ])
176+ {
177+ cache = _out[0 ];
178+ }
179+ else if (value >= _in[size-1 ])
180+ {
181+ cache = _out[size-1 ];
182+ }
183+ else
184+ {
185+ // search right interval; index 0 _in[0] already tested
186+ uint16_t pos = 1 ;
187+ while (value > _in[pos]) pos++;
188+
189+ // this will handle all exact "points" in the _in array
190+ if (value == _in[pos])
191+ {
192+ cache = _out[pos];
193+ }
194+ else
195+ {
196+ // 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 ];
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];
200+ }
201+ }
202+ return cache;
143203}
144204
145205
@@ -151,7 +211,7 @@ T2 multiMap(T1 value, T1* _in, T2* _out, uint8_t size)
151211//
152212// note: the in array must have increasing values
153213template <typename T1, typename T2>
154- T2 multiMapBS (T1 value, T1* _in, T2* _out, uint8_t size)
214+ T2 multiMapBS (T1 value, T1* _in, T2* _out, uint16_t size)
155215{
156216 // output is constrained to out array
157217 if (value <= _in[0 ]) return _out[0 ];
@@ -166,8 +226,10 @@ T2 multiMapBS(T1 value, T1* _in, T2* _out, uint8_t size)
166226 if (value >= _in[mid]) lower = mid;
167227 else upper = mid;
168228 }
169-
229+ // interpolate in the right segment for the rest
170230 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];
171233}
172234
173235
0 commit comments