master
Daniel Knüttel 2018-12-11 15:33:09 +01:00
parent 223de5d8fd
commit 68f78432c2
1 changed files with 158 additions and 57 deletions

View File

@ -50,6 +50,15 @@
* *
* gcc -o main -lm Projekt2_Knuettel_Daniel.c lib/lrmp.c lib/vorrueckwaertsub.c * 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 eps Used precision.
* \param Nmax Stop searching after Nmax iterations. * \param Nmax Stop searching after Nmax iterations.
* \param flag Will be set to 0xf000, if the goal has been reached, * \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. * Any other value indicates an unknown error.
* \param file The function will not use this parameter, it is there just * \param file The function will not use this parameter, it is there just
* for backwards compability. * for backwards compability.
@ -104,6 +114,7 @@ double bisek(double (*f)(double)
, int * flag , int * flag
, FILE * file); , FILE * file);
#ifdef NOCRAPMODE
/* /*
* \brief Calculate f(x) < eps using bisek and write the results to file. * \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 eps Used precision.
* \param Nmax Stop searching after Nmax iterations. * \param Nmax Stop searching after Nmax iterations.
* \param flag Will be set to 0xf000, if the goal has been reached, * \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. * Any other value indicates an unknown error.
* \param file Write ``Nmax,error\n`` to this file. * \param file Write ``Nmax,error\n`` to this file.
* \param x0 The real result for bisek. * \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 a
, double b , double b
, double eps , double eps
@ -126,6 +140,7 @@ int write_error_bisek(double (*f)(double)
, int * flag , int * flag
, FILE * file , FILE * file
, double x0); , double x0);
#endif
@ -155,6 +170,7 @@ double newton(double x0
, FILE * file); , FILE * file);
#ifdef NOCRAPMODE
/* /*
* \brief Calculate f(x) < eps or a minimum of f. And write the results to file * \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 , int * flag
, FILE * file , FILE * file
, double x1); , double x1);
#endif
/* /*
* \brief Calculate one step of the newton iteration. * \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 g(double * x, double * y, int N);
void dg(double * x, double ** y, int N); void dg(double * x, double ** y, int N);
int main(void) int main(void)
{ {
@ -289,41 +307,57 @@ int main(void)
int flag; int flag;
double result; double result;
// // Calculate the bisection of g1. // Calculate the bisection of g1.
// for(i = 1, j = 0; i < 100 ;i += 1, j++) for(i = 1, j = 0; i < 100 ;i += 1, j++)
// { {
// write_error_bisek(g1, -2.5, -100, 1e-7, i, &flag, stdout, -6); #ifdef NOCRAPMODE
// } write_error_bisek(g1, -2.5, -100, 1e-7, i, &flag, stdout, -6);
// printf("XXX\n"); #else
// fprintf(stderr, "wrote %d lines for g1 to /dev/stdout\n", j); bisek(g1, -2.5, -100, 1e-7, i, &flag, stdout);
// #endif
// // Calculate the bisection of g2. }
// // Note that the output of this will be basically crap, because printf("XXX\n");
// // g2 does not meet the requirements for a bisection. fprintf(stderr, "wrote %d lines for g1 to /dev/stdout\n", j);
// for(i = 1, j = 0; i < 100 ;i += 1, j++)
// { // Calculate the bisection of g2.
// write_error_bisek(g2, -2.5, -100, 1e-7, i, &flag, stdout, -6); // Note that the output of this will be basically crap, because
// } // g2 does not meet the requirements for a bisection.
// printf("XXX\n"); for(i = 1, j = 0; i < 100 ;i += 1, j++)
// fprintf(stderr, "wrote %d lines for g2 to /dev/stdout\n", j); {
// #ifdef NOCRAPMODE
// // Calculate the newton iteration of g1. write_error_bisek(g2, -2.5, -100, 1e-7, i, &flag, stdout, -6);
// for(i = 1, j = 0; i < 100 ;i += 1, j++) #else
// { bisek(g2, -2.5, -100, 1e-7, i, &flag, stdout);
// write_error_newton(-100, g1, dg1, 1e-7, i, &flag, stdout, -6); #endif
// } }
// printf("XXX\n"); printf("XXX\n");
// fprintf(stderr, "wrote %d lines for g1 to /dev/stdout\n", j); fprintf(stderr, "wrote %d lines for g2 to /dev/stdout\n", j);
//
// // Calculate the newton iteration of g2. // Calculate the newton iteration of g1.
// // Note that the output of this will be basically crap, because for(i = 1, j = 0; i < 100 ;i += 1, j++)
// // 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, g1, dg1, 1e-7, i, &flag, stdout, -6);
// write_error_newton(-100, g2, dg1, 1e-7, i, &flag, stdout, -6); #else
// } newton(-100, g1, dg1, 1e-7, i, &flag, stdout);
// printf("XXX\n"); #endif
// fprintf(stderr, "wrote %d lines for g2 to /dev/stdout\n", j); }
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 // Calculate the multi dimensional newton iteration
@ -433,7 +467,13 @@ int bisec_one(double * x_minus
return 0; return 0;
} }
double bisek(double (*f)(double) double
#ifdef NOCRAPMODE
bisek
#else
__inline_bisek
#endif
(double (*f)(double)
, double a , double a
, double b , double b
, double eps , double eps
@ -441,6 +481,11 @@ double bisek(double (*f)(double)
, int * flag , int * flag
, FILE * file) , FILE * file)
{ {
if(f(a)*f(b) >= 0)
{
*flag = 0xf004;
return 0;
}
double x_minus = a double x_minus = a
, x_plus = b; , x_plus = b;
if(a > b) if(a > b)
@ -466,23 +511,45 @@ double bisek(double (*f)(double)
return x_minus; 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 a
, double b , double b
, double eps , double eps
, int Nmax , int Nmax
, int * flag , int * flag
, FILE * file , FILE * file
, double x0) #ifdef NOCRAPMODE
, double x0
#endif
)
{ {
#ifndef NOCRAPMODE
double x0 = -6;
#endif
double result double result
, error; , error;
result = bisek(f, a, b, eps, Nmax, flag, file); result =
if(*flag & 0xff) #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); 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)) if(!(*flag & 0xff00))
{ {
fprintf(stderr, "WARNING: bisek flag is invalid.\n"); fprintf(stderr, "WARNING: bisek flag is invalid.\n");
@ -494,12 +561,15 @@ int write_error_bisek(double (*f)(double)
// FIXME: // FIXME:
// Shold we allow negative errors? It is mathematically incorrect but // Shold we allow negative errors? It is mathematically incorrect but
// more interesting. // more interesting.
// if(error < 0) #ifndef ALLOW_NEGATGIVE_ERRORS
// { if(error < 0)
// error *= -1; {
// } 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; double y, yd;
y = f(*x); y = f(*x);
yd = df(*x); yd = df(*x);
#ifdef DEBUG
fprintf(stderr, "f(%.4e) -> %.4e; df(%.4e) -> %.4e\n", *x, y, *x, yd); fprintf(stderr, "f(%.4e) -> %.4e; df(%.4e) -> %.4e\n", *x, y, *x, yd);
#endif
if(abs(y) < eps) if(abs(y) < eps)
{ {
return 0xe000; return 0xe000;
@ -522,12 +594,20 @@ int newton_one(double * x
} }
*x -= y / yd; *x -= y / yd;
#ifdef DEBUG
fprintf(stderr, "set new x: %.4e\n", *x); fprintf(stderr, "set new x: %.4e\n", *x);
#endif
return 0; return 0;
} }
double newton(double x0 double
#ifdef NOCRAPMODE
newton
#else
__inline_newton
#endif
(double x0
, double (*f)(double) , double (*f)(double)
, double (*df)(double) , double (*df)(double)
, double eps , 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 (*f)(double)
, double (*df)(double) , double (*df)(double)
, double eps , double eps
, int Nmax , int Nmax
, int * flag , int * flag
, FILE * file , FILE * file
, double x1) #ifdef NOCRAPMODE
, double x1
#endif
)
{ {
#ifndef NOCRAPMODE
double x1 = -6;
#endif
double result, error; 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) if(*flag & 0xff)
{ {
@ -584,12 +682,15 @@ double write_error_newton(double x0
// FIXME: // FIXME:
// Shold we allow negative errors? It is mathematically incorrect but // Shold we allow negative errors? It is mathematically incorrect but
// more interesting. // more interesting.
// if(error < 0) #ifndef ALLOW_NEGATGIVE_ERRORS
// { if(error < 0)
// error *= -1; {
// } 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 int newton_mult(int N