Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 21 additions & 14 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,22 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).


## [0.3.3] - 2025-03-23
- fix #28, prevent promotion of constants to double. Kudos to Harrison3000
- replace M_PI by a const float _PI_ to prevent promotion.
- update examples
- update readme.md (minor)
- minor edits


## [0.3.3] - 2023-11-02
- update readme.md
- update keywords.txt
- update changelog.md


## [0.3.2] - 2022-12-20
- fix changelog
- fix #25 change reference parameters to pointer
- fix #25 change reference parameters to pointer
- isincos(float f, float \*si, float \*co)
- isincos256(uint32_t v, int \*si, int \*co);
- fix examples
Expand All @@ -35,9 +42,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
----

## [0.2.1] - 2022-12-05
- add atanFast(x) => faster and less accurate than atan().
- add atanFast(x) => faster and less accurate than atan().
Input range (-1..1) is fastest.
- add atan2Fast(y, x) => faster and less accurate.
- add atan2Fast(y, x) => faster and less accurate.
calls atanFast() + offset.
- add example to measure performance atanFast
- update readme.md
Expand All @@ -60,11 +67,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- no functional changes

## [0.1.10] - 2022-04-15
- fix #12
- fix #12
- split .h in .h and .cpp Needed in case of more complex projects.

## [0.1.9] - 2021-12-18
- update Arduino-CI, badges,
## [0.1.9] - 2021-12-18
- update Arduino-CI, badges,
- update library.json
- minor edits

Expand All @@ -83,14 +90,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- new table
- added iasin() and iacos()

In (0.1.4) an error was found in the optimize algorithm, so for 0.1.5
it was ran again and accuracy improved for **isin()** and **icos()**.
However **itan()** lost a (smaller) bit.
In (0.1.4) an error was found in the optimize algorithm, so for 0.1.5
it was ran again and accuracy improved for **isin()** and **icos()**.
However **itan()** lost a (smaller) bit.
The gain outweighs the loss and so new table is kept.

Performance has not changed.

An initial version of a reverse lookup for **iasin(val)** and **iacos(val)**
An initial version of a reverse lookup for **iasin(val)** and **iacos(val)**
is added, as it uses the same **isintable16\[\]** interpolation table.

There is no **atan()** or **atan2()** replacement.
Expand All @@ -101,8 +108,8 @@ There is no **atan()** or **atan2()** replacement.
- cleanup
- examples

The library (0.1.4) provides an **itan()** which improved accuracy
upon the (0.1.3) version and performance for the ESP32.
The library (0.1.4) provides an **itan()** which improved accuracy
upon the (0.1.3) version and performance for the ESP32.
Performance on AVR (UNO) is still an issue, accuracy is OK.


Expand All @@ -126,7 +133,7 @@ _eons passed_
- added interpolation

## [0.1.01] - 2011-08-18
- improved tables a bit
- improved tables a bit
- changed param to float

## [0.1.00] - 2011-08-18
Expand Down
46 changes: 25 additions & 21 deletions FastTrig.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//
// FILE: FastTrig.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.3.3
// VERSION: 0.3.4
// PURPOSE: Arduino library for a faster approximation of sin() and cos()
// DATE: 2011-08-18
// URL: https://github.com/RobTillaart/FastTrig
Expand All @@ -11,6 +11,10 @@
#include "FastTrig.h"


const float _PI_ = 3.14159265;
const float _PI_DIV_2_ = _PI_ / 2;


