Skip to content

Instantly share code, notes, and snippets.

@uucidl uucidl/atan_approx.c
Last active Jan 4, 2018

Embed
What would you like to do?
Approximations
// Atan approximation
// https://www.dsprelated.com/showarticle/1052.php#tabs1-comments
#include <math.h>
#include <stdio.h>
double atan_approx(double z)
{
double m = z<0? -1.0:1.0;
z *= m;
double y = 0.141499*z*z*z*z +
-0.343315*z*z*z +
-0.016224*z*z +
1.003839*z +
-0.000158;
return m*y;
}
double atan2_approx(double y, double x)
{
double ay = fabs(y), ax = fabs(x);
int invert = ay > ax;
double z = invert ? ax/ay : ay/ax; // [0,1]
double th = atan_approx(z); // [0,π/4]
if(invert) th = M_PI_2 - th; // [0,π/2]
if(x < 0) th = M_PI - th; // [0,π]
th = copysign(th, y); // [-π,π]
return th;
}
int main(int argc, char **argv)
{
float x0 = -1.0f;
float x1 = x0 + 2.f;
float xinc = (x1 - x0)/50.0f;
double err_max = 0.0;
double lsqerr = 0.0;
int lsqerr_n = 0;
printf("x\tatan\tatan_approx\terr\n");
for (float x = x0; x <= x1; x += xinc) {
double y = atan(x);
double ay = atan_approx(x);
double err = fabs(ay - y);
err_max = err_max<err? err:err_max;
printf("%f\t%f\t%f\t%f\n", x, y, ay, err);
lsqerr += err*err;
++lsqerr_n;
}
printf("LSQERR: %ef\n", lsqerr/lsqerr_n);
printf("MAXERR: %f\n", err_max);
printf("PI_4: %f\n", M_PI/4.0);
return 0;
}
/*
x atan atan_approx err
-1.000000 -0.785398 -0.785641 0.000243
-0.960000 -0.764993 -0.765014 0.000021
-0.920000 -0.743756 -0.743675 0.000080
-0.880000 -0.721655 -0.721553 0.000102
-0.840000 -0.698660 -0.698583 0.000077
-0.800000 -0.674741 -0.674711 0.000030
-0.760000 -0.649870 -0.649889 0.000018
-0.720000 -0.624023 -0.624080 0.000057
-0.680000 -0.597177 -0.597256 0.000079
-0.640000 -0.569313 -0.569395 0.000082
-0.600000 -0.540419 -0.540487 0.000067
-0.560000 -0.510488 -0.510528 0.000040
-0.520000 -0.479519 -0.479524 0.000005
-0.480000 -0.447520 -0.447490 0.000030
-0.440000 -0.414507 -0.414449 0.000058
-0.400000 -0.380506 -0.380432 0.000074
-0.360000 -0.345555 -0.345480 0.000075
-0.320000 -0.309703 -0.309643 0.000060
-0.280000 -0.273009 -0.272978 0.000030
-0.240000 -0.235545 -0.235552 0.000007
-0.200000 -0.197395 -0.197441 0.000045
-0.160000 -0.158655 -0.158727 0.000072
-0.120000 -0.119429 -0.119505 0.000076
-0.080000 -0.079830 -0.079875 0.000045
-0.040000 -0.039979 -0.039948 0.000031
0.000000 0.000000 -0.000158 0.000158
0.040000 0.039979 0.039948 0.000031
0.080000 0.079830 0.079875 0.000045
0.120000 0.119429 0.119505 0.000076
0.160000 0.158655 0.158728 0.000072
0.200000 0.197396 0.197441 0.000045
0.240000 0.235545 0.235552 0.000007
0.280000 0.273009 0.272978 0.000030
0.320000 0.309703 0.309643 0.000060
0.360000 0.345556 0.345480 0.000075
0.400000 0.380506 0.380432 0.000074
0.440000 0.414507 0.414449 0.000058
0.480000 0.447520 0.447490 0.000030
0.520000 0.479519 0.479524 0.000005
0.560000 0.510488 0.510528 0.000040
0.600000 0.540420 0.540487 0.000068
0.640000 0.569313 0.569395 0.000082
0.680000 0.597177 0.597256 0.000079
0.720000 0.624023 0.624080 0.000057
0.760000 0.649871 0.649889 0.000018
0.800000 0.674741 0.674711 0.000030
0.840000 0.698660 0.698583 0.000077
0.880000 0.721655 0.721553 0.000102
0.920000 0.743756 0.743676 0.000080
0.960000 0.764993 0.765014 0.000021
LSQERR: 4.990835e-09f
MAXERR: 0.000243
PI_4: 0.785398
*/
// Pseudo Sine function.
//
// Originally from Stefan Stenzel, CEO of Waldorf
// @url: https://namoseley.wordpress.com/2017/01/03/pseudo-sinusoidal-waveform-ii/
// https://twitter.com/5tenzel/status/816225338330140673
#include <math.h>
#include <stdio.h>
/* x in [-1,1] -> [-1,1] */
float waldorf_cycle(float x)
{
float abs_x = x < 0.f? -x:x;
return x*4.f*(1 - abs_x);
}
/* x in [-1,1] -> [-1,1] */
float cycle(float x)
{
return sin(x*3.14159265358979323846);
}
int main(int argc, char **argv)
{
float x0 = -1.0f;
float x1 = x0 + 2.f;
float xinc = (x1 - x0)/50.0f;
float err_max = 0.0;
float lsqerr = 0.0;
int lsqerr_n = 0;
printf("x\tcycle\twaldorf_cycle\terr\n");
for (float x = x0; x <= x1; x += xinc) {
float y = cycle(x);
float wy = waldorf_cycle(x);
float err = fabs(wy - y);
err_max = err_max<err? err:err_max;
printf("%f\t%f\t%f\t%f\n", x, wy, y, err);
lsqerr += err*err;
++lsqerr_n;
}
printf("LSQERR: %f\n", lsqerr/lsqerr_n);
printf("MAXERR: %f\n", err_max);
return 0;
}
/*
clang waldorf_sin.c -o waldorf_sin && ./waldorf_sin
x cycle waldorf_cycle err
-1.000000 -0.000000 -0.000000 0.000000
-0.960000 -0.153600 -0.125333 0.028267
-0.920000 -0.294400 -0.248690 0.045710
-0.880000 -0.422400 -0.368125 0.054275
-0.840000 -0.537600 -0.481754 0.055846
-0.800000 -0.640000 -0.587786 0.052215
-0.760000 -0.729600 -0.684547 0.045053
-0.720000 -0.806400 -0.770514 0.035887
-0.680000 -0.870400 -0.844328 0.026072
-0.640000 -0.921600 -0.904827 0.016773
-0.600000 -0.960000 -0.951057 0.008943
-0.560000 -0.985600 -0.982287 0.003313
-0.520000 -0.998400 -0.998027 0.000373
-0.480000 -0.998400 -0.998027 0.000373
-0.440000 -0.985600 -0.982287 0.003313
-0.400000 -0.960000 -0.951056 0.008944
-0.360000 -0.921600 -0.904827 0.016773
-0.320000 -0.870400 -0.844328 0.026072
-0.280000 -0.806400 -0.770513 0.035887
-0.240000 -0.729600 -0.684547 0.045053
-0.200000 -0.640000 -0.587785 0.052215
-0.160000 -0.537600 -0.481753 0.055846
-0.120000 -0.422399 -0.368124 0.054275
-0.080000 -0.294399 -0.248689 0.045710
-0.040000 -0.153599 -0.125333 0.028267
0.000000 0.000001 0.000001 0.000000
0.040000 0.153601 0.125334 0.028267
0.080000 0.294401 0.248690 0.045710
0.120000 0.422401 0.368125 0.054275
0.160000 0.537600 0.481754 0.055846
0.200000 0.640000 0.587786 0.052215
0.240000 0.729600 0.684547 0.045053
0.280000 0.806400 0.770514 0.035887
0.320000 0.870400 0.844328 0.026072
0.360000 0.921600 0.904827 0.016773
0.400000 0.960000 0.951057 0.008943
0.440000 0.985600 0.982287 0.003313
0.480000 0.998400 0.998027 0.000373
0.520000 0.998400 0.998027 0.000373
0.560000 0.985600 0.982287 0.003313
0.600000 0.960000 0.951056 0.008943
0.640000 0.921600 0.904827 0.016773
0.680000 0.870400 0.844328 0.026072
0.720000 0.806400 0.770513 0.035887
0.760000 0.729600 0.684547 0.045053
0.800000 0.639999 0.587785 0.052215
0.840000 0.537599 0.481753 0.055846
0.880000 0.422399 0.368124 0.054275
0.920000 0.294399 0.248689 0.045710
0.960000 0.153599 0.125332 0.028267
LSQERR: 0.001284
MAXERR: 0.055846
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.