
Untitled
By: a guest on
Jun 13th, 2012 | syntax:
None | size: 2.07 KB | hits: 26 | expires: Never
#include <stdio.h>
#include <math.h>
unsigned int evaluations; /* This EVIL global variable stores the number of times curve_length has been called for the current curve. */
typedef struct {double x, y;} point;
typedef point (*curve_func)(double t);
point line(double t) {
point p;
p.x = t;
p.y = t * 2;
return p;
}
point parabola(double t) {
point p;
p.x = t;
p.y = t * t;
return p;
}
point sqrt_sin(double t) {
point p;
p.x = t;
p.y = sqrt(sin(t));
return p;
}
double distance(point a, point b) {
double dx = (a.x - b.x);
double dy = (a.y - b.y);
return sqrt(dx * dx + dy * dy);
}
double curve_length(double a, double b, curve_func curve, double tolerance, unsigned int depth) {
if (depth == 1) {
evaluations = 1;
} else {
evaluations++;
}
double avg_ab = (a + b) / 2;
point curve_at_a = (*curve)(a);
point curve_at_b = (*curve)(b);
double coarse = distance(curve_at_a, curve_at_b);
point curve_at_avg_ab = (*curve)(avg_ab);
double fine = (
distance(
curve_at_a,
curve_at_avg_ab
) +
distance(
curve_at_avg_ab,
curve_at_b
)
);
if (depth == 30) {
return fine;
} else {
if ((depth >= 3) && (fabs(fine - coarse) <= tolerance)) {
return fine;
} else {
double new_tolerance = tolerance / 2;
unsigned int new_depth = depth + 1;
return (
curve_length(a, avg_ab, curve, new_tolerance, new_depth) +
curve_length(avg_ab, b, curve, new_tolerance, new_depth)
);
}
}
}
void print_curve_length(double a, double b, curve_func curve, double tolerance) {
double length = curve_length(a, b, curve, tolerance, 1);
printf(" tol %4f : %f, %d evaluations\n", tolerance, length, evaluations);
}
int main() {
printf("Line\n");
print_curve_length(0, 2, &line, .01);
print_curve_length(0, 2, &line, .0001);
printf("Parabola\n");
print_curve_length(0, 1, ¶bola, .01);
print_curve_length(0, 1, ¶bola, .0001);
printf("Sqrt sin\n");
print_curve_length(0, 1, &sqrt_sin, .01);
print_curve_length(0, 1, &sqrt_sin, .0001);
return 0;
}