// 91 x 2 bytes ==> 182 bytes
// use 65535.0 as divider
uint16_t sinTable16[] = {
Expand Down Expand Up @@ -45,7 +49,7 @@ uint16_t sinTable16[] = {
*/


// use 255.0 as divider
// use 255.0 as divider
uint8_t sinTable8[] = {
0, 4, 9, 13, 18, 22, 27, 31, 35, 40, 44,
49, 53, 57, 62, 66, 70, 75, 79, 83, 87,
Expand All @@ -62,8 +66,8 @@ uint8_t sinTable8[] = {

///////////////////////////////////////////////////////
//
// GONIO INT EXPERIMENTAL
// works with only whole degrees.
// GONIO INT EXPERIMENTAL
// works with only whole degrees.
//
int isin256(uint32_t v)
{
Expand Down Expand Up @@ -174,15 +178,15 @@ float isin(float f)
}
}

// float value improves ~4% on avg error for ~60 bytes.
// float value improves ~4% on average error for ~60 bytes.
uint16_t value = sinTable16[y];

// interpolate if needed
if (remain > 0)
{
value = value + ((sinTable16[y + 1] - value) / 8 * remain) / 32; // == * remain / 256
}
float g = value * 0.0000152590219; // = / 65535.0
float g = value * 0.0000152590219f; // = / 65535.0
if (negative) return -g;
return g;
}
Expand Down Expand Up @@ -235,15 +239,15 @@ void isincos(float f, float *si, float *co)
cneg = !cneg;
}

// float value improves ~4% on avg error for ~60 bytes.
// float value improves ~4% on average error for ~60 bytes.
// SIN
uint16_t value = sinTable16[y];
// interpolate if needed
if (remain > 0)
{
value = value + ((sinTable16[y + 1] - value) / 8 * remain) / 32; // == * remain / 256
}
*si = value * 0.0000152590219; // = / 65535.0
*si = value * 0.0000152590219f; // = / 65535.0
if (sneg) *si = - *si;

// COS
Expand All @@ -254,7 +258,7 @@ void isincos(float f, float *si, float *co)
remain = 256 - remain;
value = value + ((sinTable16[90-y] - value) / 8 * remain) / 32; // == * remain / 256
}
*co = value * 0.0000152590219; // = / 65535.0
*co = value * 0.0000152590219f; // = / 65535.0
if (cneg) *co = - *co;
}

Expand Down Expand Up @@ -382,19 +386,19 @@ float iatan(float f)
float atanFast(float x)
{
// remove two test will limit the input range but makes it even faster.
if ( x > 1) return ( M_PI / 2) - atanHelper(1.0 / x);
if ( x < -1) return (-M_PI / 2) - atanHelper(1.0 / x);
if ( x > 1) return (_PI_DIV_2_) - atanHelper(1.0 / x);
if ( x < -1) return (-_PI_DIV_2_) - atanHelper(1.0 / x);
return atanHelper(x);
}


inline float atanHelper(float x)
{
float x2 = x * x;
return (((0.079331 * x2) - 0.288679) * x2 + 0.995354) * x;
return (((0.079331f * x2) - 0.288679f) * x2 + 0.995354f) * x;

// an even more accurate alternative, less fast
// return ((((-0.0389929 * x2) + 0.1462766) * x2 - 0.3211819) * x2 + 0.9992150) * x;
// return ((((-0.0389929f * x2) + 0.1462766f) * x2 - 0.3211819f) * x2 + 0.9992150f) * x;
}


Expand All @@ -407,29 +411,29 @@ float atan2Fast(float y, float x)
{
if (y >= 0)
{
if (fabs(y) >= fabs(x)) return M_PI / 2 - atanFast(x / y);
if (fabs(y) >= fabs(x)) return _PI_DIV_2_ - atanFast(x / y);
return atanFast(y / x);
}
if (fabs(y) >= fabs(x)) return -M_PI / 2 - atanFast(x / y);
if (fabs(y) >= fabs(x)) return -_PI_DIV_2_ - atanFast(x / y);
return atanFast(y / x);
}
else
{
if (y >= 0)
{
if (fabs(y) >= fabs(x)) return M_PI / 2 - atanFast(x / y);
return M_PI + atanFast(y / x);
if (fabs(y) >= fabs(x)) return _PI_DIV_2_ - atanFast(x / y);
return _PI_ + atanFast(y / x);
}
if (fabs(y) >= fabs(x)) return -M_PI / 2 - atanFast(x / y);
return -M_PI + atanFast(y / x);
if (fabs(y) >= fabs(x)) return -_PI_DIV_2_ - atanFast(x / y);
return -_PI_ + atanFast(y / x);
}
}


