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
*
*
* 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