/* utility.c -- various root finding utility routines */ /* $Id: utility.c,v 1.9 1999/07/21 17:49:34 bjg Exp $ */ /* config headers */ #include /* standard headers */ #include #include #include #include #include /* gsl headers */ #include #include /* roots headers */ #include "roots.h" /* Validate arguments common to gsl_root_bisection and gsl_root_falsepos. Return GSL_SUCCESS if all arguments are okay, complain appropriately (i.e. call GSL_ERROR and return GSL_FAILURE) otherwise. */ int _gsl_root_validate_bfp_args (double *root, double (*f) (double), double *lower_bound, double *upper_bound, double epsrel, double epsabs, unsigned int max_iterations, double max_deltay) { /* Is the maximum delta-y too small? */ if (max_deltay < GSL_ROOT_MIN_MAX_DELTAY) GSL_ERROR ("maximum delta-y negative, zero, or too small", GSL_EBADTOL); /* Did the user give a lower bound that not less than the upper bound? */ if (*lower_bound >= *upper_bound) GSL_ERROR ("lower bound larger than upper_bound", GSL_EINVAL); /* The rest of the arguments are common. */ return _gsl_root_validate_args (root, f, lower_bound, upper_bound, epsrel, epsabs, max_iterations); } /* Validate arguments commond to gsl_root_secant and gsl_root_newtons. Return GSL_SUCCESS if all arguments are okay, complain appropriately (i.e. call GSL_ERROR and return GSL_FAILURE) otherwise. */ int _gsl_root_validate_sn_args (double *root, double (*f) (double), double *guess1, double *guess2, double epsrel, double epsabs, unsigned int max_iterations, double max_step_size) { /* Is the maximum step size ridiculous? */ if (max_step_size <= 0.0) GSL_ERROR ("maximum step size <= 0", GSL_EBADTOL); /* The rest of the arguments are common. */ return _gsl_root_validate_args (root, f, guess1, guess2, epsrel, epsabs, max_iterations); } /* Validate the arguments common to all four low level functions. Return GSL_SUCCESS if all of the following arguments hold true, call GSL_ERROR and return GSL_FAILURE otherwise. * No pointer arguments are null. * The maximum number of iterations is non-zero. * Relative and absolute error are non-negative. * The relative error is not too small. */ int _gsl_root_validate_args (double *root, double (*f) (double), double *where1, double *where2, double epsrel, double epsabs, unsigned int max_iterations) { /* Are any pointers null? */ if ((root == NULL) || (f == NULL) || (where1 == NULL) || (where2 == NULL)) GSL_ERROR ("pointer argument null", GSL_EINVAL); /* Did the user tell us to do no iterations? */ if (max_iterations == 0) GSL_ERROR ("maximum iterations 0", GSL_EINVAL); /* Did the user try to pawn a negative tolerance off on us? */ if (epsrel < 0.0 || epsabs < 0.0) GSL_ERROR ("relative or absolute tolerance negative", GSL_EBADTOL); /* Is the relative error too small? */ if (epsrel < GSL_DBL_EPSILON * GSL_ROOT_EPSILON_BUFFER) GSL_ERROR ("relative tolerance too small", GSL_EBADTOL); /* All is well. */ return GSL_SUCCESS; } /* Verify that the supplied interval is guaranteed by the Intermediate Value Theorem to contain a root and complain appropriately if it is not. (It might actually be a discontinuity, but we check for that elsewhere.) Return GSL_SUCCESS if all is well, otherwise, call GSL_ERROR and return GSL_FAILURE. */ int _gsl_root_ivt_guar (double (*f) (double), double lower_bound, double upper_bound) { double fl, fu; _BARF_FPCALL (f, lower_bound, fl); _BARF_FPCALL (f, upper_bound, fu); if (fl * fu > 0.0) { GSL_ERROR ("interval not guaranteed to contain a root", GSL_EINVAL); } else { return GSL_SUCCESS; } } /* Check if the user has the root but doesn't know it. If lower_bound or upper_bound is a root of f, or the interval [upper_bound, lower_bound] is within tolerance, return 1 and set *root appropriately. Otherwise, return 0. On error, call GSL_ERROR and return GSL_FAILURE. Only worry about max_deltay if it is greater than 0 (which implies that you should validate arguments _before_ calling this function). */ int _gsl_root_silly_user (double *root, double (*f) (double), double lower_bound, double upper_bound, double epsrel, double epsabs, double max_deltay) { double fl, fu; /* Is lower_bound the root? */ _BARF_FPCALL (f, lower_bound, fl); if (fl == 0.0) { *root = lower_bound; return 1; } /* Is upper_bound the root? */ _BARF_FPCALL (f, upper_bound, fu); if (fu == 0.0) { *root = upper_bound; return 1; } /* Are lower_bound and upper_bound within tolerance? */ _BARF_TOLS (lower_bound, upper_bound, 2 * epsrel, 2 * epsabs); if (max_deltay > 0.0) _BARF_DELTAY (fl, fu, max_deltay); if (_WITHIN_TOL (lower_bound, upper_bound, 2 * epsrel, 2 * epsabs)) { *root = (lower_bound + upper_bound) / 2.0; return 1; } /* No? Bummer. */ return 0; }