refactor c files
This commit is contained in:
parent
32294879c9
commit
86938469af
2
posts/stereo/1/.gitignore
vendored
Normal file
2
posts/stereo/1/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
compare_complex
|
||||||
|
compare_math
|
||||||
10
posts/stereo/1/Makefile
Normal file
10
posts/stereo/1/Makefile
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
default: compare_complex compare_math
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf compare_complex compare_math
|
||||||
|
|
||||||
|
compare_complex:
|
||||||
|
gcc main.c stereo_complex.c -lm -DUSE_COMPLEX -o compare_complex
|
||||||
|
|
||||||
|
compare_math:
|
||||||
|
gcc main.c stereo_math.c -lm -o compare_math
|
||||||
168
posts/stereo/1/main.c
Normal file
168
posts/stereo/1/main.c
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
#include <complex.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define STR_RED "\x1b[31m"
|
||||||
|
#define STR_GREEN "\x1b[32m"
|
||||||
|
#define STR_NORM "\x1b[m"
|
||||||
|
|
||||||
|
#define SECONDS_PER_NANOSECOND 1000000000
|
||||||
|
#define NUM_LOOPS 100000
|
||||||
|
#define SQRT_NUM_LOOPS 100
|
||||||
|
|
||||||
|
struct circle {
|
||||||
|
double c;
|
||||||
|
double s;
|
||||||
|
};
|
||||||
|
|
||||||
|
void turn_update(double turn, void* result);
|
||||||
|
void approx_turn_update(double turn, void* result);
|
||||||
|
|
||||||
|
#ifdef USE_COMPLEX
|
||||||
|
#define EXTRACT_REAL(a) creal(a)
|
||||||
|
#define EXTRACT_IMAG(a) cimag(a)
|
||||||
|
#define CIRCLE_TYPE double complex
|
||||||
|
#else
|
||||||
|
#define EXTRACT_REAL(a) (a.c)
|
||||||
|
#define EXTRACT_IMAG(a) (a.s)
|
||||||
|
#define CIRCLE_TYPE struct circle
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void print_errors(
|
||||||
|
const double* inputs,
|
||||||
|
const CIRCLE_TYPE* ideals,
|
||||||
|
const CIRCLE_TYPE* approxs,
|
||||||
|
int n
|
||||||
|
)
|
||||||
|
{
|
||||||
|
double c_error, s_error;
|
||||||
|
double largest_c_error, largest_s_error;
|
||||||
|
size_t largest_c_index, largest_s_index;
|
||||||
|
|
||||||
|
double total_c_error = 0, total_s_error = 0;
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
CIRCLE_TYPE ideal, approx;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
ideal = ideals[i];
|
||||||
|
approx = approxs[i];
|
||||||
|
|
||||||
|
// squared error in c components
|
||||||
|
c_error = EXTRACT_REAL(ideal) - EXTRACT_REAL(approx);
|
||||||
|
c_error *= c_error;
|
||||||
|
// squared error in s components
|
||||||
|
s_error = EXTRACT_IMAG(ideal) - EXTRACT_IMAG(approx);
|
||||||
|
s_error *= s_error;
|
||||||
|
|
||||||
|
if (largest_c_error < c_error) {
|
||||||
|
largest_c_error = c_error;
|
||||||
|
largest_c_index = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (largest_s_error < s_error) {
|
||||||
|
largest_s_error = s_error;
|
||||||
|
largest_s_index = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
total_c_error += c_error;
|
||||||
|
total_s_error += s_error;
|
||||||
|
}
|
||||||
|
// these now contain the *average* squared error
|
||||||
|
total_c_error /= (double)n;
|
||||||
|
total_s_error /= (double)n;
|
||||||
|
|
||||||
|
printf(
|
||||||
|
"Squared error in cosines: \n"
|
||||||
|
"\tAverage: %f (%f%% error)\n"
|
||||||
|
"\tLargest: %f (%f%% error)\n"
|
||||||
|
"\t\tInput:\t\t%f\n"
|
||||||
|
"\t\tValue:\t\t%f\n"
|
||||||
|
"\t\tApproximation:\t%f\n",
|
||||||
|
total_c_error, sqrt(total_c_error) * SQRT_NUM_LOOPS, largest_c_error,
|
||||||
|
sqrt(largest_c_error) * SQRT_NUM_LOOPS, inputs[largest_c_index],
|
||||||
|
EXTRACT_REAL(ideals[largest_c_index]),
|
||||||
|
EXTRACT_REAL(approxs[largest_c_index])
|
||||||
|
);
|
||||||
|
printf(
|
||||||
|
"Squared error in sines: \n"
|
||||||
|
"\tAverage: %f (%f%% error)\n"
|
||||||
|
"\tLargest: %f (%f%% error)\n"
|
||||||
|
"\t\tInput:\t\t%f\n"
|
||||||
|
"\t\tValue:\t\t%f\n"
|
||||||
|
"\t\tApproximation:\t%f\n",
|
||||||
|
total_s_error, sqrt(total_s_error) * SQRT_NUM_LOOPS, largest_s_error,
|
||||||
|
sqrt(largest_s_error) * SQRT_NUM_LOOPS, inputs[largest_c_index],
|
||||||
|
EXTRACT_IMAG(ideals[largest_s_index]),
|
||||||
|
EXTRACT_IMAG(approxs[largest_s_index])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// time the length of the computation `f` in nanoseconds
|
||||||
|
long time_computation(
|
||||||
|
void (*f)(double, void*), const double* inputs, CIRCLE_TYPE* results, int n
|
||||||
|
)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
struct timespec tp1;
|
||||||
|
struct timespec tp2;
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &tp1);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
f(inputs[i], results + i);
|
||||||
|
}
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &tp2);
|
||||||
|
|
||||||
|
return SECONDS_PER_NANOSECOND * (tp2.tv_sec - tp1.tv_sec) +
|
||||||
|
(tp2.tv_nsec - tp1.tv_sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argn, char** args)
|
||||||
|
{
|
||||||
|
long trig_time, rat_time;
|
||||||
|
|
||||||
|
double rands[NUM_LOOPS];
|
||||||
|
CIRCLE_TYPE trigs[NUM_LOOPS];
|
||||||
|
CIRCLE_TYPE rats[NUM_LOOPS];
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < NUM_LOOPS; i++) {
|
||||||
|
rands[i] = rand() / (double)RAND_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
trig_time = time_computation(&turn_update, rands, trigs, NUM_LOOPS);
|
||||||
|
printf(
|
||||||
|
#ifdef USE_COMPLEX
|
||||||
|
"Timing for %d complex.h cexp:\t%ldns\n",
|
||||||
|
#else
|
||||||
|
"Timing for %d math.h sin and cos:\t%ldns\n",
|
||||||
|
#endif
|
||||||
|
NUM_LOOPS,
|
||||||
|
trig_time
|
||||||
|
);
|
||||||
|
|
||||||
|
rat_time = time_computation(&approx_turn_update, rands, rats, NUM_LOOPS);
|
||||||
|
printf("Timing for %d approximations:\t%ldns\n", NUM_LOOPS, rat_time);
|
||||||
|
|
||||||
|
long diff = rat_time - trig_time;
|
||||||
|
double frac_speed;
|
||||||
|
if (diff > 0) {
|
||||||
|
frac_speed = rat_time / (double)trig_time;
|
||||||
|
printf(
|
||||||
|
STR_RED "stdlib" STR_NORM " faster, speedup: %ldns (%2.2fx)\n",
|
||||||
|
diff, frac_speed
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
frac_speed = trig_time / (double)rat_time;
|
||||||
|
printf(
|
||||||
|
STR_GREEN "Approximation" STR_NORM
|
||||||
|
" faster, speedup: %ldns (%2.2fx)\n",
|
||||||
|
-diff, frac_speed
|
||||||
|
);
|
||||||
|
print_errors(rands, trigs, rats, NUM_LOOPS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -1,20 +1,7 @@
|
|||||||
#include <complex.h>
|
#include <complex.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#define STRRED "\x1b[31m"
|
double complex complex_approx_turn(double turn)
|
||||||
#define STRGREEN "\x1b[32m"
|
|
||||||
#define STRNORM "\x1b[m"
|
|
||||||
|
|
||||||
#define SECONDS_PER_NANOSECOND 1000000000
|
|
||||||
|
|
||||||
#define NUM_LOOPS 100000
|
|
||||||
|
|
||||||
double complex complex_turn(double turn) { return cexp(I * M_PI * turn); }
|
|
||||||
|
|
||||||
double complex approx_turn(double turn)
|
|
||||||
{
|
{
|
||||||
const static double a = 8 * M_SQRT2 / 3 - 3;
|
const static double a = 8 * M_SQRT2 / 3 - 3;
|
||||||
const static double b = 4 - 8 * M_SQRT2 / 3;
|
const static double b = 4 - 8 * M_SQRT2 / 3;
|
||||||
@ -27,130 +14,14 @@ double complex approx_turn(double turn)
|
|||||||
return (c * c - s * s) + I * (2 * c * s);
|
return (c * c - s * s) + I * (2 * c * s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_errors(
|
double complex complex_turn(double turn) { return cexp(I * M_PI * turn); }
|
||||||
const double* inputs,
|
|
||||||
const double complex* ideals,
|
void turn_update(double turn, double complex* result)
|
||||||
const double complex* approxs,
|
|
||||||
int n
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
double c_error, s_error;
|
*result = complex_turn(turn);
|
||||||
double largest_c_error, largest_s_error;
|
|
||||||
size_t largest_c_index, largest_s_index;
|
|
||||||
|
|
||||||
double total_c_error = 0, total_s_error = 0;
|
|
||||||
|
|
||||||
size_t i;
|
|
||||||
double complex ideal, approx;
|
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
|
||||||
ideal = ideals[i];
|
|
||||||
approx = approxs[i];
|
|
||||||
|
|
||||||
// squared error in c components
|
|
||||||
c_error = creal(ideal) - creal(approx);
|
|
||||||
c_error *= c_error;
|
|
||||||
// squared error in s components
|
|
||||||
s_error = cimag(ideal) - cimag(approx);
|
|
||||||
s_error *= s_error;
|
|
||||||
|
|
||||||
if (largest_c_error < c_error) {
|
|
||||||
largest_c_error = c_error;
|
|
||||||
largest_c_index = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (largest_s_error < s_error) {
|
|
||||||
largest_s_error = s_error;
|
|
||||||
largest_s_index = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
total_c_error += c_error;
|
|
||||||
total_s_error += s_error;
|
|
||||||
}
|
|
||||||
// these now contain the *average* squared error
|
|
||||||
total_c_error /= (double)n;
|
|
||||||
total_s_error /= (double)n;
|
|
||||||
|
|
||||||
printf(
|
|
||||||
"Squared error in cosines: \n"
|
|
||||||
"\tAverage: %f (%f%% error)\n"
|
|
||||||
"\tLargest: %f (%f%% error)"
|
|
||||||
"\n\t\tInput:\t\t%f\n\t\tValue:\t\t%f\n\t\tApproximation:\t%f\n",
|
|
||||||
total_c_error, sqrt(total_c_error) * 100, largest_c_error,
|
|
||||||
sqrt(largest_c_error) * 100, inputs[largest_c_index],
|
|
||||||
creal(ideals[largest_c_index]), creal(approxs[largest_c_index])
|
|
||||||
);
|
|
||||||
printf(
|
|
||||||
"Squared error in sines: \n"
|
|
||||||
"\tAverage: %f (%f%% error)\n\tLargest: %f (%f%% error)"
|
|
||||||
"\n\t\tInput:\t\t%f\n\t\tValue:\t\t%f\n\t\tApproximation:\t%f\n",
|
|
||||||
total_s_error, sqrt(total_s_error) * 100, largest_s_error,
|
|
||||||
sqrt(largest_s_error) * 100, inputs[largest_c_index],
|
|
||||||
cimag(ideals[largest_s_index]), cimag(approxs[largest_s_index])
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// time the length of the computation `f` in nanoseconds
|
void approx_turn_update(double turn, double complex* result)
|
||||||
long time_computation(
|
|
||||||
double complex (*f)(double),
|
|
||||||
const double* inputs,
|
|
||||||
double complex* results,
|
|
||||||
int n
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
size_t i;
|
*result = complex_approx_turn(turn);
|
||||||
long tick_s;
|
|
||||||
long tick_ns;
|
|
||||||
struct timespec tp;
|
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &tp);
|
|
||||||
tick_ns = tp.tv_nsec;
|
|
||||||
tick_s = tp.tv_sec;
|
|
||||||
for (i = 0; i < n; i++) {
|
|
||||||
results[i] = f(inputs[i]);
|
|
||||||
}
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &tp);
|
|
||||||
|
|
||||||
return SECONDS_PER_NANOSECOND * (tp.tv_sec - tick_s) +
|
|
||||||
(tp.tv_nsec - tick_ns);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argn, char** args)
|
|
||||||
{
|
|
||||||
long trig_time, rat_time;
|
|
||||||
|
|
||||||
double rands[NUM_LOOPS];
|
|
||||||
double complex trigs[NUM_LOOPS];
|
|
||||||
double complex rats[NUM_LOOPS];
|
|
||||||
|
|
||||||
size_t i;
|
|
||||||
for (i = 0; i < NUM_LOOPS; i++) {
|
|
||||||
rands[i] = rand() / (double)RAND_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
trig_time = time_computation(&complex_turn, rands, trigs, NUM_LOOPS);
|
|
||||||
printf("Timing for %d math.h sin and cos:\t%ldns\n", NUM_LOOPS, trig_time);
|
|
||||||
|
|
||||||
rat_time = time_computation(&approx_turn, rands, rats, NUM_LOOPS);
|
|
||||||
printf("Timing for %d approximations:\t%ldns\n", NUM_LOOPS, rat_time);
|
|
||||||
|
|
||||||
long diff = rat_time - trig_time;
|
|
||||||
double frac_speed;
|
|
||||||
if (diff > 0) {
|
|
||||||
frac_speed = rat_time / (double)trig_time;
|
|
||||||
printf(
|
|
||||||
STRRED "math.h" STRNORM " faster, speedup: %ldns (%2.2fx)\n", diff,
|
|
||||||
frac_speed
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
frac_speed = trig_time / (double)rat_time;
|
|
||||||
printf(
|
|
||||||
STRGREEN "Approximation" STRNORM
|
|
||||||
" faster, speedup: %ldns (%2.2fx)\n",
|
|
||||||
-diff, frac_speed
|
|
||||||
);
|
|
||||||
print_errors(rands, trigs, rats, NUM_LOOPS);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,29 +1,15 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#define STRRED "\x1b[31m"
|
|
||||||
#define STRGREEN "\x1b[32m"
|
|
||||||
#define STRNORM "\x1b[m"
|
|
||||||
|
|
||||||
struct circle {
|
struct circle {
|
||||||
double c;
|
double c;
|
||||||
double s;
|
double s;
|
||||||
};
|
};
|
||||||
|
|
||||||
double a = 8 * M_SQRT2 / 3 - 3;
|
void approx_turn_update(double turn, struct circle* ret)
|
||||||
double b = 4 - 8 * M_SQRT2 / 3;
|
|
||||||
|
|
||||||
void trig(double turn, struct circle* ret)
|
|
||||||
{
|
{
|
||||||
double arg = M_PI * turn;
|
static const double a = 8 * M_SQRT2 / 3 - 3;
|
||||||
ret->c = cos(arg);
|
static const double b = 4 - 8 * M_SQRT2 / 3;
|
||||||
ret->s = sin(arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rational(double turn, struct circle* ret)
|
|
||||||
{
|
|
||||||
double p = turn * (b * turn * turn + a);
|
double p = turn * (b * turn * turn + a);
|
||||||
double q = p * p;
|
double q = p * p;
|
||||||
double r = 1 + q;
|
double r = 1 + q;
|
||||||
@ -33,108 +19,9 @@ void rational(double turn, struct circle* ret)
|
|||||||
ret->s = 2 * c * s;
|
ret->s = 2 * c * s;
|
||||||
}
|
}
|
||||||
|
|
||||||
double
|
void turn_update(double turn, struct circle* ret)
|
||||||
errors(int n, const struct circle* circles1, const struct circle* circles2)
|
|
||||||
{
|
{
|
||||||
double c_error, s_error;
|
double arg = M_PI * turn;
|
||||||
double largest_c_error, largest_s_error;
|
ret->c = cos(arg);
|
||||||
|
ret->s = sin(arg);
|
||||||
double total_c_error = 0, total_s_error = 0;
|
|
||||||
|
|
||||||
int i;
|
|
||||||
struct circle circle1, circle2;
|
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
|
||||||
circle1 = circles1[i];
|
|
||||||
circle2 = circles2[i];
|
|
||||||
|
|
||||||
// squared error in c components
|
|
||||||
c_error = circle1.c - circle2.c;
|
|
||||||
c_error *= c_error;
|
|
||||||
// squared error in s components
|
|
||||||
s_error = circle1.s - circle2.s;
|
|
||||||
s_error *= s_error;
|
|
||||||
|
|
||||||
if (largest_c_error < c_error)
|
|
||||||
largest_c_error = c_error;
|
|
||||||
|
|
||||||
if (largest_s_error < s_error)
|
|
||||||
largest_s_error = s_error;
|
|
||||||
|
|
||||||
total_c_error += c_error;
|
|
||||||
total_s_error += s_error;
|
|
||||||
}
|
|
||||||
// these now contain the *average* squared error
|
|
||||||
total_c_error /= (double)n;
|
|
||||||
total_s_error /= (double)n;
|
|
||||||
|
|
||||||
printf(
|
|
||||||
"Squared error in cosines: \n\tAverage: %f (%f%% error)\n\tLargest: %f "
|
|
||||||
"(%f%% error)\n",
|
|
||||||
total_c_error, sqrt(total_c_error) * 100, largest_c_error,
|
|
||||||
sqrt(largest_c_error) * 100
|
|
||||||
);
|
|
||||||
printf(
|
|
||||||
"Squared error in sines: \n\tAverage: %f (%f%% error)\n\tLargest: %f "
|
|
||||||
"(%f%% error)\n",
|
|
||||||
total_s_error, sqrt(total_s_error) * 100, largest_s_error,
|
|
||||||
sqrt(largest_s_error) * 100
|
|
||||||
);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argn, char** args)
|
|
||||||
{
|
|
||||||
// struct circle ret;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
struct timespec tp;
|
|
||||||
long tick;
|
|
||||||
long trig_time, rat_time;
|
|
||||||
|
|
||||||
double rands[10000];
|
|
||||||
struct circle trigs[10000];
|
|
||||||
struct circle rats[10000];
|
|
||||||
|
|
||||||
for (i = 0; i < 10000; i++) {
|
|
||||||
rands[i] = rand() / (double)RAND_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &tp);
|
|
||||||
tick = tp.tv_nsec;
|
|
||||||
for (i = 0; i < 10000; i++) {
|
|
||||||
trig(rands[i], trigs + i);
|
|
||||||
}
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &tp);
|
|
||||||
// this isn't quite proper, since the clock may have ticked over a second
|
|
||||||
trig_time = tp.tv_nsec - tick;
|
|
||||||
printf("Timing for 10000 math.h sin and cos:\t%ldns\n", trig_time);
|
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &tp);
|
|
||||||
tick = tp.tv_nsec;
|
|
||||||
for (i = 0; i < 10000; i++) {
|
|
||||||
rational(rands[i], rats + i);
|
|
||||||
}
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &tp);
|
|
||||||
rat_time = tp.tv_nsec - tick;
|
|
||||||
printf("Timing for 10000 approximations:\t%ldns\n", rat_time);
|
|
||||||
|
|
||||||
double fracSpeed;
|
|
||||||
long linSpeed = rat_time - trig_time;
|
|
||||||
if (linSpeed > 0) {
|
|
||||||
fracSpeed = rat_time / (double)trig_time;
|
|
||||||
printf(
|
|
||||||
STRRED "math.h" STRNORM " faster, speedup: %ldns (%2.2fx)\n",
|
|
||||||
linSpeed, fracSpeed
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
fracSpeed = trig_time / (double)rat_time;
|
|
||||||
printf(
|
|
||||||
STRGREEN "Approximation" STRNORM
|
|
||||||
" faster, speedup: %ldns (%2.2fx)\n",
|
|
||||||
-linSpeed, fracSpeed
|
|
||||||
);
|
|
||||||
errors(10000, rats, trigs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user