After playing with my Sharp distancesensor - SHARP 2Y0A02 F 9Y - I needed a mapping from measurements upon centimeters. As the functions I found did not cover the whole range with the accuracy needed I decided to write a linear interpolation function. There was allready one on the playground called reMap() but that used floats, so I redid it in integer to improve performance and robustness. Furthermore I added some snippets how multiMap() can be used.
All remarks, improvements or good examples are - as allways - welcome.
put this in a file multiMap.h and use it as a library
#include "Arduino.h"
template<typename T>
T multiMap(T val, T* _in, T* _out, uint8_t size)
{
// take care the value is within range
// val = constrain(val, _in[0], _in[size-1]);
if (val <= _in[0]) return _out[0];
if (val >= _in[size-1]) return _out[size-1];
// search right interval
uint8_t pos = 1; // _in[0] allready tested
while(val > _in[pos]) pos++;
// this will handle all exact "points" in the _in array
if (val == _in[pos]) return _out[pos];
// interpolate in the right segment for the rest
return (val - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1]) + _out[pos-1];
}
I never noticed it won't take values assigned to variables and it doesn't like Strings or strings, but everything else works. However I reverted it back to just this.
template< typename A, typename B, typename C, typename D, typename E >
auto map( const A x, B in_min, C in_max, D out_min, E out_max ) -> decltype( x * in_min * in_max * out_min * out_max )
{
typedef decltype( x * in_min * in_max * out_min * out_max) T_out;
//((x < in_min)? in_min : ((x > in_max)? in_max : x)) -> constrain without overhead
return (T_out)( ((x < in_min)? in_min : ((x > in_max)? in_max : x)) - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
Even disallowing Strings and strings, does it make sense to use different types for the from range (float fromMin, long fromMax), for instance? Does it make sense to use different types for the to range (long long toMin, byte toMax)?
C allows you to shoot yourself in the foot. C++'s templates allow you to blow your whole leg off.
This is a situation, I think, where a template is NOT a good idea.
I think it is a great example what can be done with templates, but I agree with PaulS that using different types for all parameters is overkill for 99.9% of all sketches I have seen.
If a user wants performance (s)he inlines the formula
If a user wants precision (s)he either selects float (because it rounds better in the division) or uses long.
The whole point to allowing multiple types was for decltype to choose the largest type and make it the returning result.
Originally I only allowed one type, but then you lose precision if the first type (valueToMap) is smaller then the rest. So allowing multiple types solves that, but as Paul pointed out, it can also cause problems if the data entered is foolish. A possible scenario for new programmers, i'm sure, but we can't prevent everything.
but as Paul pointed out, it can also cause problems
I wasn't picking on your efforts. I've never had the need for templates, so I've not studied up on them. I don't know if you can create a template that takes different types, and still require that some of the function arguments must all be the same type. I guess it's time to get over the lack of knowledge of templates.
PaulS:
Even disallowing Strings and strings, does it make sense to use different types for the from range (float fromMin, long fromMax), for instance? Does it make sense to use different types for the to range (long long toMin, byte toMax)?
C allows you to shoot yourself in the foot. C++'s templates allow you to blow your whole leg off.
This is a situation, I think, where a template is NOT a good idea.
Silly use of any code is a bad idea, and yes it does make sense if you understand the declaration.