Skip to content

Instantly share code, notes, and snippets.

@uucidl
Last active January 4, 2018 00:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save uucidl/d1a60cc0e4ce9d911c5f38dec8db6356 to your computer and use it in GitHub Desktop.
Save uucidl/d1a60cc0e4ce9d911c5f38dec8db6356 to your computer and use it in GitHub Desktop.
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