mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-09-19 16:46:11 -04:00
0.4.0 FastMap
This commit is contained in:
parent
5e0c1b5641
commit
6c196e7c48
@ -1,3 +1,18 @@
|
||||
platforms:
|
||||
rpipico:
|
||||
board: rp2040:rp2040:rpipico
|
||||
package: rp2040:rp2040
|
||||
gcc:
|
||||
features:
|
||||
defines:
|
||||
- ARDUINO_ARCH_RP2040
|
||||
warnings:
|
||||
flags:
|
||||
|
||||
packages:
|
||||
rp2040:rp2040:
|
||||
url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
|
||||
|
||||
compile:
|
||||
# Choosing to run compilation tests on 2 different Arduino platforms
|
||||
platforms:
|
||||
@ -9,6 +24,7 @@ compile:
|
||||
- esp32
|
||||
# - esp8266
|
||||
# - mega2560
|
||||
- rpipico
|
||||
|
||||
# Declaring Dependent Arduino Libraries (to be installed via the Arduino Library Manager)
|
||||
libraries:
|
||||
|
72
libraries/FastMap/CHANGELOG.md
Normal file
72
libraries/FastMap/CHANGELOG.md
Normal file
@ -0,0 +1,72 @@
|
||||
# Change Log FastMap
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
|
||||
## [0.4.0] - 2022-11-02
|
||||
- add changelog.md
|
||||
- add rp2040 to build-CI
|
||||
- update readme.md
|
||||
- init() returns bool to indicate valid (non-zero) ranges.
|
||||
- add range check in init()
|
||||
|
||||
----
|
||||
|
||||
## [0.3.3] - 2021-12-17
|
||||
- update library.json
|
||||
- update license
|
||||
- minor edits
|
||||
|
||||
## [0.3.2] - 2020-12-21
|
||||
- add Arduino-CI + unit test
|
||||
|
||||
## [0.3.1] - 2020-08-31
|
||||
- update documentation
|
||||
|
||||
## [0.3.0] - 2020-07-04
|
||||
- added fastMapDouble + test sketch.
|
||||
|
||||
----
|
||||
|
||||
## [0.2.1] - 2020-06-10
|
||||
- fix library.json
|
||||
- rename license
|
||||
## [0.2.0] - 2020-03-21
|
||||
- #pragma once
|
||||
- readme.md
|
||||
- license.md
|
||||
|
||||
----
|
||||
|
||||
## [0.1.8] - 2017-07-27
|
||||
- revert double to float (issue 33)
|
||||
|
||||
## [0.1.7] - 2017-04-28
|
||||
- clean up code
|
||||
- get examples working again
|
||||
|
||||
## [0.1.06] - 2015-03-08
|
||||
- replaced float by double (support ARM)
|
||||
|
||||
## [0.1.05] - 2014-11-02
|
||||
- stripped of bit mask experimental code
|
||||
|
||||
## [0.1.04]
|
||||
- add back() - the inverse map
|
||||
- tested with bit mask for constrain code (Performance was killed)
|
||||
|
||||
## [0.1.03]
|
||||
- proper name
|
||||
|
||||
## [0.1.02]
|
||||
- squeezed the code (first public version)
|
||||
|
||||
## [0.1.01]
|
||||
- refactor
|
||||
|
||||
|
||||
## [0.1.00]
|
||||
- initial version
|
@ -1,51 +1,43 @@
|
||||
//
|
||||
// FILE: FastMap.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.3.3
|
||||
// VERSION: 0.4.0
|
||||
// PURPOSE: class with fast map function - library for Arduino
|
||||
// URL: https://github.com/RobTillaart/FastMap
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.3.3 2021-12-17 update library.json, license, minor edits
|
||||
// 0.3.2 2020-12-21 add Arduino-CI + unit test
|
||||
// 0.3.1 2020-08-31 updated documentation
|
||||
// 0.3.0 2020-07-04 added fastMapDouble + test sketch.
|
||||
// 0.2.1 2020-06-10 fix library.json; rename license
|
||||
// 0.2.0 2020-03-21 #pragma once; readme.md; license.md
|
||||
//
|
||||
// 0.1.8 2017-07-27 revert double to float (issue 33)
|
||||
// 0.1.7 2017-04-28 cleaned up, get examples working again
|
||||
// 0.1.06 2015-03-08 replaced float by double (support ARM)
|
||||
// 0.1.05 2014-11-02 stripped of bit mask experimental code
|
||||
// 0.1.04 add back() - the inverse map
|
||||
// tested with bit mask for constrain code (Performance was killed)
|
||||
// 0.1.03 proper name
|
||||
// 0.1.02 squeezed the code (first public version)
|
||||
// 0.1.01 refactor
|
||||
// 0.1.00 initial version
|
||||
// HISTORY: see changelog.md
|
||||
|
||||
|
||||
#include "FastMap.h"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// FASTMAP
|
||||
//
|
||||
FastMap::FastMap()
|
||||
{
|
||||
init(0, 1, 0, 1);
|
||||
}
|
||||
|
||||
|
||||
void FastMap::init(float in_min, float in_max, float out_min, float out_max)
|
||||
bool FastMap::init(float in_min, float in_max, float out_min, float out_max)
|
||||
{
|
||||
float _inRange = in_max - in_min;
|
||||
float _outRange = out_max - out_min;
|
||||
if ((_inRange == 0.0 ) || (_outRange == 0.0)) return false;
|
||||
|
||||
_in_min = in_min;
|
||||
_in_max = in_max;
|
||||
_out_min = out_min;
|
||||
_out_max = out_max;
|
||||
|
||||
_factor = (out_max - out_min)/(in_max - in_min);
|
||||
_base = out_min - in_min * _factor;
|
||||
_factor = _outRange/_inRange;
|
||||
_base = _out_min - _in_min * _factor;
|
||||
|
||||
_backfactor = 1/_factor;
|
||||
_backbase = in_min - out_min * _backfactor;
|
||||
_backfactor = _inRange/_outRange;
|
||||
_backbase = _in_min - _out_min * _backfactor;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -71,24 +63,33 @@ float FastMap::upperConstrainedMap(float value)
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// FASTMAP_DOUBLE
|
||||
//
|
||||
FastMapDouble::FastMapDouble()
|
||||
{
|
||||
init(0, 1, 0, 1);
|
||||
}
|
||||
|
||||
|
||||
void FastMapDouble::init(double in_min, double in_max, double out_min, double out_max)
|
||||
bool FastMapDouble::init(double in_min, double in_max, double out_min, double out_max)
|
||||
{
|
||||
double _inRange = in_max - in_min;
|
||||
double _outRange = out_max - out_min;
|
||||
if ((_inRange == 0.0 ) || (_outRange == 0.0)) return false;
|
||||
|
||||
_in_min = in_min;
|
||||
_in_max = in_max;
|
||||
_out_min = out_min;
|
||||
_out_max = out_max;
|
||||
|
||||
_factor = (out_max - out_min)/(in_max - in_min);
|
||||
_base = out_min - in_min * _factor;
|
||||
_factor = _outRange/_inRange;
|
||||
_base = _out_min - _in_min * _factor;
|
||||
|
||||
_backfactor = 1/_factor;
|
||||
_backbase = in_min - out_min * _backfactor;
|
||||
_backfactor = _inRange/_outRange;
|
||||
_backbase = _in_min - _out_min * _backfactor;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,15 +2,14 @@
|
||||
//
|
||||
// FILE: FastMap.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.3.3
|
||||
// VERSION: 0.4.0
|
||||
// PURPOSE: class with fast map function - library for Arduino
|
||||
// URL: https://github.com/RobTillaart/FastMap
|
||||
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#define FASTMAP_LIB_VERSION (F("0.3.3"))
|
||||
#define FASTMAP_LIB_VERSION (F("0.4.0"))
|
||||
|
||||
|
||||
class FastMap
|
||||
@ -18,7 +17,7 @@ class FastMap
|
||||
public:
|
||||
FastMap();
|
||||
|
||||
void init(const float in_min, const float in_max, const float out_min, const float out_max);
|
||||
bool init(float in_min, float in_max, float out_min, float out_max);
|
||||
|
||||
float inline map (const float value) { return _base + value * _factor; }
|
||||
float inline back (const float value) { return _backbase + value * _backfactor; }
|
||||
@ -38,7 +37,7 @@ class FastMapDouble
|
||||
{
|
||||
public:
|
||||
FastMapDouble();
|
||||
void init(const double in_min, const double in_max, const double out_min, const double out_max);
|
||||
bool init(double in_min, double in_max, double out_min, double out_max);
|
||||
|
||||
double inline map (const double value) { return _base + value * _factor; }
|
||||
double inline back (const double value) { return _backbase + value * _backfactor; }
|
||||
|
@ -15,7 +15,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/FastMap"
|
||||
},
|
||||
"version": "0.3.3",
|
||||
"version": "0.4.0",
|
||||
"license": "MIT",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=FastMap
|
||||
version=0.3.3
|
||||
version=0.4.0
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Library with fast map function for Arduino.
|
||||
|
@ -14,53 +14,64 @@ Fast mapping and constraining.
|
||||
## Description
|
||||
|
||||
FastMap is an object that pre-calculates (internal) floats to make a mapping function especially for floats.
|
||||
The Fastmap also provides a **back()** function to reverse the mapping.
|
||||
This only works well with floats, so use with care.
|
||||
The FastMap also provides a **back()** function to reverse the mapping.
|
||||
This only works well with floats, and less with integers, so use with care.
|
||||
|
||||
An important difference with the traditional **map()** function is that both **init()** and **map()**
|
||||
accepts floats as parameters, allowing mapping that would be hard to achieve with the normal **map()**
|
||||
function.
|
||||
accepts floats as parameters.
|
||||
This allows mapping that would be hard to achieve with the normal **map()** function.
|
||||
|
||||
Since 0.4.0 the **init()** function will not accept zero range defining input or output parameters.
|
||||
|
||||
## Performance notes
|
||||
|
||||
(based upon tests https://github.com/RobTillaart/FastMap/issues/4 )
|
||||
- On AVR (UNO and MEGA) no gain is made mapping integers with fastMap, 130% slower = substantial
|
||||
- On AVR the gain for float is limited, 10% faster
|
||||
- On ESP32 the gain for integers and float is both in the order of 25%
|
||||
- On AVR (UNO and MEGA) no gain is made mapping integers with fastMap, 130% slower = substantial.
|
||||
- On AVR the gain for float is limited, 10% faster.
|
||||
- On ESP32 the gain for integers and float is both in the order of 25%.
|
||||
|
||||
To see the actual gain in your project on your hardware you should test and compare.
|
||||
|
||||
FastMap is faster when mapping floats as it uses less float operations than the standard map formula does.
|
||||
The performance results from pre-calculating values in the **init()** function so actual mapping needs only
|
||||
one multiply and add, where the standard **map()** function uses four adds, a multiplication and a division.
|
||||
The performance results from pre-calculating values in the **init()** function.
|
||||
An actual mapping therefore needs only one multiply and one add operation where the standard **map()** function
|
||||
uses four adds, a multiplication and a division.
|
||||
The pre-calculation in **init()** should be taken in account and if every **map()** call needs an **init()**
|
||||
there will be no gain, on contrary.
|
||||
|
||||
|
||||
## Precision notes
|
||||
|
||||
The implementation of **fastMap()** uses floats (typical 32 bits) which might result in more memory usage
|
||||
and loss of precision for mapping of larger values, especially 32 and 64 bit integers.
|
||||
|
||||
This is caused by the limits of the mantissa (~23 bits) of the standard 4 byte float.
|
||||
To solve this a **FastMapDouble** class is added which uses the **double** type for the platforms
|
||||
that support 8 byte floats.
|
||||
If your platform does not support double it will often be mapped to float, so no gain.
|
||||
Furthermore using double might imply a performance penalty on some platforms.
|
||||
|
||||
|
||||
## Interface
|
||||
|
||||
- **void init(float in_min, float in_max, float out_min, float out_max);** defines the linear mapping parameters.
|
||||
- **bool init(float in_min, float in_max, float out_min, float out_max)** defines the linear mapping parameters.
|
||||
The **init()** function calculates all needed values for the **map()**, the **back()** call and the **constrainXX()** functions.
|
||||
The **init()** function can be called again with new values when needed to do other mapping,
|
||||
although it will give less overhead if you create an fastMap object per conversion needed.
|
||||
Note: **init()** does not check for a divide by zero (out_max == out_min) or (in_max == in_min)
|
||||
Returns false if (out_max == out_min) or (in_max == in_min). (breaking change in 0.4.0).
|
||||
- **float map(float value)** maps the parameter.
|
||||
- **float back(float value)** does the inverse mapping
|
||||
- **float back(float value)** does the inverse mapping.
|
||||
|
||||
|
||||
### Constrains
|
||||
|
||||
FastMap supports three versions of constraining the map function, based upon the parameters of **init()**
|
||||
- **float constrainedMap(float value);** returns a value between outMin .. outMax
|
||||
- **float lowerConstrainedMap(float value);** returns a value between outMin .. inf (No upper limit)
|
||||
- **float upperConstrainedMap(float value);** returns a value between -inf .. outMax
|
||||
FastMap supports three versions of constraining the map function, based upon the parameters of **init()**.
|
||||
|
||||
To change the constrain values call **init()** with new limits, or call **constrain()**
|
||||
- **float constrainedMap(float value);** returns a value between outMin .. outMax
|
||||
- **float lowerConstrainedMap(float value);** returns a value between outMin .. infinity, ==> no upper limit.
|
||||
- **float upperConstrainedMap(float value);** returns a value between -infinity .. outMax ==> no lower limit.
|
||||
|
||||
To change the constrain values call **init()** with new limits, or use the standard **constrain()**.
|
||||
|
||||
Note there are **NO** constrain-versions for **back(value)** function.
|
||||
|
||||
@ -72,6 +83,34 @@ This class is meant to support 8 bytes doubles in their native accuracy and prec
|
||||
To display doubles one might need the **sci()** function of my **printHelpers** class.
|
||||
https://github.com/RobTillaart/printHelpers
|
||||
|
||||
Note that on most embedded platforms the performance of doubles is less than floats.
|
||||
|
||||
#### boards supporting double
|
||||
|
||||
| board | float | double |
|
||||
|:---------------|:-------:|:--------:|
|
||||
| UNO | yes | no |
|
||||
| ATMEGA | yes | no |
|
||||
| MKR1000 | yes | yes |
|
||||
| Zero | yes | yes |
|
||||
| Teensy | yes | ? |
|
||||
| ESP32 | yes | yes |
|
||||
| RP2040 | yes | ? |
|
||||
|
||||
to elaborate table. (if someone has a good link, please let me know).
|
||||
|
||||
test code.
|
||||
```cpp
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.print("size of double:\t");
|
||||
Serial.println(sizeof(double));
|
||||
Serial.print("size of float: \t");
|
||||
Serial.println(sizeof(float));
|
||||
}
|
||||
void loop() {}
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
@ -80,9 +119,15 @@ See examples.
|
||||
|
||||
## Future
|
||||
|
||||
#### must
|
||||
|
||||
#### should
|
||||
- update documentation
|
||||
- test performance fastMapDouble on ESP32.
|
||||
|
||||
#### could
|
||||
- investigate map function for complex numbers? / coordinates?
|
||||
- can fastMap and fastMapDouble be in a class hierarchy? gain?
|
||||
- Template class?
|
||||
- test performance fastMapDouble on ESP32.
|
||||
|
||||
|
||||
|
@ -39,6 +39,23 @@ unittest_teardown()
|
||||
}
|
||||
|
||||
|
||||
unittest(test_init)
|
||||
{
|
||||
FastMap fm;
|
||||
FastMapDouble fmd;
|
||||
|
||||
assertTrue(fm.init(-2, 12, 17, 42));
|
||||
assertFalse(fm.init(12, 12, 17, 42));
|
||||
assertFalse(fm.init(-2, 12, 17, 17));
|
||||
assertFalse(fm.init(12, 12, 17, 17));
|
||||
|
||||
assertTrue(fmd.init(-2, 12, 17, 42));
|
||||
assertFalse(fmd.init(12, 12, 17, 42));
|
||||
assertFalse(fmd.init(-2, 12, 17, 17));
|
||||
assertFalse(fmd.init(12, 12, 17, 17));
|
||||
}
|
||||
|
||||
|
||||
unittest(test_map)
|
||||
{
|
||||
FastMap fm;
|
||||
|
Loading…
Reference in New Issue
Block a user