Skip to content
Snippets Groups Projects
Commit ad6e4432 authored by Sander Mathijs van Veen's avatar Sander Mathijs van Veen
Browse files

Added Sander's modsim ass2.

parent 6f9f38c3
No related branches found
No related tags found
No related merge requests found
CFLAGS := -Wextra -Wall -Werror -g -std=c99 -D_GNU_SOURCE
LDFLAGS := -lm
progs := bisection numdiff sqrt newton_raphson
all: $(progs)
bisection: bisection.c
numdiff: numdiff.c
sqrt: sqrt.c
newton_raphson: newton_raphson.c
$(progs): CFLAGS += -DMAIN_$@
clean: ; $(RM) $(progs)
#include <stdio.h>
#include <math.h>
static double bisect(double (*f)(double), double a, double b, double tolerance,
unsigned int *steps, unsigned int max_steps, double approximation,
int error_per_step)
{
double c = INFINITY;
for ( *steps = 1; *steps < max_steps; *steps += 1) {
c = (a + b) / 2;
if ( error_per_step )
printf("step %2d error: %.3E (%3f%%)\n", *steps,
fabs(approximation - c),
100 * fabs(c - approximation) / approximation);
if (f(c) == 0 || (b - a) / 2 < tolerance)
return c;
if (signbit(f(c)) == signbit(f(a)))
a = c;
else
b = c;
}
return c;
}
#ifdef MAIN_bisection
static inline double f(double x) { return x * sin(x) - 1.0; }
int main(void)
{
double approximation = 1.11415714087193008730052518;
unsigned int steps;
bisect(&f, 0.0, 2.0, 10e-12, &steps, 100, approximation, 0);
printf("bisection of x * sin(x) - 1 for x in [%.1f, %.1f] in %d steps.\n",
0.0, 2.0, steps);
return 0;
}
#endif
#include <stdio.h>
#include <math.h>
static double newton_raphson(double (*f)(double), double (*df)(double),
double start_x, double tolerance, unsigned int *steps,
unsigned int max_steps, double approximation, int error_per_step)
{
double x = start_x, last_x = x - 1;
for( *steps = 1; fabs(x - last_x) >= tolerance; (*steps)++ ) {
if ( *steps == max_steps )
return NAN;
last_x = x;
x -= f(x) / df(x);
if ( error_per_step )
printf("step %2d error: %.3E (%3f%%)\n", *steps,
fabs(approximation - last_x),
100 * fabs(last_x - approximation) / approximation);
}
return x;
}
#ifdef MAIN_newton_raphson
static inline double f1(double x) { return x * x - x + 2; }
static inline double df1(double x) { return 2 * x - 1; }
static inline double f2(double x) { return x * x * x - 3 * x - 2; }
static inline double df2(double x) { return 3 * x * x - 3; }
static inline double f3(double x) { return (x * x + 1) * (x - 4); }
static inline double df3(double x) { return 3 * x * x - 8 * x + 1; }
int main(void)
{
unsigned int steps;
double result;
result = newton_raphson(&f1, &df1, 0, 10e-12, &steps, 100, 0, 0);
printf("f1 using newton-raphson = %.20f (%d steps)\n", result, steps);
result = newton_raphson(&f2, &df2, -10, 10e-12, &steps, 100, 0, 0);
printf("f2 using newton-raphson = %.20f (%d steps)\n", result, steps);
result = newton_raphson(&f2, &df2, 10, 10e-12, &steps, 100, 0, 0);
printf("f2 using newton-raphson = %.20f (%d steps)\n", result, steps);
result = newton_raphson(&f3, &df3, 0, 10e-12, &steps, 100, 0, 0);
printf("f3 using newton-raphson = %.20f (%d steps)\n", result, steps);
return 0;
}
#endif
#include <stdio.h>
#include <math.h>
#include <float.h>
static double numdiff_central(double (*f)(double), double x, double h) {
return (f(x + h) - f(x - h)) / (2 * h);
}
static double numdiff_right(double (*f)(double), double x, double h) {
return (f(x + h) - f(x)) / h;
}
#define NUMDIFF(f, x) { \
volatile double h = sqrt(DBL_EPSILON) * (x); \
\
printf("right-hand diff. of " #f "(x) for x = " #x ": %lf\n", \
numdiff_right(f, x, h)); \
\
printf("central diff. of " #f "(x) for x = " #x ": %lf\n", \
numdiff_central(f, x, h)); \
\
printf("calculated h = √e * (" #x "): %lf\n\n", h); \
}
int main(void)
{
NUMDIFF(sin, M_PI / 3.0);
NUMDIFF(sin, 100 * M_PI + M_PI / 3.0);
NUMDIFF(sin, 10e12 * M_PI + M_PI / 3.0);
return 0;
}
#include <stdio.h>
#include <math.h>
#include "bisection.c"
#include "newton_raphson.c"
static double regula_falsi(double (*f)(double), double a, double b,
double tolerance, unsigned int *steps, unsigned int max_steps,
double approximation, int error_per_step)
{
int side = 0;
double c, fc, fa = f(a), fb = f(b);
for( *steps = 1; *steps < max_steps; (*steps)++ ) {
c = (fa * b - fb * a) / (fa - fb);
if ( error_per_step )
printf("step %2d error: %.3E (%3f%%)\n", *steps,
fabs(approximation - c),
100 * fabs(c - approximation) / approximation);
if ( fabs(b - a) < tolerance * fabs(b + a) )
break;
fc = f(c);
if ( fc * fb > 0 ) {
b = c;
fb = fc;
if( side == -1 )
fa /= 2;
side = -1;
} else if (fa * fc > 0) {
a = c;
fa = fc;
if( side == 1 )
fb /= 2;
side = 1;
} else
break;
}
return c;
}
#ifdef MAIN_sqrt
static inline double f(double x) { return x * x - 2; }
static inline double df(double x) { return 2 * x; }
int main(void)
{
unsigned int steps;
double approx = 1.41421356237309504880168872420, result;
printf("√2 is approximate = %.20f\n", approx);
result = bisect(&f, 1, 2, 10e-12, &steps, 100, approx, 0);
printf("√2 using bisection = %.20f (%d steps)\n", result, steps);
result = regula_falsi(&f, 1, 2, 10e-12, &steps, 100, approx, 0);
printf("√2 using regula falsi = %.20f (%d steps)\n", result, steps);
result = newton_raphson(&f, &df, 1.4, 10e-12, &steps, 100, approx, 0);
printf("√2 using newton-raphson = %.20f (%d steps)\n", result, steps);
return 0;
}
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment