diff --git a/Projekt2_Knuettel_Daniel.c b/Projekt2_Knuettel_Daniel.c index d546d44..f443415 100644 --- a/Projekt2_Knuettel_Daniel.c +++ b/Projekt2_Knuettel_Daniel.c @@ -50,6 +50,15 @@ * * gcc -o main -lm Projekt2_Knuettel_Daniel.c lib/lrmp.c lib/vorrueckwaertsub.c * + * + * Preprocessor flags: + * + * - DEBUG turns on some more output. + * - NOCRAPMODE enables a reusable interface which is not conformous to the + * specification given but allowes to used the algorithms with arbitrary + * functions. Also this adds the functions `write_error_(newton|bisek)`. + * - ALLOW_NEGATGIVE_ERRORS allows negative errors which might be interesting. + * */ @@ -88,7 +97,8 @@ int bisec_one(double * x_minus * \param eps Used precision. * \param Nmax Stop searching after Nmax iterations. * \param flag Will be set to 0xf000, if the goal has been reached, - * to 0xf001, if Nmax has been reached. + * to 0xf001, if Nmax has been reached + * , to 0xf004 if f(a)*f(b) >= 0. * Any other value indicates an unknown error. * \param file The function will not use this parameter, it is there just * for backwards compability. @@ -104,6 +114,7 @@ double bisek(double (*f)(double) , int * flag , FILE * file); +#ifdef NOCRAPMODE /* * \brief Calculate f(x) < eps using bisek and write the results to file. * @@ -113,12 +124,15 @@ double bisek(double (*f)(double) * \param eps Used precision. * \param Nmax Stop searching after Nmax iterations. * \param flag Will be set to 0xf000, if the goal has been reached, - * to 0xf001, if Nmax has been reached. + * to 0xf001, if Nmax has been reached + * , to 0xf004 if f(a)*f(b) >= 0. * Any other value indicates an unknown error. * \param file Write ``Nmax,error\n`` to this file. * \param x0 The real result for bisek. + * + * \return The result of the bisection * */ -int write_error_bisek(double (*f)(double) +double write_error_bisek(double (*f)(double) , double a , double b , double eps @@ -126,6 +140,7 @@ int write_error_bisek(double (*f)(double) , int * flag , FILE * file , double x0); +#endif @@ -155,6 +170,7 @@ double newton(double x0 , FILE * file); +#ifdef NOCRAPMODE /* * \brief Calculate f(x) < eps or a minimum of f. And write the results to file * @@ -181,6 +197,7 @@ double write_error_newton(double x0 , int * flag , FILE * file , double x1); +#endif /* * \brief Calculate one step of the newton iteration. @@ -282,6 +299,7 @@ double dg2(double x); void g(double * x, double * y, int N); void dg(double * x, double ** y, int N); + int main(void) { @@ -289,41 +307,57 @@ int main(void) int flag; double result; -// // Calculate the bisection of g1. -// for(i = 1, j = 0; i < 100 ;i += 1, j++) -// { -// write_error_bisek(g1, -2.5, -100, 1e-7, i, &flag, stdout, -6); -// } -// printf("XXX\n"); -// fprintf(stderr, "wrote %d lines for g1 to /dev/stdout\n", j); -// -// // Calculate the bisection of g2. -// // Note that the output of this will be basically crap, because -// // g2 does not meet the requirements for a bisection. -// for(i = 1, j = 0; i < 100 ;i += 1, j++) -// { -// write_error_bisek(g2, -2.5, -100, 1e-7, i, &flag, stdout, -6); -// } -// printf("XXX\n"); -// fprintf(stderr, "wrote %d lines for g2 to /dev/stdout\n", j); -// -// // Calculate the newton iteration of g1. -// for(i = 1, j = 0; i < 100 ;i += 1, j++) -// { -// write_error_newton(-100, g1, dg1, 1e-7, i, &flag, stdout, -6); -// } -// printf("XXX\n"); -// fprintf(stderr, "wrote %d lines for g1 to /dev/stdout\n", j); -// -// // Calculate the newton iteration of g2. -// // Note that the output of this will be basically crap, because -// // g2 does not meet the requirements for the newton iteration. -// for(i = 1, j = 0; i < 100 ;i += 1, j++) -// { -// write_error_newton(-100, g2, dg1, 1e-7, i, &flag, stdout, -6); -// } -// printf("XXX\n"); -// fprintf(stderr, "wrote %d lines for g2 to /dev/stdout\n", j); + // Calculate the bisection of g1. + for(i = 1, j = 0; i < 100 ;i += 1, j++) + { +#ifdef NOCRAPMODE + write_error_bisek(g1, -2.5, -100, 1e-7, i, &flag, stdout, -6); +#else + bisek(g1, -2.5, -100, 1e-7, i, &flag, stdout); +#endif + } + printf("XXX\n"); + fprintf(stderr, "wrote %d lines for g1 to /dev/stdout\n", j); + + // Calculate the bisection of g2. + // Note that the output of this will be basically crap, because + // g2 does not meet the requirements for a bisection. + for(i = 1, j = 0; i < 100 ;i += 1, j++) + { +#ifdef NOCRAPMODE + write_error_bisek(g2, -2.5, -100, 1e-7, i, &flag, stdout, -6); +#else + bisek(g2, -2.5, -100, 1e-7, i, &flag, stdout); +#endif + } + printf("XXX\n"); + fprintf(stderr, "wrote %d lines for g2 to /dev/stdout\n", j); + + // Calculate the newton iteration of g1. + for(i = 1, j = 0; i < 100 ;i += 1, j++) + { +#ifdef NOCRAPMODE + write_error_newton(-100, g1, dg1, 1e-7, i, &flag, stdout, -6); +#else + newton(-100, g1, dg1, 1e-7, i, &flag, stdout); +#endif + } + printf("XXX\n"); + fprintf(stderr, "wrote %d lines for g1 to /dev/stdout\n", j); + + // Calculate the newton iteration of g2. + // Note that the output of this will be basically crap, because + // g2 does not meet the requirements for the newton iteration. + for(i = 1, j = 0; i < 100 ;i += 1, j++) + { +#ifdef NOCRAPMODE + write_error_newton(-100, g2, dg2, 1e-7, i, &flag, stdout, -6); +#else + newton(-100, g2, dg2, 1e-7, i, &flag, stdout); +#endif + } + printf("XXX\n"); + fprintf(stderr, "wrote %d lines for g2 to /dev/stdout\n", j); // Calculate the multi dimensional newton iteration @@ -433,7 +467,13 @@ int bisec_one(double * x_minus return 0; } -double bisek(double (*f)(double) +double +#ifdef NOCRAPMODE + bisek +#else + __inline_bisek +#endif + (double (*f)(double) , double a , double b , double eps @@ -441,6 +481,11 @@ double bisek(double (*f)(double) , int * flag , FILE * file) { + if(f(a)*f(b) >= 0) + { + *flag = 0xf004; + return 0; + } double x_minus = a , x_plus = b; if(a > b) @@ -466,23 +511,45 @@ double bisek(double (*f)(double) return x_minus; } -int write_error_bisek(double (*f)(double) +double +#ifdef NOCRAPMODE + write_error_bisek +#else + bisek +#endif + (double (*f)(double) , double a , double b , double eps , int Nmax , int * flag , FILE * file - , double x0) +#ifdef NOCRAPMODE + , double x0 +#endif + ) { +#ifndef NOCRAPMODE + double x0 = -6; +#endif double result , error; - result = bisek(f, a, b, eps, Nmax, flag, file); - if(*flag & 0xff) + result = +#ifdef NOCRAPMODE + bisek +#else + __inline_bisek +#endif + (f, a, b, eps, Nmax, flag, file); + if(*flag & 0x0f == 0x01) { fprintf(stderr, "WARNING: bisek(..., eps = %.10e, Nmax = %d, ...) hit Nmax.\n", eps, Nmax); } + if(*flag & 0x0f == 0x04) + { + fprintf(stderr, "WARNING: bisek(..., eps = %.10e, Nmax = %d, ...) conditions failed.\n", eps, Nmax); + } if(!(*flag & 0xff00)) { fprintf(stderr, "WARNING: bisek flag is invalid.\n"); @@ -494,12 +561,15 @@ int write_error_bisek(double (*f)(double) // FIXME: // Shold we allow negative errors? It is mathematically incorrect but // more interesting. -// if(error < 0) -// { -// error *= -1; -// } +#ifndef ALLOW_NEGATGIVE_ERRORS + if(error < 0) + { + error *= -1; + } +#endif - return fprintf(file, "%d,%.10e\n", Nmax, error); + fprintf(file, "%d,%.10e\n", Nmax, error); + return result; } @@ -511,7 +581,9 @@ int newton_one(double * x double y, yd; y = f(*x); yd = df(*x); +#ifdef DEBUG fprintf(stderr, "f(%.4e) -> %.4e; df(%.4e) -> %.4e\n", *x, y, *x, yd); +#endif if(abs(y) < eps) { return 0xe000; @@ -522,12 +594,20 @@ int newton_one(double * x } *x -= y / yd; +#ifdef DEBUG fprintf(stderr, "set new x: %.4e\n", *x); +#endif return 0; } -double newton(double x0 +double +#ifdef NOCRAPMODE + newton +#else + __inline_newton +#endif + (double x0 , double (*f)(double) , double (*df)(double) , double eps @@ -556,18 +636,36 @@ double newton(double x0 } -double write_error_newton(double x0 +double +#ifdef NOCRAPMODE + write_error_newton +#else + newton +#endif + (double x0 , double (*f)(double) , double (*df)(double) , double eps , int Nmax , int * flag , FILE * file - , double x1) +#ifdef NOCRAPMODE + , double x1 +#endif + ) { +#ifndef NOCRAPMODE + double x1 = -6; +#endif double result, error; - result = newton(x0, f, df, eps, Nmax, flag, file); + result = +#ifdef NOCRAPMODE + newton +#else + __inline_newton +#endif + (x0, f, df, eps, Nmax, flag, file); if(*flag & 0xff) { @@ -584,12 +682,15 @@ double write_error_newton(double x0 // FIXME: // Shold we allow negative errors? It is mathematically incorrect but // more interesting. -// if(error < 0) -// { -// error *= -1; -// } +#ifndef ALLOW_NEGATGIVE_ERRORS + if(error < 0) + { + error *= -1; + } +#endif - return fprintf(file, "%d,%.10e\n", Nmax, error); + fprintf(file, "%d,%.10e\n", Nmax, error); + return result; } int newton_mult(int N