///////////////////////////////////////////////////////
//
// HYPOT
// related but not strict gonio.
// related but not strict goniometry.
//
// hypotFast() formula for faster hypot() at the price of accuracy
// experimental!
Expand All @@ -442,7 +446,7 @@ float hypotFast(float x, float y)
a = fabs(y);
b = fabs(x);
}
float z = 0.917981 * (b + a / 2);
float z = 0.917981f * (b + a / 2);
if (z > b) return z;
return b;
}
Expand Down
7 changes: 4 additions & 3 deletions FastTrig.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// FILE: FastTrig.h
// AUTHOR: Rob Tillaart
// VERSION: 0.3.3
// VERSION: 0.3.4
// PURPOSE: Arduino library for a faster approximation of sin() and cos()
// DATE: 2011-08-18
// URL: https://github.com/RobTillaart/FastTrig
Expand All @@ -18,7 +18,8 @@
#endif


#define FAST_TRIG_LIB_VERSION (F("0.3.3"))
#define FAST_TRIG_LIB_VERSION (F("0.3.4"))


#ifdef __cplusplus
extern "C"
Expand Down Expand Up @@ -74,7 +75,7 @@ float atan2Fast(float y, float x);
///////////////////////////////////////////////////////
//
// HYPOT
// related but not strict gonio.
// related but not strict goniometry.
//
// hypotFast() formula for faster hypot() at the price of accuracy
// experimental!
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2011-2024 Rob Tillaart
Copyright (c) 2011-2025 Rob Tillaart

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
19 changes: 13 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,20 @@ Of course this introduces an error but the error is small and performance is sti
quite fast (which was the goal).


### Related

- https://github.com/RobTillaart/fast_math
- https://github.com/RobTillaart?tab=repositories&q=math


## Interface

```cpp
#include "FastTrig.h"
```


#### Lookup tables
### Lookup tables

The lookup tables are optimized (sketch provided) to minimize the error when using the interpolation,
this implies that the points in the table might not be optimal when you use only whole degrees.
Expand All @@ -71,10 +77,10 @@ however it is great to use in a LEDstrip or motor movements when less accuracy i

Although the tables can be written to, it is advised not to do so.

*OK, the optimize example does a write to improve the table to minimize errors*
_OK, the optimize example does a write to improve the table to minimize errors_


#### atan, atan2
### atan, atan2

Since version 0.2.1 two functions are added:
- **float atanFast(float f)** input range -1 .. 1 is faster.
Expand All @@ -89,7 +95,7 @@ Use **fastTrig_atan_performance.ino** to check the gain on your board.
Price is that the values are less accurate, but the difference is < 0.001.


#### isin256, icos256, isincos256
### isin256, icos256, isincos256

Version 0.3.0 added these experimental functions:

Expand All @@ -102,7 +108,7 @@ returns both the sin(v)\*256 and the cos(v)\*256 of the same angle.
Faster than both individual calls together.


#### isincos
### isincos

Version 0.3.0 added this experimental function:

Expand All @@ -113,7 +119,7 @@ There is a minor difference between the value of the **float co** compared to **
This need some investigation ( truncating ?)


#### hypotFast
### hypotFast

Strictly **hypot()** is no gonio function but it is often used
for calculating length in polar coordinates.
Expand Down Expand Up @@ -367,6 +373,7 @@ See examples

#### Should

- clean example headers (consistency)
- write more tests to verify values.
- test performance on more platforms.
- investigate the difference between **isincos()** and **icos()**.
Expand Down
Loading