├── .arduino-ci.yml ├── .github ├── FUNDING.yml └── workflows │ ├── arduino-lint.yml │ ├── arduino_test_runner.yml │ └── jsoncheck.yml ├── CHANGELOG.md ├── FastMap.cpp ├── FastMap.h ├── LICENSE ├── README.md ├── examples ├── constrainedMapDemo │ └── constrainedMapDemo.ino ├── fastMapDemo │ └── fastMapDemo.ino ├── fastMapDemo2 │ └── fastMapDemo2.ino ├── fastMapDemo3 │ └── fastMapDemo3.ino ├── fastMapDemo4 │ └── fastMapDemo4.ino ├── fastMapDouble │ └── fastMapDouble.ino └── fastMap_performance_test │ ├── fastMap_performance_test.ino │ ├── performance_0.4.1_ESP32.txt │ └── performance_0.4.1_UNO.txt ├── keywords.txt ├── library.json ├── library.properties └── test └── unit_test_001.cpp /.arduino-ci.yml: -------------------------------------------------------------------------------- 1 | platforms: 2 | rpipico: 3 | board: rp2040:rp2040:rpipico 4 | package: rp2040:rp2040 5 | gcc: 6 | features: 7 | defines: 8 | - ARDUINO_ARCH_RP2040 9 | warnings: 10 | flags: 11 | 12 | packages: 13 | rp2040:rp2040: 14 | url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json 15 | 16 | compile: 17 | # Choosing to run compilation tests on 2 different Arduino platforms 18 | platforms: 19 | - uno 20 | # - due 21 | # - zero 22 | # - leonardo 23 | - m4 24 | - esp32 25 | # - esp8266 26 | # - mega2560 27 | - rpipico 28 | 29 | # Declaring Dependent Arduino Libraries (to be installed via the Arduino Library Manager) 30 | libraries: 31 | - "printHelpers" 32 | 33 | 34 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: RobTillaart 4 | custom: "https://www.paypal.me/robtillaart" 5 | -------------------------------------------------------------------------------- /.github/workflows/arduino-lint.yml: -------------------------------------------------------------------------------- 1 | name: Arduino-lint 2 | 3 | on: [push, pull_request] 4 | jobs: 5 | lint: 6 | runs-on: ubuntu-latest 7 | timeout-minutes: 5 8 | steps: 9 | - uses: actions/checkout@v4 10 | - uses: arduino/arduino-lint-action@v1 11 | with: 12 | library-manager: update 13 | compliance: strict -------------------------------------------------------------------------------- /.github/workflows/arduino_test_runner.yml: -------------------------------------------------------------------------------- 1 | name: Arduino CI 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | runTest: 7 | runs-on: ubuntu-latest 8 | timeout-minutes: 20 9 | 10 | steps: 11 | - uses: actions/checkout@v4 12 | - uses: ruby/setup-ruby@v1 13 | with: 14 | ruby-version: 2.6 15 | - run: | 16 | gem install arduino_ci 17 | arduino_ci.rb 18 | -------------------------------------------------------------------------------- /.github/workflows/jsoncheck.yml: -------------------------------------------------------------------------------- 1 | name: JSON check 2 | 3 | on: 4 | push: 5 | paths: 6 | - '**.json' 7 | pull_request: 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-latest 12 | timeout-minutes: 5 13 | steps: 14 | - uses: actions/checkout@v4 15 | - name: json-syntax-check 16 | uses: limitusus/json-syntax-check@v2 17 | with: 18 | pattern: "\\.json$" -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log FastMap 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](http://keepachangelog.com/) 6 | and this project adheres to [Semantic Versioning](http://semver.org/). 7 | 8 | 9 | ## [0.4.2] - 2024-02-02 10 | - update readme.md 11 | - a.o. rewrite description, future section. 12 | - minor refactor examples 13 | - minor edits 14 | 15 | 16 | ## [0.4.1] - 2023-10-30 17 | - update readme.md (badges). 18 | - add performance test example (another). 19 | - add UNO + ESP32 test results. 20 | - minor edits. 21 | 22 | ## [0.4.0] - 2022-11-02 23 | - add changelog.md 24 | - add rp2040 to build-CI 25 | - update readme.md 26 | - init() returns bool to indicate valid (non-zero) ranges. 27 | - add range check in init() 28 | 29 | ---- 30 | 31 | ## [0.3.3] - 2021-12-17 32 | - update library.json 33 | - update license 34 | - minor edits 35 | 36 | ## [0.3.2] - 2020-12-21 37 | - add Arduino-CI + unit test 38 | 39 | ## [0.3.1] - 2020-08-31 40 | - update documentation 41 | 42 | ## [0.3.0] - 2020-07-04 43 | - added fastMapDouble + test sketch. 44 | 45 | ---- 46 | 47 | ## [0.2.1] - 2020-06-10 48 | - fix library.json 49 | - rename license 50 | ## [0.2.0] - 2020-03-21 51 | - #pragma once 52 | - readme.md 53 | - license.md 54 | 55 | ---- 56 | 57 | ## [0.1.8] - 2017-07-27 58 | - revert double to float (issue 33) 59 | 60 | ## [0.1.7] - 2017-04-28 61 | - clean up code 62 | - get examples working again 63 | 64 | ## [0.1.06] - 2015-03-08 65 | - replaced float by double (support ARM) 66 | 67 | ## [0.1.05] - 2014-11-02 68 | - stripped of bit mask experimental code 69 | 70 | ## [0.1.04] 71 | - add back() - the inverse map 72 | - tested with bit mask for constrain code (Performance was killed) 73 | 74 | ## [0.1.03] 75 | - proper name 76 | 77 | ## [0.1.02] 78 | - squeezed the code (first public version) 79 | 80 | ## [0.1.01] 81 | - refactor 82 | 83 | 84 | ## [0.1.00] 85 | - initial version 86 | -------------------------------------------------------------------------------- /FastMap.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: FastMap.cpp 3 | // AUTHOR: Rob Tillaart 4 | // VERSION: 0.4.2 5 | // PURPOSE: class with fast map function - library for Arduino 6 | // URL: https://github.com/RobTillaart/FastMap 7 | 8 | 9 | #include "FastMap.h" 10 | 11 | 12 | /////////////////////////////////////////////////////////////// 13 | // 14 | // FASTMAP 15 | // 16 | FastMap::FastMap() 17 | { 18 | init(0, 1, 0, 1); 19 | } 20 | 21 | 22 | bool FastMap::init(float in_min, float in_max, float out_min, float out_max) 23 | { 24 | float _inRange = in_max - in_min; 25 | float _outRange = out_max - out_min; 26 | if ((_inRange == 0.0 ) || (_outRange == 0.0)) return false; 27 | 28 | _in_min = in_min; 29 | _in_max = in_max; 30 | _out_min = out_min; 31 | _out_max = out_max; 32 | 33 | _factor = _outRange/_inRange; 34 | _base = _out_min - _in_min * _factor; 35 | 36 | _backfactor = _inRange/_outRange; 37 | _backbase = _in_min - _out_min * _backfactor; 38 | return true; 39 | } 40 | 41 | 42 | float FastMap::constrainedMap(float value) 43 | { 44 | if (value <= _in_min) return _out_min; 45 | if (value >= _in_max) return _out_max; 46 | return this->map(value); 47 | } 48 | 49 | 50 | float FastMap::lowerConstrainedMap(float value) 51 | { 52 | if (value <= _in_min) return _out_min; 53 | return this->map(value); 54 | } 55 | 56 | 57 | float FastMap::upperConstrainedMap(float value) 58 | { 59 | if (value >= _in_max) return _out_max; 60 | return this->map(value); 61 | } 62 | 63 | 64 | /////////////////////////////////////////////////////////////// 65 | // 66 | // FASTMAP_DOUBLE 67 | // 68 | FastMapDouble::FastMapDouble() 69 | { 70 | init(0, 1, 0, 1); 71 | } 72 | 73 | 74 | bool FastMapDouble::init(double in_min, double in_max, double out_min, double out_max) 75 | { 76 | double _inRange = in_max - in_min; 77 | double _outRange = out_max - out_min; 78 | if ((_inRange == 0.0 ) || (_outRange == 0.0)) return false; 79 | 80 | _in_min = in_min; 81 | _in_max = in_max; 82 | _out_min = out_min; 83 | _out_max = out_max; 84 | 85 | _factor = _outRange/_inRange; 86 | _base = _out_min - _in_min * _factor; 87 | 88 | _backfactor = _inRange/_outRange; 89 | _backbase = _in_min - _out_min * _backfactor; 90 | return true; 91 | } 92 | 93 | 94 | double FastMapDouble::constrainedMap(double value) 95 | { 96 | if (value <= _in_min) return _out_min; 97 | if (value >= _in_max) return _out_max; 98 | return this->map(value); 99 | } 100 | 101 | 102 | double FastMapDouble::lowerConstrainedMap(double value) 103 | { 104 | if (value <= _in_min) return _out_min; 105 | return this->map(value); 106 | } 107 | 108 | 109 | double FastMapDouble::upperConstrainedMap(double value) 110 | { 111 | if (value >= _in_max) return _out_max; 112 | return this->map(value); 113 | } 114 | 115 | 116 | // -- END OF FILE -- 117 | 118 | -------------------------------------------------------------------------------- /FastMap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // 3 | // FILE: FastMap.h 4 | // AUTHOR: Rob Tillaart 5 | // VERSION: 0.4.2 6 | // PURPOSE: class with fast map function - library for Arduino 7 | // URL: https://github.com/RobTillaart/FastMap 8 | 9 | 10 | #include "Arduino.h" 11 | 12 | #define FASTMAP_LIB_VERSION (F("0.4.2")) 13 | 14 | 15 | class FastMap 16 | { 17 | public: 18 | FastMap(); 19 | 20 | bool init(float in_min, float in_max, float out_min, float out_max); 21 | 22 | float inline map (const float value) { return _base + value * _factor; } 23 | float inline back (const float value) { return _backbase + value * _backfactor; } 24 | 25 | float constrainedMap(const float value); 26 | float lowerConstrainedMap(const float value); 27 | float upperConstrainedMap(const float value); 28 | 29 | private: 30 | float _in_min, _in_max, _out_min, _out_max; 31 | float _factor, _base; 32 | float _backfactor, _backbase; 33 | }; 34 | 35 | 36 | class FastMapDouble 37 | { 38 | public: 39 | FastMapDouble(); 40 | bool init(double in_min, double in_max, double out_min, double out_max); 41 | 42 | double inline map (const double value) { return _base + value * _factor; } 43 | double inline back (const double value) { return _backbase + value * _backfactor; } 44 | 45 | double constrainedMap(const double value); 46 | double lowerConstrainedMap(const double value); 47 | double upperConstrainedMap(const double value); 48 | 49 | private: 50 | double _in_min, _in_max, _out_min, _out_max; 51 | double _factor, _base; 52 | double _backfactor, _backbase; 53 | }; 54 | 55 | 56 | // -- END OF FILE -- 57 | 58 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2010-2024 Rob Tillaart 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | [![Arduino CI](https://github.com/RobTillaart/FastMap/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci) 3 | [![Arduino-lint](https://github.com/RobTillaart/FastMap/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/FastMap/actions/workflows/arduino-lint.yml) 4 | [![JSON check](https://github.com/RobTillaart/FastMap/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/FastMap/actions/workflows/jsoncheck.yml) 5 | [![GitHub issues](https://img.shields.io/github/issues/RobTillaart/FastMap.svg)](https://github.com/RobTillaart/FastMap/issues) 6 | 7 | [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/FastMap/blob/master/LICENSE) 8 | [![GitHub release](https://img.shields.io/github/release/RobTillaart/FastMap.svg?maxAge=3600)](https://github.com/RobTillaart/FastMap/releases) 9 | [![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/FastMap.svg)](https://registry.platformio.org/libraries/robtillaart/FastMap) 10 | 11 | 12 | # FastMap 13 | 14 | Fast mapping and constraining. 15 | 16 | 17 | ## Description 18 | 19 | FastMap replaces the Arduino **map()** function which does integer mapping. 20 | The result of integer mapping is that the (internal) division truncates and looses precision. 21 | 22 | Another problem possible problem of the **map()** function is that it can extrapolate 23 | outside the output range specified if the input is outside the input range. 24 | This behaviour is not always wanted, and can cause unexpected side effects. 25 | 26 | **FastMap** is an object that pre-calculates (internal) floats to make a mapping function 27 | especially for floats (and doubles). 28 | The usage of floats reduces the truncating problem of **map()** and keeps precision. 29 | As it pre-calculates the mapping partially the performance is good. 30 | See **FastMap_performance_test.ino**. 31 | 32 | To prevent extrapolating **FastMap** provides so called **constrainedMap()** which takes 33 | care that the returned value is within the specified output range. 34 | The library provides three variations, see API below. 35 | 36 | Finally the **FastMap** provides a **back()** function to reverse the mapping. 37 | This only works well with floats, and less with integers, so use with care and 38 | verify if it meet your requirements. 39 | 40 | An important difference with the traditional **map()** function is that both 41 | **init()** and **map()** accepts floats as parameters. 42 | See the precision notes below 43 | 44 | Since 0.4.0 the **init()** function will not accept a zero range defining input or output parameters. 45 | This is to prevent NaN errors and **init()** will return false if such range is detected. 46 | 47 | If the **init()** function is not called a 1 to 1 mapping is used. 48 | 49 | #### Related 50 | 51 | Other mapping libraries 52 | 53 | - https://github.com/RobTillaart/FastMap 54 | - https://github.com/RobTillaart/Gamma 55 | - https://github.com/RobTillaart/map2colour 56 | - https://github.com/RobTillaart/moduloMap 57 | - https://github.com/RobTillaart/MultiMap 58 | 59 | 60 | ## Performance notes 61 | 62 | (based upon tests https://github.com/RobTillaart/FastMap/issues/4 ) 63 | - On AVR (UNO and MEGA) no gain is made mapping integers with FastMap, 130% slower = substantial. 64 | - On AVR the gain for float is limited, 10% faster. 65 | - On ESP32 the gain for integers and float is both in the order of 25%. 66 | 67 | To see the actual gain in your project on your hardware you should test and compare. 68 | 69 | **FastMap** is faster when mapping floats as it uses less float operations than the standard map formula does. 70 | The performance results from pre-calculating values in the **init()** function. 71 | An actual mapping therefore needs only one multiply and one add operation where the 72 | standard **map()** function uses four adds, a multiplication and a division. 73 | The pre-calculation in **init()** should be taken in account and if every **map()** 74 | call needs an **init()** there will be no gain, on contrary. 75 | 76 | 77 | ## Precision notes 78 | 79 | The implementation of **FastMap()** uses floats (typical 32 bits) which might result in more memory usage 80 | and loss of precision for mapping of larger values, especially 32 and 64 bit integers. 81 | 82 | This is caused by the limits of the mantissa (~23 bits) of the standard 4 byte float. 83 | To solve this a **FastMapDouble** class is added which uses the **double** type for the platforms 84 | that support 8 byte floats. 85 | If your platform does not support double it will often be mapped to float, so no gain. 86 | Furthermore using double might imply a performance penalty on some platforms. 87 | 88 | 89 | ## Interface 90 | 91 | ```cpp 92 | #include "FastMap.h" 93 | ``` 94 | 95 | #### Base 96 | 97 | - **FastMap()** Constructor 98 | - **bool init(float in_min, float in_max, float out_min, float out_max)** defines the linear mapping parameters. 99 | Be sure that in_min must be smaller than in_max. 100 | The **init()** function calculates all needed values for the **map()**, the **back()** call and the **constrainXX()** functions. 101 | The **init()** function can be called again with new values when needed to do other mapping, 102 | although it will give less overhead if you create an FastMap object per conversion needed. 103 | Returns false if (out_max == out_min) or (in_max == in_min). (breaking change in 0.4.0). 104 | If **init()** is not called the default is 1 to 1 mapping. 105 | - **float map(float value)** maps the parameter. 106 | - **float back(float value)** does the inverse mapping. 107 | 108 | 109 | #### Constrains 110 | 111 | FastMap supports three versions of constraining the map function, based upon the parameters of **init()**. 112 | 113 | - **float constrainedMap(float value);** returns a value between outMin .. outMax 114 | - **float lowerConstrainedMap(float value);** returns a value between outMin .. infinity, ==> no upper limit. 115 | - **float upperConstrainedMap(float value);** returns a value between -infinity .. outMax ==> no lower limit. 116 | 117 | To change the constrain values call **init()** with new limits, or use the standard **constrain()**. 118 | 119 | Note there are **NO** constrain-versions for **back(value)** function. 120 | 121 | 122 | ## FastMapDouble 123 | 124 | Version 3.0 adds **FastMapDouble** which has the same interface as **FastMap()**. 125 | This class is meant to support 8 bytes doubles in their native accuracy and precision. 126 | To display doubles one might need the **sci()** function of my **printHelpers** class. 127 | https://github.com/RobTillaart/printHelpers 128 | 129 | Note that on most embedded platforms the performance of doubles is less than floats. 130 | See below. 131 | 132 | 133 | #### boards supporting double 134 | 135 | | board | float | double | 136 | |:---------------|:-------:|:--------:| 137 | | UNO | yes | no | 138 | | ATMEGA | yes | no | 139 | | MKR1000 | yes | yes | 140 | | Zero | yes | yes | 141 | | Teensy | yes | ? | 142 | | ESP32 | yes | yes | 143 | | RP2040 | yes | ? | 144 | 145 | To elaborate table. (if someone has a good link, please let me know). 146 | 147 | 148 | test code. 149 | ```cpp 150 | void setup() { 151 | Serial.begin(115200); 152 | Serial.print("size of double:\t"); 153 | Serial.println(sizeof(double)); 154 | Serial.print("size of float: \t"); 155 | Serial.println(sizeof(float)); 156 | } 157 | void loop() {} 158 | ``` 159 | 160 | 161 | ## Performance 162 | 163 | Tested version 0.4.1 with **FastMap_performance_test.ino** 164 | 165 | | | MAP | FastMap | FastMap dbl | Notes | 166 | |:--------|:--------:|:---------:|:-------------:|:-------:| 167 | | UNO | 496072 | 211888 | 211888 | float == double 168 | | ESP32 | 1814 | 627 | 6924 | 169 | 170 | 171 | UNO scores factor 2.34 172 | ESP32 scores factor 2.89 173 | 174 | Note: the 8 byte double (ESP32) is ~11 x slower than the float version, 175 | and ~4 x slower than the default map function. 176 | So unless the precision of 8 bytes double is required one better 177 | uses the float version. 178 | 179 | Note: always do your own performance measurements! 180 | 181 | If you have additional performance figures for other boards, 182 | please let me know (report via an issue). 183 | 184 | 185 | ## Percentage 186 | 187 | An often useful mapping is an input range upon percentage. 188 | ``` 189 | FM.init(in_min, in_max, 0.0, 100.0); 190 | ``` 191 | 192 | 193 | ## Future 194 | 195 | #### Must 196 | 197 | - update documentation 198 | 199 | #### Should 200 | 201 | 202 | #### Could 203 | 204 | - investigate map function for 64 bit integers. 205 | - investigate map function for complex numbers? / coordinates? 206 | - what does linear interpolation mean, map an input area upon an output area? 207 | - Template class? 208 | - investigate exponential mapping: ```x -> alpha * beta^x```?? 209 | - do we need **constrainedBack()**? in three versions? 210 | 211 | #### Wont 212 | 213 | - can FastMap and FastMapDouble be in a class hierarchy? limited gain? 214 | 215 | 216 | ## Support 217 | 218 | If you appreciate my libraries, you can support the development and maintenance. 219 | Improve the quality of the libraries by providing issues and Pull Requests, or 220 | donate through PayPal or GitHub sponsors. 221 | 222 | Thank you, 223 | 224 | 225 | 226 | -------------------------------------------------------------------------------- /examples/constrainedMapDemo/constrainedMapDemo.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: constrainedMap.ino 3 | // AUTHOR: Rob Tillaart 4 | // PURPOSE: demo of FastMap class ==> merge map and constrain functions 5 | // URL: https://github.com/RobTillaart/FastMap 6 | 7 | 8 | #include "FastMap.h" 9 | 10 | FastMap mapper; 11 | 12 | 13 | void setup() 14 | { 15 | Serial.begin(115200); 16 | Serial.println(__FILE__); 17 | Serial.print("FASTMAP_LIB_VERSION: "); 18 | Serial.println(FASTMAP_LIB_VERSION); 19 | Serial.println(); 20 | 21 | mapper.init(0, 10, 0, 300); 22 | 23 | Serial.println("I\t\tMAP\t\tLCM\t\tUCM\t\tCM"); 24 | for (int i = -5; i < 20; i++) 25 | { 26 | float a = map(i, 0, 10, 0, 300); 27 | float b = mapper.lowerConstrainedMap(i); 28 | float c = mapper.upperConstrainedMap(i); 29 | float d = mapper.constrainedMap(i); 30 | Serial.print(i); 31 | Serial.print("\t\t"); 32 | Serial.print(a); 33 | Serial.print("\t\t"); 34 | Serial.print(b); 35 | Serial.print("\t\t"); 36 | Serial.print(c); 37 | Serial.print("\t\t"); 38 | Serial.println(d); 39 | } 40 | Serial.println("\ndone..."); 41 | } 42 | 43 | 44 | void loop() 45 | { 46 | } 47 | 48 | 49 | // -- END OF FILE -- 50 | -------------------------------------------------------------------------------- /examples/fastMapDemo/fastMapDemo.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: fastMapDemo.ino 3 | // AUTHOR: Rob Tillaart 4 | // PURPOSE: demo of FastMap class ==> a faster map function 5 | // URL: https://github.com/RobTillaart/FastMap 6 | 7 | 8 | #include "FastMap.h" 9 | 10 | uint32_t start; 11 | uint32_t stop; 12 | uint32_t reference; 13 | 14 | volatile long zz = 30000, yy = 20000; 15 | volatile float x; 16 | 17 | FastMap mapper; 18 | 19 | 20 | void setup() 21 | { 22 | Serial.begin(115200); 23 | Serial.println(__FILE__); 24 | Serial.print("FASTMAP_LIB_VERSION: "); 25 | Serial.println(FASTMAP_LIB_VERSION); 26 | Serial.println(); 27 | 28 | // Get a non optimizable value; 29 | int z = analogRead(A0); 30 | 31 | // REFERENCE 32 | start = micros(); 33 | for (int i = 0; i < 10000; i++) 34 | { 35 | x = map(z, 0, 1023, yy, zz); 36 | } 37 | stop = micros(); 38 | reference = stop - start; 39 | Serial.println(reference); 40 | Serial.print(z); 41 | Serial.print(" -> "); 42 | Serial.println(x); 43 | Serial.println(); 44 | 45 | // FASTMAP 46 | mapper.init(0, 1023, yy, zz); 47 | start = micros(); 48 | for (int i = 0; i < 10000; i++) 49 | { 50 | x = mapper.map(z); 51 | } 52 | stop = micros(); 53 | Serial.println(stop - start); 54 | Serial.print(z); 55 | Serial.print(" -> "); 56 | Serial.println(x); 57 | 58 | // GAIN 59 | Serial.print("Performance factor: "); 60 | Serial.println((float)reference / (stop - start)); 61 | } 62 | 63 | 64 | void loop() 65 | { 66 | } 67 | 68 | 69 | // -- END OF FILE -- 70 | -------------------------------------------------------------------------------- /examples/fastMapDemo2/fastMapDemo2.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: fastMapDemo2.ino 3 | // AUTHOR: Rob Tillaart 4 | // PURPOSE: demo of FastMap class ==> a faster map function 5 | // URL: https://github.com/RobTillaart/FastMap 6 | 7 | 8 | #include "FastMap.h" 9 | 10 | FastMap CtoF; // Celsius to Fahrenheit 11 | FastMap FtoC; // Fahrenheit to Celsius 12 | 13 | 14 | void setup() 15 | { 16 | Serial.begin(115200); 17 | Serial.println(__FILE__); 18 | Serial.print("FASTMAP_LIB_VERSION: "); 19 | Serial.println(FASTMAP_LIB_VERSION); 20 | Serial.println(); 21 | 22 | CtoF.init(0, 100, 32, 212); 23 | FtoC.init(32, 212, 0, 100); 24 | 25 | float f = FtoC.map(163); 26 | Serial.print(f); 27 | Serial.print(char(223)); 28 | Serial.println('C'); 29 | 30 | float c = CtoF.map(f); 31 | Serial.print(c); 32 | Serial.print(char(223)); 33 | Serial.println('F'); 34 | } 35 | 36 | 37 | void loop() 38 | { 39 | } 40 | 41 | 42 | // -- END OF FILE -- 43 | 44 | -------------------------------------------------------------------------------- /examples/fastMapDemo3/fastMapDemo3.ino: -------------------------------------------------------------------------------- 1 | // FILE: fastMapDemo3.ino 2 | // AUTHOR: Rob Tillaart 3 | // PURPOSE: demo of FastMap class ==> a faster map function 4 | // URL: https://github.com/RobTillaart/FastMap 5 | // http://forum.arduino.cc/index.php?topic=276194 6 | 7 | 8 | #include "FastMap.h" 9 | 10 | FastMap CtoF; // Celsius to Fahrenheit 11 | 12 | 13 | void setup() 14 | { 15 | Serial.begin(115200); 16 | Serial.println(__FILE__); 17 | Serial.print("FASTMAP_LIB_VERSION: "); 18 | Serial.println(FASTMAP_LIB_VERSION); 19 | Serial.println(); 20 | 21 | CtoF.init(0, 100, 32, 212); 22 | 23 | float f = CtoF.map(163); 24 | Serial.print(f); 25 | Serial.print(char(176)); 26 | Serial.println('F'); 27 | 28 | float c = CtoF.back(f); 29 | Serial.print(c); 30 | Serial.print(char(176)); 31 | Serial.println('C'); 32 | 33 | f = CtoF.upperConstrainedMap(163); 34 | Serial.print(f); 35 | Serial.print(char(176)); 36 | Serial.println('F'); 37 | 38 | f = CtoF.lowerConstrainedMap(163); 39 | Serial.print(f); 40 | Serial.print(char(176)); 41 | Serial.println('C'); 42 | } 43 | 44 | void loop() 45 | { 46 | } 47 | 48 | 49 | // -- END OF FILE -- 50 | -------------------------------------------------------------------------------- /examples/fastMapDemo4/fastMapDemo4.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: fastMapDemo4.ino 3 | // AUTHOR: Rob Tillaart 4 | // PURPOSE: demo of FastMap class ==> a faster map function 5 | // URL: https://github.com/RobTillaart/FastMap 6 | 7 | 8 | #include "FastMap.h" 9 | 10 | uint32_t start; 11 | uint32_t stop; 12 | uint32_t reference; 13 | 14 | volatile long zz = 3000, yy = 20000; 15 | volatile float x; 16 | 17 | FastMap mapper; 18 | 19 | 20 | void setup() 21 | { 22 | Serial.begin(115200); 23 | Serial.println(__FILE__); 24 | Serial.print("FASTMAP_LIB_VERSION: "); 25 | Serial.println(FASTMAP_LIB_VERSION); 26 | Serial.println(); 27 | 28 | // Get a non optimizable value; 29 | int z = analogRead(A0); 30 | 31 | // REFERENCE 32 | start = micros(); 33 | for (int i = 0; i < 10000; i++) 34 | { 35 | x = map(z, 0, 1023, yy, zz); 36 | } 37 | stop = micros(); 38 | reference = stop - start; 39 | Serial.print("map():\t"); 40 | Serial.println(reference); 41 | Serial.print(z); 42 | Serial.print(" -> "); 43 | Serial.println(x); 44 | Serial.println(); 45 | 46 | // FASTMAP 47 | mapper.init(0, 1023, yy, zz); 48 | start = micros(); 49 | for (int i = 0; i < 10000; i++) 50 | { 51 | x = mapper.map(z); 52 | } 53 | stop = micros(); 54 | Serial.print("fastmap.map():\t"); 55 | Serial.println(stop - start); 56 | Serial.print(z); 57 | Serial.print(" -> "); 58 | Serial.println(x); 59 | 60 | // GAIN 61 | Serial.print("Performance factor: "); 62 | Serial.println((float)reference / (stop - start)); 63 | Serial.println(); 64 | 65 | // constrainedMap 66 | mapper.init(0, 1023, yy, zz); 67 | start = micros(); 68 | for (int i = 0; i < 10000; i++) 69 | { 70 | x = mapper.constrainedMap(z); 71 | } 72 | stop = micros(); 73 | Serial.print("fastmap.constrainedMap():\t"); 74 | Serial.println(stop - start); 75 | Serial.print(z); 76 | Serial.print(" -> "); 77 | Serial.println(x); 78 | 79 | // GAIN 80 | Serial.print("Performance factor: "); 81 | Serial.println((float)reference / (stop - start)); 82 | Serial.println(); 83 | 84 | // lowerConstrainedMap 85 | mapper.init(0, 1023, yy, zz); 86 | start = micros(); 87 | for (int i = 0; i < 10000; i++) 88 | { 89 | x = mapper.lowerConstrainedMap(z); 90 | } 91 | stop = micros(); 92 | Serial.print("fastmap.lowerConstrainedMap():\t"); 93 | Serial.println(stop - start); 94 | Serial.print(z); 95 | Serial.print(" -> "); 96 | Serial.println(x); 97 | 98 | // GAIN 99 | Serial.print("Performance factor: "); 100 | Serial.println((float)reference / (stop - start)); 101 | Serial.println(); 102 | 103 | // upperConstrainedMap 104 | mapper.init(0, 1023, yy, zz); 105 | start = micros(); 106 | for (int i = 0; i < 10000; i++) 107 | { 108 | x = mapper.upperConstrainedMap(z); 109 | } 110 | stop = micros(); 111 | Serial.print("fastmap.upperConstrainedMap():\t"); 112 | Serial.println(stop - start); 113 | Serial.print(z); 114 | Serial.print(" -> "); 115 | Serial.println(x); 116 | 117 | // GAIN 118 | Serial.print("Performance factor: "); 119 | Serial.println((float)reference / (stop - start)); 120 | Serial.println(); 121 | 122 | Serial.println("done..."); 123 | } 124 | 125 | 126 | void loop() 127 | { 128 | } 129 | 130 | 131 | // -- END OF FILE -- 132 | -------------------------------------------------------------------------------- /examples/fastMapDouble/fastMapDouble.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: fastMapDouble.ino 3 | // AUTHOR: Rob Tillaart 4 | // PURPOSE: demo of FastMapDouble class 5 | // URL: https://github.com/RobTillaart/FastMap 6 | // 7 | // Note: the mapping used in the example cannot be done 8 | // with the normal map function. 9 | 10 | 11 | #include "FastMap.h" 12 | 13 | #include "printHelpers.h" // https://github.com/RobTillaart/printHelpers 14 | 15 | uint32_t start, stop; 16 | volatile double x; 17 | 18 | FastMapDouble mapper; 19 | 20 | 21 | void setup() 22 | { 23 | Serial.begin(115200); 24 | Serial.println(__FILE__); 25 | Serial.print("FASTMAP_LIB_VERSION: "); 26 | Serial.println(FASTMAP_LIB_VERSION); 27 | Serial.println(); 28 | 29 | // Get a non optimizable value; 30 | volatile double pie = PI; 31 | 32 | // FASTMAP 33 | // map 0 .. 100% to lightspeed in km/hr 34 | mapper.init(0, 100, 0, 1.0792528488E+12); 35 | start = micros(); 36 | for (int i = 0; i < 10000; i++) 37 | { 38 | x = mapper.map(pie); 39 | } 40 | stop = micros(); 41 | Serial.print("10000 calls map:\t"); 42 | Serial.print(pie, 5); 43 | Serial.print(" -> "); 44 | Serial.println(sci(x, 5)); 45 | Serial.print(" time:\t"); 46 | Serial.println(stop - start); 47 | Serial.println(); 48 | 49 | Serial.println("PERC\tSpeed in Km/h"); 50 | for (float p = 80; p <= 100; p += 0.25) 51 | { 52 | x = mapper.map(p); 53 | Serial.print(p, 2); 54 | Serial.print('\t'); 55 | Serial.print(sci(x, 4)); 56 | Serial.println(); 57 | } 58 | Serial.println("\nDone..."); 59 | } 60 | 61 | 62 | void loop() 63 | { 64 | } 65 | 66 | 67 | // -- END OF FILE -- 68 | -------------------------------------------------------------------------------- /examples/fastMap_performance_test/fastMap_performance_test.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: fastMap_performance_test.ino 3 | // AUTHOR: Rob Tillaart 4 | // PURPOSE: demo of FastMap class ==> a faster map function 5 | // URL: https://github.com/RobTillaart/FastMap 6 | 7 | 8 | #include "FastMap.h" 9 | 10 | uint32_t start; 11 | uint32_t stop; 12 | uint32_t reference; 13 | 14 | volatile long zz = 3000, yy = 20000; 15 | volatile float x; 16 | volatile int z; 17 | 18 | FastMap mapper; 19 | FastMapDouble mapperD; 20 | 21 | 22 | void setup() 23 | { 24 | Serial.begin(115200); 25 | Serial.println(); 26 | Serial.println(__FILE__); 27 | Serial.print("FASTMAP_LIB_VERSION: "); 28 | Serial.println(FASTMAP_LIB_VERSION); 29 | Serial.println(); 30 | delay(100); 31 | 32 | // Get a non optimizable value; 33 | z = analogRead(A0); 34 | 35 | 36 | // REFERENCE 37 | start = micros(); 38 | for (int i = 0; i < 10000; i++) 39 | { 40 | x = map(z, 0, 1023, yy, zz); 41 | } 42 | stop = micros(); 43 | reference = stop - start; 44 | Serial.print("MAP:\t"); 45 | Serial.println(reference); 46 | Serial.print(z); 47 | Serial.print(" -> "); 48 | Serial.println(x); 49 | Serial.println(); 50 | delay(100); 51 | 52 | 53 | 54 | // FASTMAP 55 | mapper.init(0, 1023, yy, zz); 56 | start = micros(); 57 | for (int i = 0; i < 10000; i++) 58 | { 59 | x = mapper.map(z); 60 | } 61 | stop = micros(); 62 | Serial.print("FASTMAP:\t"); 63 | Serial.println(stop - start); 64 | Serial.print(z); 65 | Serial.print(" -> "); 66 | Serial.println(x); 67 | Serial.print("Performance factor: "); 68 | Serial.println((float)reference / (stop - start)); 69 | Serial.println(); 70 | delay(100); 71 | 72 | 73 | 74 | // FASTMAPDOUBLE 75 | mapperD.init(0, 1023, yy, zz); 76 | start = micros(); 77 | for (int i = 0; i < 10000; i++) 78 | { 79 | x = mapperD.map(z); 80 | } 81 | stop = micros(); 82 | Serial.print("FASTMAPD:\t"); 83 | Serial.println(stop - start); 84 | Serial.print(z); 85 | Serial.print(" -> "); 86 | Serial.println(x); 87 | Serial.print("Performance factor: "); 88 | Serial.println((float)reference / (stop - start)); 89 | Serial.println(); 90 | 91 | } 92 | 93 | 94 | void loop() 95 | { 96 | } 97 | 98 | 99 | // -- END OF FILE -- 100 | -------------------------------------------------------------------------------- /examples/fastMap_performance_test/performance_0.4.1_ESP32.txt: -------------------------------------------------------------------------------- 1 | fastMap_performance_test.ino 2 | FASTMAP_LIB_VERSION: 0.4.1 3 | 4 | MAP: 1814 5 | 0 -> 20000.00 6 | 7 | FASTMAP: 627 8 | 0 -> 20000.00 9 | Performance factor: 2.89 10 | 11 | FASTMAPD: 6924 12 | 0 -> 20000.00 13 | Performance factor: 0.26 14 | -------------------------------------------------------------------------------- /examples/fastMap_performance_test/performance_0.4.1_UNO.txt: -------------------------------------------------------------------------------- 1 | 2 | fastMap_performance_test.ino 3 | FASTMAP_LIB_VERSION: 0.4.1 4 | 5 | MAP: 496072 6 | 1023 -> 3000.00 7 | 8 | FASTMAP: 211888 9 | 1023 -> 3000.00 10 | Performance factor: 2.34 11 | 12 | FASTMAPD: 211888 13 | 1023 -> 3000.00 14 | Performance factor: 2.34 15 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | # Syntax Colouring Map For FastMap 2 | 3 | 4 | # Data types (KEYWORD1) 5 | FastMap KEYWORD1 6 | FastMapDouble KEYWORD1 7 | 8 | 9 | # Methods and Functions (KEYWORD2) 10 | init KEYWORD2 11 | map KEYWORD2 12 | back KEYWORD2 13 | 14 | constrainedMap KEYWORD2 15 | lowerConstrainedMap KEYWORD2 16 | upperConstrainedMap KEYWORD2 17 | 18 | 19 | # Constants (LITERAL1) 20 | FASTMAP_LIB_VERSION LITERAL1 21 | 22 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "FastMap", 3 | "keywords": "Fast,map,lookup,table", 4 | "description": "Library with fast map function for Arduino.", 5 | "authors": 6 | [ 7 | { 8 | "name": "Rob Tillaart", 9 | "email": "Rob.Tillaart@gmail.com", 10 | "maintainer": true 11 | } 12 | ], 13 | "repository": 14 | { 15 | "type": "git", 16 | "url": "https://github.com/RobTillaart/FastMap" 17 | }, 18 | "version": "0.4.2", 19 | "license": "MIT", 20 | "frameworks": "*", 21 | "platforms": "*", 22 | "headers": "FastMap.h" 23 | } 24 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=FastMap 2 | version=0.4.2 3 | author=Rob Tillaart 4 | maintainer=Rob Tillaart 5 | sentence=Library with fast map function for Arduino. 6 | paragraph= 7 | category=Data Processing 8 | url=https://github.com/RobTillaart/FastMap 9 | architectures=* 10 | includes=FastMap.h 11 | depends= -------------------------------------------------------------------------------- /test/unit_test_001.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: unit_test_001.cpp 3 | // AUTHOR: Rob Tillaart 4 | // DATE: 2020-12-21 5 | // PURPOSE: unit tests for the FastMap 6 | // https://github.com/RobTillaart/FastMap 7 | // https://github.com/Arduino-CI/arduino_ci/blob/master/REFERENCE.md 8 | // 9 | 10 | // supported assertions 11 | // https://github.com/Arduino-CI/arduino_ci/blob/master/cpp/unittest/Assertion.h#L33-L42 12 | // ---------------------------- 13 | // assertEqual(expected, actual) 14 | // assertNotEqual(expected, actual) 15 | // assertLess(expected, actual) 16 | // assertMore(expected, actual) 17 | // assertLessOrEqual(expected, actual) 18 | // assertMoreOrEqual(expected, actual) 19 | // assertTrue(actual) 20 | // assertFalse(actual) 21 | // assertNull(actual) 22 | // assertNotNull(actual) 23 | 24 | #include 25 | 26 | 27 | #include "Arduino.h" 28 | #include "FastMap.h" 29 | 30 | 31 | unittest_setup() 32 | { 33 | fprintf(stderr, "FASTMAP_LIB_VERSION: %s\n", (char *) FASTMAP_LIB_VERSION); 34 | } 35 | 36 | 37 | unittest_teardown() 38 | { 39 | } 40 | 41 | 42 | unittest(test_init) 43 | { 44 | FastMap fm; 45 | FastMapDouble fmd; 46 | 47 | assertTrue(fm.init(-2, 12, 17, 42)); 48 | assertFalse(fm.init(12, 12, 17, 42)); 49 | assertFalse(fm.init(-2, 12, 17, 17)); 50 | assertFalse(fm.init(12, 12, 17, 17)); 51 | 52 | assertTrue(fmd.init(-2, 12, 17, 42)); 53 | assertFalse(fmd.init(12, 12, 17, 42)); 54 | assertFalse(fmd.init(-2, 12, 17, 17)); 55 | assertFalse(fmd.init(12, 12, 17, 17)); 56 | } 57 | 58 | 59 | unittest(test_map) 60 | { 61 | FastMap fm; 62 | 63 | fm.init(-2, 12, 17, 42); 64 | 65 | assertEqualFloat(11.6429, fm.map(-5), 0.001); 66 | assertEqualFloat(17, fm.map(-2), 0.001); 67 | assertEqualFloat(20.5714, fm.map(0), 0.001); 68 | assertEqualFloat(26.1814, fm.map(PI), 0.001); 69 | assertEqualFloat(42, fm.map(12), 0.001); 70 | assertEqualFloat(47.3571, fm.map(15), 0.001); 71 | } 72 | 73 | 74 | unittest(test_back) 75 | { 76 | FastMap fm; 77 | 78 | fm.init(-2, 12, 17, 42); 79 | 80 | assertEqualFloat(-14.32, fm.back(-5), 0.001); 81 | assertEqualFloat(-11.52, fm.back(0), 0.001); 82 | assertEqualFloat(-5.92, fm.back(10), 0.001); 83 | assertEqualFloat(-2, fm.back(17), 0.001); 84 | assertEqualFloat(2.48, fm.back(25), 0.001); 85 | assertEqualFloat(12, fm.back(42), 0.001); 86 | assertEqualFloat(24.88, fm.back(65), 0.001); 87 | } 88 | 89 | 90 | unittest(test_constrainedMap) 91 | { 92 | FastMap fm; 93 | 94 | fm.init(-2, 12, 17, 42); 95 | 96 | assertEqualFloat(17, fm.constrainedMap(-5), 0.001); 97 | assertEqualFloat(17, fm.constrainedMap(-2), 0.001); 98 | assertEqualFloat(20.5714, fm.constrainedMap(0), 0.001); 99 | assertEqualFloat(26.1814, fm.constrainedMap(PI), 0.001); 100 | assertEqualFloat(42, fm.constrainedMap(12), 0.001); 101 | assertEqualFloat(42, fm.constrainedMap(15), 0.001); 102 | } 103 | 104 | 105 | unittest(test_lowerConstrainedMap) 106 | { 107 | FastMap fm; 108 | 109 | fm.init(-2, 12, 17, 42); 110 | 111 | assertEqualFloat(17, fm.lowerConstrainedMap(-5), 0.001); 112 | assertEqualFloat(17, fm.lowerConstrainedMap(-2), 0.001); 113 | assertEqualFloat(20.5714, fm.lowerConstrainedMap(0), 0.001); 114 | assertEqualFloat(26.1814, fm.lowerConstrainedMap(PI), 0.001); 115 | assertEqualFloat(42, fm.lowerConstrainedMap(12), 0.001); 116 | assertEqualFloat(47.3571, fm.lowerConstrainedMap(15), 0.001); 117 | } 118 | 119 | 120 | unittest(test_upperConstrainedMap) 121 | { 122 | FastMap fm; 123 | 124 | fm.init(-2, 12, 17, 42); 125 | 126 | assertEqualFloat(11.6429, fm.upperConstrainedMap(-5), 0.001); 127 | assertEqualFloat(17, fm.upperConstrainedMap(-2), 0.001); 128 | assertEqualFloat(20.5714, fm.upperConstrainedMap(0), 0.001); 129 | assertEqualFloat(26.1814, fm.upperConstrainedMap(PI), 0.001); 130 | assertEqualFloat(42, fm.upperConstrainedMap(12), 0.001); 131 | assertEqualFloat(42, fm.upperConstrainedMap(15), 0.001); 132 | } 133 | 134 | 135 | unittest(test_map_double) 136 | { 137 | fprintf(stderr, "FAST MAP DOUBLE\n"); 138 | 139 | FastMapDouble fm; 140 | 141 | fm.init(-2, 12, 17, 42); 142 | 143 | assertEqualFloat(11.6429, fm.map(-5), 0.001); 144 | assertEqualFloat(17, fm.map(-2), 0.001); 145 | assertEqualFloat(20.5714, fm.map(0), 0.001); 146 | assertEqualFloat(26.1814, fm.map(PI), 0.001); 147 | assertEqualFloat(42, fm.map(12), 0.001); 148 | assertEqualFloat(47.3571, fm.map(15), 0.001); 149 | } 150 | 151 | 152 | unittest_main() 153 | 154 | // -------- 155 | --------------------------------------------------------------------------------