Skip to content

Commit e96b24b

Browse files
authored
fix #12 split .h in .h and .cpp (#13)
* fix #12 split .h in .h and .cpp
1 parent e2062b2 commit e96b24b

File tree

6 files changed

+276
-223
lines changed

6 files changed

+276
-223
lines changed

FastTrig.cpp

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
//
2+
// FILE: FastTrig.cpp
3+
// AUTHOR: Rob Tillaart
4+
// VERSION: 0.1.10
5+
// PURPOSE: Arduino library for a faster approximation of sin() and cos()
6+
// DATE: 2011-08-18
7+
// URL: https://github.com/RobTillaart/FastTrig
8+
// https://forum.arduino.cc/index.php?topic=69723.0
9+
//
10+
// HISTORY:
11+
// 0.1.00 2011-08-18 initial version
12+
// 0.1.01 2011-08-18 improved tables a bit + changed param to float
13+
// 0.1.02 2011-08-20 added interpolation
14+
// eons passed
15+
// 0.1.1 2020-08-30 refactor, create a library out of it.
16+
// itan() approximation is bad.
17+
// 0.1.2 2020-09-06 optimize 16 bit table with example sketch
18+
// 0.1.3 2020-09-07 initial release.
19+
// 0.1.4 2020-09-08 rewrite itan() + cleanup + examples
20+
// 0.1.5 2020-09-11 fixed optimize, new table, added iasin() and iacos()
21+
// 0.1.6 2020-12-23 Arduino-CI + unit tests
22+
// 0.1.7 2021-04-23 fix for PlatformIO
23+
// 0.1.8 2021-08-10 made % 180 conditional in itan() => performance gain
24+
// added icot() cotangent.
25+
// 0.1.9 2021-12-18 update Arduino-CI, badges,
26+
// update library.json, minor edits
27+
// 0.1.10 2022-04-15 fix #12 split .h in .h and .cpp
28+
29+
30+
#include "FastTrig.h"
31+
32+
33+
34+
// 91 x 2 bytes ==> 182 bytes
35+
// use 65535.0 as divider
36+
uint16_t isinTable16[] = {
37+
0,
38+
1145, 2289, 3435, 4572, 5716, 6853, 7989, 9125, 10255, 11385,
39+
12508, 13631, 14745, 15859, 16963, 18067, 19165, 20253, 21342, 22417,
40+
23489, 24553, 25610, 26659, 27703, 28731, 29755, 30773, 31777, 32772,
41+
33756, 34734, 35697, 36649, 37594, 38523, 39445, 40350, 41247, 42131,
42+
42998, 43856, 44701, 45528, 46344, 47147, 47931, 48708, 49461, 50205,
43+
50933, 51646, 52342, 53022, 53686, 54334, 54969, 55579, 56180, 56760,
44+
57322, 57866, 58394, 58908, 59399, 59871, 60327, 60768, 61184, 61584,
45+
61969, 62330, 62677, 63000, 63304, 63593, 63858, 64108, 64334, 64545,
46+
64731, 64903, 65049, 65177, 65289, 65377, 65449, 65501, 65527, 65535,
47+
65535
48+
};
49+
50+
51+
/* 0.1.4 table
52+
uint16_t isinTable16[] = {
53+
0,
54+
1145, 2289, 3435, 4571, 5715, 6852, 7988, 9125, 10254, 11385,
55+
12508, 13630, 14745, 15859, 16963, 18067, 19165, 20253, 21342, 22416,
56+
23488, 24553, 25610, 26659, 27699, 28730, 29754, 30773, 31777, 32771,
57+
33755, 34734, 35697, 36649, 37594, 38523, 39445, 40350, 41247, 42127,
58+
42998, 43856, 44697, 45527, 46344, 47146, 47931, 48708, 49461, 50205,
59+
50933, 51645, 52341, 53022, 53686, 54333, 54969, 55578, 56180, 56759,
60+
57322, 57866, 58394, 58908, 59399, 59871, 60327, 60767, 61184, 61584,
61+
61969, 62330, 62677, 63000, 63304, 63592, 63857, 64108, 64333, 64544,
62+
64731, 64902, 65049, 65177, 65289, 65376, 65449, 65501, 65527, 65535,
63+
65535
64+
};
65+
*/
66+
67+
68+
// use 255.0 as divider
69+
uint8_t isinTable8[] = {
70+
0, 4, 9, 13, 18, 22, 27, 31, 35, 40, 44,
71+
49, 53, 57, 62, 66, 70, 75, 79, 83, 87,
72+
91, 96, 100, 104, 108, 112, 116, 120, 124, 128,
73+
131, 135, 139, 143, 146, 150, 153, 157, 160, 164,
74+
167, 171, 174, 177, 180, 183, 186, 190, 192, 195,
75+
198, 201, 204, 206, 209, 211, 214, 216, 219, 221,
76+
223, 225, 227, 229, 231, 233, 235, 236, 238, 240,
77+
241, 243, 244, 245, 246, 247, 248, 249, 250, 251,
78+
252, 253, 253, 254, 254, 254, 255, 255, 255, 255,
79+
255
80+
};
81+
82+
83+
///////////////////////////////////////////////////////
84+
//
85+
// GONIO LOOKUP
86+
//
87+
float isin(float f)
88+
{
89+
boolean pos = true; // positive
90+
if (f < 0)
91+
{
92+
f = -f;
93+
pos = !pos;
94+
}
95+
96+
long x = f;
97+
uint8_t r = (f - x) * 256;
98+
99+
if (x >= 360) x %= 360;
100+
101+
int y = x; // 16 bit math is faster than 32 bit
102+
103+
if (y >= 180)
104+
{
105+
y -= 180;
106+
pos = !pos;
107+
}
108+
109+
if (y >= 90)
110+
{
111+
y = 180 - y;
112+
if (r != 0)
113+
{
114+
r = 255 - r;
115+
y--;
116+
}
117+
}
118+
119+
// float v improves ~4% on avg error for ~60 bytes.
120+
uint16_t v = isinTable16[y];
121+
122+
// interpolate if needed
123+
if (r > 0)
124+
{
125+
v = v + ((isinTable16[y + 1] - v) / 8 * r) /32; // == * r / 256
126+
}
127+
float g = v * 0.0000152590219; // = /65535.0
128+
if (pos) return g;
129+
return -g;
130+
}
131+
132+
133+
float icos(float x)
134+
{
135+
// prevent modulo math if x in 0..360
136+
return isin(x - 270.0); // better than x + 90;
137+
}
138+
139+
140+
float itan(float f)
141+
{
142+
// reference
143+
// return isin(f)/icos(f);
144+
145+
// idea is to divide two (interpolated) values from the table
146+
// so no divide by 65535
147+
148+
// FOLDING
149+
bool mir = false;
150+
bool neg = (f < 0);
151+
if (neg) f = -f;
152+
153+
long x = f;
154+
float rem = f - x;
155+
if (x >= 180) x %= 180;
156+
float v = rem + x; // normalised value 0..179.9999
157+
if (v > 90)
158+
{
159+
v = 180 - v;
160+
neg = !neg;
161+
mir = true;
162+
}
163+
uint8_t d = v;
164+
if (d == 90) return 0;
165+
166+
// COS FIRST
167+
uint8_t p = 90 - d;
168+
float co = isinTable16[p];
169+
if (rem != 0)
170+
{
171+
float delta = (isinTable16[p] - isinTable16[p - 1]);
172+
if (mir) co = isinTable16[p - 1] + rem * delta;
173+
else co = isinTable16[p] - rem * delta;
174+
}
175+
else if (co == 0) return 0;
176+
177+
float si = isinTable16[d];
178+
if (rem != 0) si += rem * (isinTable16[d + 1] - isinTable16[d]);
179+
180+
float ta = si/co;
181+
if (neg) return -ta;
182+
return ta;
183+
}
184+
185+
186+
// some problem at 0 but at least we have a icot(x) cotangent.
187+
float icot(float f)
188+
{
189+
float t = itan(f);
190+
if (t == 0) return NAN;
191+
return 1.0 / t;
192+
}
193+
194+
195+
// missing function...
196+
// float cot(float f)
197+
// {
198+
// return 1.0/tan(f);
199+
// }
200+
201+
202+
///////////////////////////////////////////////////////
203+
//
204+
// INVERSE GONIO LOOKUP
205+
//
206+
float iasin(float f)
207+
{
208+
bool neg = (f < 0);
209+
if (neg)
210+
{
211+
f = -f;
212+
neg = true;
213+
}
214+
uint16_t val = round(f * 65535);
215+
uint8_t lo = 0;
216+
uint8_t hi = 90;
217+
218+
while (hi - lo > 1)
219+
{
220+
uint8_t mi = (lo + hi) / 2;
221+
if (isinTable16[mi] == val)
222+
{
223+
if (neg) return -mi;
224+
return mi;
225+
}
226+
if (isinTable16[mi] < val) lo = mi;
227+
else hi = mi;
228+
}
229+
float delta = val - isinTable16[lo];
230+
uint16_t range = isinTable16[hi] - isinTable16[lo];
231+
delta /= range;
232+
if (neg) return -(lo + delta);
233+
return (lo + delta);
234+
}
235+
236+
237+
float iacos(float f)
238+
{
239+
return 90 - iasin(f);
240+
}
241+
242+
243+
// PLACEHOLDER
244+
float iatan(float f)
245+
{
246+
return 0 * f;
247+
}
248+
249+
250+
// -- END OF FILE --

0 commit comments

Comments
 (0)