Added script front-end for primer-design code
[htsworkflow.git] / htswanalysis / MACS / lib / gsl / gsl-1.11 / roots / falsepos.c
1 /* roots/falsepos.c
2  * 
3  * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Reid Priedhorsky, Brian Gough
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or (at
8  * your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19
20 /* falsepos.c -- falsepos root finding algorithm 
21
22    The false position algorithm uses bracketing by linear interpolation.
23
24    If a linear interpolation step would decrease the size of the
25    bracket by less than a bisection step would then the algorithm
26    takes a bisection step instead.
27    
28    The last linear interpolation estimate of the root is used. If a
29    bisection step causes it to fall outside the brackets then it is
30    replaced by the bisection estimate (x_upper + x_lower)/2.
31
32 */
33
34 #include <config.h>
35
36 #include <stddef.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <math.h>
40 #include <float.h>
41
42 #include <gsl/gsl_math.h>
43 #include <gsl/gsl_errno.h>
44 #include <gsl/gsl_roots.h>
45
46 #include "roots.h"
47
48 typedef struct
49   {
50     double f_lower, f_upper;
51   }
52 falsepos_state_t;
53
54 static int falsepos_init (void * vstate, gsl_function * f, double * root, double x_lower, double x_upper);
55 static int falsepos_iterate (void * vstate, gsl_function * f, double * root, double * x_lower, double * x_upper);
56
57 static int
58 falsepos_init (void * vstate, gsl_function * f, double * root, double x_lower, double x_upper)
59 {
60   falsepos_state_t * state = (falsepos_state_t *) vstate;
61
62   double f_lower, f_upper ;
63
64   *root = 0.5 * (x_lower + x_upper);
65
66   SAFE_FUNC_CALL (f, x_lower, &f_lower);
67   SAFE_FUNC_CALL (f, x_upper, &f_upper);
68   
69   state->f_lower = f_lower;
70   state->f_upper = f_upper;
71
72   if ((f_lower < 0.0 && f_upper < 0.0) || (f_lower > 0.0 && f_upper > 0.0))
73     {
74       GSL_ERROR ("endpoints do not straddle y=0", GSL_EINVAL);
75     }
76
77   return GSL_SUCCESS;
78
79 }
80
81 static int
82 falsepos_iterate (void * vstate, gsl_function * f, double * root, double * x_lower, double * x_upper)
83 {
84   falsepos_state_t * state = (falsepos_state_t *) vstate;
85
86   double x_linear, f_linear;
87   double x_bisect, f_bisect;
88
89   double x_left = *x_lower ;
90   double x_right = *x_upper ;
91
92   double f_lower = state->f_lower; 
93   double f_upper = state->f_upper;
94
95   double w ;
96
97   if (f_lower == 0.0)
98     {
99       *root = x_left ;
100       *x_upper = x_left;
101       return GSL_SUCCESS;
102     }
103   
104   if (f_upper == 0.0)
105     {
106       *root = x_right ;
107       *x_lower = x_right;
108       return GSL_SUCCESS;
109     }
110       
111   /* Draw a line between f(*lower_bound) and f(*upper_bound) and
112      note where it crosses the X axis; that's where we will
113      split the interval. */
114   
115   x_linear = x_right - (f_upper * (x_left - x_right) / (f_lower - f_upper));
116
117   SAFE_FUNC_CALL (f, x_linear, &f_linear);
118       
119   if (f_linear == 0.0)
120     {
121       *root = x_linear;
122       *x_lower = x_linear;
123       *x_upper = x_linear;
124       return GSL_SUCCESS;
125     }
126       
127   /* Discard the half of the interval which doesn't contain the root. */
128   
129   if ((f_lower > 0.0 && f_linear < 0.0) || (f_lower < 0.0 && f_linear > 0.0))
130     {
131       *root = x_linear ;
132       *x_upper = x_linear;
133       state->f_upper = f_linear;
134       w = x_linear - x_left ;
135     }
136   else
137     {
138       *root = x_linear ;
139       *x_lower = x_linear;
140       state->f_lower = f_linear;
141       w = x_right - x_linear;
142     }
143
144   if (w < 0.5 * (x_right - x_left)) 
145     {
146       return GSL_SUCCESS ;
147     }
148
149   x_bisect = 0.5 * (x_left + x_right);
150
151   SAFE_FUNC_CALL (f, x_bisect, &f_bisect);
152
153   if ((f_lower > 0.0 && f_bisect < 0.0) || (f_lower < 0.0 && f_bisect > 0.0))
154     {
155       *x_upper = x_bisect;
156       state->f_upper = f_bisect;
157       if (*root > x_bisect)
158         *root = 0.5 * (x_left + x_bisect) ;
159     }
160   else
161     {
162       *x_lower = x_bisect;
163       state->f_lower = f_bisect;
164       if (*root < x_bisect)
165         *root = 0.5 * (x_bisect + x_right) ;
166     }
167
168   return GSL_SUCCESS;
169 }
170
171
172 static const gsl_root_fsolver_type falsepos_type =
173 {"falsepos",                            /* name */
174  sizeof (falsepos_state_t),
175  &falsepos_init,
176  &falsepos_iterate};
177
178 const gsl_root_fsolver_type  * gsl_root_fsolver_falsepos = &falsepos_type;