GY-63_MS5611/libraries/MultiMap/MultiMap.h

176 lines
4.6 KiB
C
Raw Normal View History

2020-11-27 05:20:37 -05:00
#pragma once
2014-11-18 13:32:33 -05:00
//
2021-01-29 06:31:58 -05:00
// FILE: MultiMap.h
2014-11-18 13:32:33 -05:00
// AUTHOR: Rob Tillaart
2023-11-13 06:13:02 -05:00
// VERSION: 0.2.0
2020-11-27 05:20:37 -05:00
// DATE: 2011-01-26
// PURPOSE: Arduino library for fast non-linear mapping or interpolation of values
// URL: https://github.com/RobTillaart/MultiMap
2014-11-18 13:32:33 -05:00
// URL: http://playground.arduino.cc/Main/MultiMap
2021-05-28 07:39:42 -04:00
2022-11-18 09:09:05 -05:00
2023-11-13 06:13:02 -05:00
#define MULTIMAP_LIB_VERSION (F("0.2.0"))
2014-11-18 13:32:33 -05:00
2021-01-29 06:31:58 -05:00
#include "Arduino.h"
2014-11-18 13:32:33 -05:00
2021-12-22 06:10:05 -05:00
2023-11-13 06:13:02 -05:00
////////////////////////////////////////////////////////////////////////
//
// SINGLE TYPE MULTIMAP - LINEAR SEARCH - the reference
//
// note: the in array must have increasing values
2014-11-18 13:32:33 -05:00
template<typename T>
2021-12-22 06:10:05 -05:00
T multiMap(T value, T* _in, T* _out, uint8_t size)
2014-11-18 13:32:33 -05:00
{
2023-06-24 13:15:01 -04:00
// output is constrained to out array
if (value <= _in[0]) return _out[0];
if (value >= _in[size-1]) return _out[size-1];
2014-11-18 13:32:33 -05:00
2023-11-13 06:13:02 -05:00
// search right interval
2023-06-24 13:15:01 -04:00
uint8_t pos = 1; // _in[0] already tested
while(value > _in[pos]) pos++;
2014-11-18 13:32:33 -05:00
2023-11-13 06:13:02 -05:00
// this will handle all exact "points" in the _in array
2023-06-24 13:15:01 -04:00
if (value == _in[pos]) return _out[pos];
2014-11-18 13:32:33 -05:00
2023-11-13 06:13:02 -05:00
// interpolate in the right segment for the rest
2023-06-24 13:15:01 -04:00
return (value - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1]) + _out[pos-1];
2014-11-18 13:32:33 -05:00
}
2023-11-13 06:13:02 -05:00
////////////////////////////////////////////////////////////////////////
//
// SINGLE TYPE MULTIMAP CACHE - LINEAR SEARCH
2022-11-18 09:09:05 -05:00
//
2023-06-24 13:15:01 -04:00
// note: the in array must have increasing values
2023-11-13 06:13:02 -05:00
// performance optimized version if inputs do not change often
// 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
// implements a minimal cache of the lastValue.
2020-11-27 05:20:37 -05:00
template<typename T>
2023-06-24 13:15:01 -04:00
T multiMapCache(T value, T* _in, T* _out, uint8_t size)
2014-11-18 13:32:33 -05:00
{
2023-06-24 13:15:01 -04:00
static T lastValue = -1;
2023-11-13 06:13:02 -05:00
static T cache = -1;
2014-11-18 13:32:33 -05:00
2023-06-24 13:15:01 -04:00
if (value == lastValue)
2021-01-29 06:31:58 -05:00
{
return cache;
}
2023-06-24 13:15:01 -04:00
lastValue = value;
2021-01-29 06:31:58 -05:00
2023-06-24 13:15:01 -04:00
// output is constrained to out array
2021-12-22 06:10:05 -05:00
if (value <= _in[0])
2021-01-29 06:31:58 -05:00
{
cache = _out[0];
}
2021-12-22 06:10:05 -05:00
else if (value >= _in[size-1])
2021-01-29 06:31:58 -05:00
{
cache = _out[size-1];
}
else
{
2023-06-24 13:15:01 -04:00
// search right interval; index 0 _in[0] already tested
2023-11-13 06:13:02 -05:00
uint8_t pos = 1;
2021-12-22 06:10:05 -05:00
while(value > _in[pos]) pos++;
2023-11-13 06:13:02 -05:00
// this will handle all exact "points" in the _in array
if (value == _in[pos])
2021-01-29 06:31:58 -05:00
{
cache = _out[pos];
}
2020-11-27 05:20:37 -05:00
else
2021-01-29 06:31:58 -05:00
{
2023-11-13 06:13:02 -05:00
// interpolate in the right segment for the rest
2021-12-22 06:10:05 -05:00
cache = (value - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1]) + _out[pos-1];
2021-01-29 06:31:58 -05:00
}
}
return cache;
2014-11-18 13:32:33 -05:00
}
2020-11-27 05:20:37 -05:00
2021-05-28 07:39:42 -04:00
2023-11-13 06:13:02 -05:00
////////////////////////////////////////////////////////////////////////
//
// SINGLE TYPE MULTIMAP - BINARY SEARCH
//
// should be faster for size >= 10
2023-06-24 13:15:01 -04:00
// (rule of thumb)
//
2023-11-13 06:13:02 -05:00
// note: the in array must have increasing values
2023-06-24 13:15:01 -04:00
template<typename T>
2023-11-13 06:13:02 -05:00
T multiMapBS(T value, T* _in, T* _out, uint8_t size)
{
// output is constrained to out array
if (value <= _in[0]) return _out[0];
if (value >= _in[size-1]) return _out[size-1];
// Binary Search, uint16_t needed to prevent overflow.
uint16_t lower = 0;
uint16_t upper = size - 1;
while (lower < upper - 1)
{
uint8_t mid = (lower + upper) / 2;
if (value >= _in[mid]) lower = mid;
else upper = mid;
}
return (value - _in[lower]) * (_out[upper] - _out[lower]) / (_in[upper] - _in[lower]) + _out[lower];
}
////////////////////////////////////////////////////////////////////////
//
// MULTITYPE MULTIMAP - LINEAR SEARCH
//
// note: the in array must have increasing values
template<typename T1, typename T2>
T2 multiMap(T1 value, T1* _in, T2* _out, uint8_t size)
{
// output is constrained to out array
if (value <= _in[0]) return _out[0];
if (value >= _in[size-1]) return _out[size-1];
// search right interval
uint16_t pos = 1; // _in[0] already tested
while(value > _in[pos]) pos++;
// this will handle all exact "points" in the _in array
if (value == _in[pos]) return _out[pos];
// interpolate in the right segment for the rest
return (value - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1]) + _out[pos-1];
}
////////////////////////////////////////////////////////////////////////
//
// MULTITYPE MULTIMAP - BINARY SEARCH
// should be faster for size >= 10
// (rule of thumb)
//
// note: the in array must have increasing values
template<typename T1, typename T2>
T2 multiMapBS(T1 value, T1* _in, T2* _out, uint8_t size)
2023-06-24 13:15:01 -04:00
{
// output is constrained to out array
if (value <= _in[0]) return _out[0];
if (value >= _in[size-1]) return _out[size-1];
2023-11-13 06:13:02 -05:00
// Binary Search, uint16_t needed to prevent overflow.
2023-06-24 13:15:01 -04:00
uint16_t lower = 0;
uint16_t upper = size - 1;
while (lower < upper - 1)
{
uint16_t mid = (lower + upper) / 2;
if (value >= _in[mid]) lower = mid;
else upper = mid;
}
return (value - _in[lower]) * (_out[upper] - _out[lower]) / (_in[upper] - _in[lower]) + _out[lower];
}
// -- END OF FILE --
2021-12-22 06:10:05 -05:00