{"id":13893778,"url":"https://github.com/RobTillaart/FastTrig","last_synced_at":"2025-07-17T08:30:46.537Z","repository":{"id":42048638,"uuid":"293471882","full_name":"RobTillaart/FastTrig","owner":"RobTillaart","description":"Arduino library with interpolated lookup for sin() and cos()","archived":false,"fork":false,"pushed_at":"2025-03-24T15:47:00.000Z","size":84,"stargazers_count":26,"open_issues_count":0,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-02T22:04:54.276Z","etag":null,"topics":["arduino","sinus","trigonometry"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RobTillaart.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"RobTillaart","custom":"https://www.paypal.me/robtillaart"}},"created_at":"2020-09-07T08:46:55.000Z","updated_at":"2025-03-25T10:13:47.000Z","dependencies_parsed_at":"2024-04-19T04:16:04.310Z","dependency_job_id":null,"html_url":"https://github.com/RobTillaart/FastTrig","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/RobTillaart/FastTrig","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FFastTrig","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FFastTrig/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FFastTrig/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FFastTrig/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RobTillaart","download_url":"https://codeload.github.com/RobTillaart/FastTrig/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FFastTrig/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265585272,"owners_count":23792712,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arduino","sinus","trigonometry"],"created_at":"2024-08-06T18:01:16.992Z","updated_at":"2025-07-17T08:30:46.531Z","avatar_url":"https://github.com/RobTillaart.png","language":"C++","funding_links":["https://github.com/sponsors/RobTillaart","https://www.paypal.me/robtillaart"],"categories":["C++"],"sub_categories":[],"readme":"\n[![Arduino CI](https://github.com/RobTillaart/FastTrig/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)\n[![Arduino-lint](https://github.com/RobTillaart/FastTrig/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/FastTrig/actions/workflows/arduino-lint.yml)\n[![JSON check](https://github.com/RobTillaart/FastTrig/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/FastTrig/actions/workflows/jsoncheck.yml)\n[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/FastTrig.svg)](https://github.com/RobTillaart/FastTrig/issues)\n\n[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/FastTrig/blob/master/LICENSE)\n[![GitHub release](https://img.shields.io/github/release/RobTillaart/FastTrig.svg?maxAge=3600)](https://github.com/RobTillaart/FastTrig/releases)\n[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/FastTrig.svg)](https://registry.platformio.org/libraries/robtillaart/FastTrig)\n\n\n# FastTrig\n\nArduino library with interpolated lookup for sin() and cos(). Trades speed for accuracy.\n\n\n## Description\n\n**Warning: The library trades speed for accuracy so use at own risk**\n\nSo please, verify the performance and accuracy to see if they meet\nthe requirements of your project.\n\n----\n\nThe library provides one lookup table that is used for\n**isin(degrees)** and **icos(degrees)** and **itan(degrees)**. \nThis lookup table is optimized for interpolation so the values for whole degrees are not optimal. \nFurthermore the **itan()** on AVR has almost no performance gain over the regular **tan()** so on AVR one is advised to use **tan()**. \nOn ESP32 the **itan(degrees)** does have a serious performance gain so use it if you need speed.\n\nThese functions are to be used as replacements for **sin(radians)**, **cos(radians)** and **tan(radians)**. \nImportant to know is that they are NOT direct replaceable as the parameter differs a factor (PI/180.0) or its inverse.\n\nSimilar to ```cos(x) == sin(x + PI)``` it is also true that ```icos(x) == isin(x + 90)```, \nso **icos()** can use the very same lookup table at the cost of a single addition. \nIn fact it uses ```icos(x) == isin(x - 270)``` as that performs better, due to the folding.\n\nThe **i** in the names stands for **int** and **interpolated** as the core is \nusing integer math and lookup table of 91 uint16_t = 182 bytes. \nBy folding and mirroring the whole 360 degrees and beyond can be handled. \nWhen **isin(float x)** is called and ```x == int(x)``` then the library will not interpolate.\nThis will improve performance even more.\nWhen x is not a whole number the library will linear interpolate \nbetween **isin(int(x))** and **isin(int(x+1))**. \nOf course this introduces an error but the error is small and performance is still \nquite fast (which was the goal).\n\n\n### Related\n\n- https://github.com/RobTillaart/fast_math\n- https://github.com/RobTillaart?tab=repositories\u0026q=math\n\n\n## Interface\n\n```cpp\n#include \"FastTrig.h\"\n```\n\n\n### Lookup tables\n\nThe lookup tables are optimized (sketch provided) to minimize the error when using the interpolation, \nthis implies that the points in the table might not be optimal when you use only whole degrees. \nA sketch that generates lookup tables is in the examples folder. \nThis generator sketch can also generate tables with different resolution e.g. 24, 14, 12 or even 6, 5 or 4 bit lookup tables. \nSo depending on the application these tables can be ideal, but verify they meet your requirements.\n\nThe lookup tables used by **isin()** can be used directly in your program, the names are:\n- **sinTable16\\[\\]** index 0..90, values need to be (float) divided by 65535.0\n- **sinTable8\\[\\]** index 0..90, values need to be (float) divided by 255.0\n\nThe **sinTable8** is not really for doing accurate math, \nhowever it is great to use in a LEDstrip or motor movements when less accuracy is needed.\n\nAlthough the tables can be written to, it is advised not to do so.\n\n_OK, the optimize example does a write to improve the table to minimize errors_\n\n\n### atan, atan2\n\nSince version 0.2.1 two functions are added:\n- **float atanFast(float f)** input range -1 .. 1 is faster.\nReturns -PI/2 .. PI/2\n- **float atan2Fast(float y, float x)** all input possible except (0, 0).\nThis (0,0) singularity returns NAN.\nReturns -PI .. PI for all other values.\n\nThese functions do not use a lookup table but are faster than the default\natan() and atan2() functions. \nUse **fastTrig_atan_performance.ino** to check the gain on your board.\nPrice is that the values are less accurate, but the difference is \u003c 0.001.\n\n\n### isin256, icos256, isincos256\n\nVersion 0.3.0 added these experimental functions:\n\n- **int isin256(uint32_t v)** accepts only positive angles in degrees.\nReturns the sin(v)\\*256 to keep all math integer (shift 8 later to correct value)\n- **int icos256(uint32_t v)** accepts only positive angles in degrees.\nReturns the cos(v)\\*256 to keep all math integer (shift 8 later to correct value)\n- **int isincos256(uint32_t v, int \\*si, int \\*co)** accepts only positive angles in degrees.\nreturns both the sin(v)\\*256 and the cos(v)\\*256 of the same angle.\nFaster than both individual calls together.\n\n\n### isincos\n\nVersion 0.3.0 added this experimental function:\n\n- **float isincos(float f, float \\*si, float \\*co)** accepts any angle in degrees.\nreturns both the sin(v) and the cos(v) of the same angle. \nFaster than both individual calls, see example.\nThere is a minor difference between the value of the **float co** compared to **icos()**.\nThis need some investigation ( truncating ?)\n\n\n### hypotFast\n\nStrictly **hypot()** is no gonio function but it is often used \nfor calculating length in polar coordinates.\n```cpp\nangle = atan2(x,y);\nlength = hypot(x, y);\n```\n\n- **float hypotFast(float x, float y)** faster approximation of the **hypot(x, y)**\nExperimental!\n\n\n## Performance isin icos itan\n\ntime in us - calls 0 - 360 step 1 degree and calls 720 - 1080 (lib version 0.1.5)\n(clock speeds in MHz)\n\n| function | UNO 16 | ESP32 240 | UNO (720-1080) | ESP (720-1080) |\n|:--------:|:------:|:---------:|:--------------:|:--------------:|\n|    sin   | 120.43 |   10.90   |    124.19      |   10.91        |\n|   isin   |  44.24 |    1.09   |     85.00      |    1.11        |\n|    cos   | 120.27 |   10.81   |    123.98      |   10.83        |\n|   icos   |  51.40 |    1.16   |     91.42      |    1.18        |\n|    tan   | 147.59 |   18.07   |    151.39      |   18.07        |\n|   itan   | 126.73 |    1.31   |    129.93      |    1.29        |\n\n*Note: itan() 0.1.3 was ( 131.23, 3.05 ) so it improved quite a bit on ESP32. *\n\nPerformance gain is most evident for the ESP32 processor, and much less on AVR.\nThe effect of the modulo (360 degrees) can be seen explicitly in AVR. \nFurthermore the **itan()** on AVR is not faster when there is also interpolation (not in table) \n\nThe 0.1.4 version of **itan()** is faster for ESP32 than 0.1.3 version but the \nimprovement on AVR is minimal. So this will stay on the TODO list.\n\nFurthermore a lot of gain is lost when the angle is not within 0..360\nand needs to be normalized ( expensive modulo on AVR ). It is worth noting that the\noriginal **sin()** **cos()** and **tan()** only have a small overhead for \nvalues outside the 0..360 range.\n\nPlease, verify the performance and accuracy to see if they meet\nthe requirements of your project.\n\n\n## Accuracy isin icos itan\n\nerrors - based upon example sketch - lib version 0.1.5\n\nESP32 calls 0.0 - 360.0 step 0.1 degree\n\n| function | max abs error | avg abs error | max rel error | avg rel error |\n|:--------:|--------------:|--------------:|--------------:|--------------:|\n|   isin   |   0.00010264  |  0.00002059   |  0.02955145   |  0.00035180   |\n|   icos   |   0.00010264  |  0.00002031   |  0.02955145   |  0.00034868   |\n|   itan   |   0.69696045  |  0.00640957   |  0.00144703   |  0.00010100   |\n\nUNO calls 0.0 - 360.0 step 0.1 degree\n\n| function | max abs error | avg abs error | max rel error | avg rel error |\n|:--------:|--------------:|--------------:|--------------:|--------------:|\n|   isin   |   0.00010270  |  0.00002059   |  0.02955145   |  0.00035171   |\n|   icos   |   0.00010264  |  0.00002032   |  0.02949960   |  0.00034869   |\n|   itan   |   0.72760009  |  0.00641527   |  0.00144703   |  0.00037889   | \n\n*Note: 0.1.3 for AVR was bad:   17.41900634 , 0.02249339 , 0.02953807 for itan() *\n\nStrange that the **itan()** on UNO and ESP32 differs (OK same order of magnitude).\nDifferent implementation of goniometry / float maths?\n\nPlease, verify the performance to see if it meets your requirements.\n\n\n## Performance iasin iacos iatan\n\n(added 0.1.5)\n\ntime in us - calls -1 ..+1 step 0.001 degree\n\n| function | UNO 16 -| ESP32 240 |\n|:--------:|:-------:|:---------:|\n|   asin   |  149.76 |  16.71    |\n|  iasin   |  107.70 |   2.58    |\n|   acos   |  169.50 |  15.44    |\n|  iacos   |  114.65 |   2.67    |\n|   atan   |  155.75 |  11.68    |\n|  iatan   |   NI    |   NI      |\n\n- the interpolated reverse lookup is around 30% faster on UNO an 80+% on ESP32\n- **iatan()** is **Not** Implemented.\n\nPlease, verify the accuracy to see if it meets your requirements.\n\n\n## Accuracy iasin iacos iatan\n\n(added 0.1.5)\n\nESP32 calls -1 ..+1 step 0.001 degree\n\n| function | max abs error | avg abs error | max rel error | avg rel error |\n|:--------:|--------------:|--------------:|--------------:|--------------:|\n|  iasin   |  0.22498322   |  0.00195790   |  0.00456106   |  0.00005727   |\n|  iacos   |  0.22498587   |  0.00195794   |  0.64284271   |  0.00021902   |\n|  iatan   |    NI         |  NI           |  NI           |  NI           |\n\n- largest error at 0.999981 - second largest error 0.052841 at -0.999000\n- **iatan()** is **Not** Implemented\n\n\nUNO calls -1 ..+1 step 0.001 degree\n\n| function | max abs error | avg abs error | max rel error | avg rel error |\n|:--------:|--------------:|--------------:|--------------:|--------------:|\n|  iasin   |  0.22499084   |  0.00195719   |  0.00456125   |  0.00005725   |\n|  iacos   |  0.22498588   |  0.00195740   |  0.64284276   |  0.00021901   |\n|  iatan   |    NI         |  NI           |  NI           |  NI           |\n\n- largest error at 0.999981 - second largest error 0.052841 at -0.999000\n- max relative error is high as it occurred near zero.\n- **iatan()** is **Not** Implemented\n\n\nPlease, verify the accuracy to see if it meets your requirements.\n\n\n## Performance atanFast, atan2Fast\n\nIndicative times in microseconds (first measurements)\n\n|  function  |  atan  |  atanF  |  atan2  |  atan2F  |  factor  |  notes  |\n|:----------:|:------:|:-------:|:-------:|:--------:|:--------:|:--------|\n|  UNO       |  188   |    96   |   196   |   124    |   ~1.6   | range -1 .. 1\n|  UNO       |  220   |   124   |   212   |   128    |   ~1.6   |  \n|  ESP32     |   50   |    15   |    44   |    13    |   ~3.3   |\n\nThe range of the second UNO is beyond the -1..1 range\n\nAdditional measurements are welcome.\n(use performance sketch)\n\nTo be elaborated.\n\n\n## Accuracy atanFast, atan2Fast\n\nThe atan2Fast() uses atanFast() so the accuracy for both is the same.\nThe test sketch indicates a maximum error is smaller than 0.001.\n\nTo be elaborated.\n\n\n## Performance isincos()\n\n**isincos()** calculates sin(f) and cos(f) in one call.\n\nloop 1000 calls in microseconds.\n\n|  function   |  UNO 16  |  ESP32 240  |\n|:------------|:--------:|:-----------:|\n| sin         |  122872  |   10926     |\n| isin        |   70704  |    1086     |\n| cos         |  122636  |   10853     |\n| icos        |   66588  |    1151     |\n| isin + icos |  148368  |    2248     |\n| isincos     |  103788  |    1909     |\n\nNote the isincos() is faster than the original \nsin() or cos() while being pretty accurate. \n\n\n## Accuracy isincos()\n\nAs the basic algorithm is very similar to isin() the accuracy is the same.\n\n\n## Performance hypotFast\n\n**hypotFast()** approximates the hypot(x,y) function with a faster formula.\nPrice is accuracy.\n\nloop 1000 calls in microseconds.\n\n|  function  |  UNO 16  |  ESP32 240  |\n|:-----------|:--------:|:-----------:|\n|  sqrt      |  58.856  |   4.472     |\n|  hypot     |  56.588  |   7.111     |\n|  hypotFast |  33.768  |   1.683     |\n\n\nNote that **sqrt(x^2, y^2)** will overflow faster than **hypot(x,y)** or **hypotFast(x,y)**.\n\n\n## Accuracy hypotFast\n\nFirst measurements indicate that the **maximum error** is \nabout 2.64% so on average about 1.32% (both + and -). \nSee test sketch.\n\nPlease verify accuracy for the ranges used in your project!\n\n\n## Performance isin256 icos256 isincos256\n\n**isin256()**, **icos256()** and **isincos256()** calculates the sin\\*256 etc.\nThese functions all return an integer value.\nThere is no floating point math in there so it performs a bit better.\nAt some moment you must correct this factor of 256 with a division or a shift 8.\n\n\nloop 1000 calls in microseconds. \nBased upon **fastTrig_isincos256.ino**\n\nNote to test and compare, the values were multiplied by 100 and shifted by 8.\n\n|  function         |  UNO 16  |  ESP32 240  |\n|:------------------|:--------:|:-----------:|\n| sin               |  131260  |   11364     |\n| isin              |   79044  |    1119     |\n| isin256           |   28284  |     255     |\n| cos               |  131008  |   11298     |\n| icos              |   74928  |    1190     |\n| icos256           |   31704  |     289     |\n| isin256 + icos256 |   58352  |     478     | \n| isincos256        |   32300  |     339     |\n\nNote the **Ixxx256()** series functions are Fast.\nThe price is accuracy but might still be OK for many projects.\n\n\n## Accuracy isin256 icos256 isincos256\n\nThe **Ixxx256()** only accept whole degrees. \nTherefore the values come directly from the lookup tables. no interpolation.\nFirst measurements indicate that the error is less than 2%.\n\n**To be quantified**\n\n\n## Operation\n\nSee examples\n\n\n## Future\n\n#### Must\n\n- improve documentation\n- verify math (tables etc) again.\n- write test sketches that output the tables for documentation :)\n\n#### Should\n\n- clean example headers (consistency)\n- write more tests to verify values.\n- test performance on more platforms.\n- investigate the difference between **isincos()** and **icos()**.\n- investigate **itan256()**\n  - itan256(0) = 0 itan256(1) = 4 itan256(2) = 9 so there will be big steps... \n  - max abs error should be 0.5 or less, it might have its uses.\n\n#### Could\n\n- How to improve the accuracy of the whole degrees, \n  - now the table is optimized for interpolation.\n- add **sinc(x)**  = **sin(x)/x** function.?\n- **ixxx256()** functions need another lookup table?\n  - separate .h file?\n\n#### Wont\n\n\n## Support\n\nIf you appreciate my libraries, you can support the development and maintenance.\nImprove the quality of the libraries by providing issues and Pull Requests, or\ndonate through PayPal or GitHub sponsors.\n\nThank you,\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRobTillaart%2FFastTrig","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FRobTillaart%2FFastTrig","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRobTillaart%2FFastTrig/lists"}