301 lines
5.8 KiB
C
301 lines
5.8 KiB
C
|
|
double lkl_rate_condition(double r, double * s, double * b, int size)
|
|
{
|
|
int i;
|
|
double res;
|
|
res = 0.;
|
|
for (i = 0; i < size; i++)
|
|
{
|
|
res += s[i]/(s[i]*r + b[i]);
|
|
};
|
|
return res;
|
|
}
|
|
|
|
double lkl_rate_condition_pkr(double r, double * pk, int size)
|
|
{
|
|
int i;
|
|
double res;
|
|
res = 0.;
|
|
for (i = 0; i < size; i++)
|
|
{
|
|
res += pk[i]/(pk[i]*r + 1.);
|
|
};
|
|
return res;
|
|
}
|
|
|
|
double get_lkl_pkr(double r, double *pk, int size)
|
|
{
|
|
int i;
|
|
double res;
|
|
res = 0.;
|
|
for (i = 0; i < size; i++)
|
|
{
|
|
res = res + log(pk[i]*r + 1.);
|
|
};
|
|
return res;
|
|
}
|
|
|
|
|
|
|
|
double r8_epsilon ( )
|
|
|
|
/****************************************************************************
|
|
|
|
Purpose:
|
|
|
|
R8_EPSILON returns the R8 roundoff unit.
|
|
|
|
Discussion:
|
|
|
|
The roundoff unit is a number R which is a power of 2 with the
|
|
property that, to the precision of the computer's arithmetic,
|
|
1 < 1 + R
|
|
but
|
|
1 = ( 1 + R / 2 )
|
|
|
|
Licensing:
|
|
|
|
This code is distributed under the GNU LGPL license.
|
|
|
|
Modified:
|
|
|
|
01 September 2012
|
|
|
|
Author:
|
|
|
|
John Burkardt
|
|
|
|
Parameters:
|
|
|
|
Output, double R8_EPSILON, the R8 round-off unit.
|
|
*/
|
|
{
|
|
const double value = 2.220446049250313E-016;
|
|
return value;
|
|
}
|
|
|
|
|
|
|
|
|
|
double brent (double rate, double exposure, double *sp, double *bp, int ssize)
|
|
//****************************************************************************
|
|
//
|
|
// Purpose:
|
|
//
|
|
// ZERO seeks the root of a function F(X) in an interval [A,B].
|
|
//
|
|
// Discussion:
|
|
//
|
|
// The interval [A,B] must be a change of sign interval for F.
|
|
// That is, F(A) and F(B) must be of opposite signs. Then
|
|
// assuming that F is continuous implies the existence of at least
|
|
// one value C between A and B for which F(C) = 0.
|
|
//
|
|
// The location of the zero is determined to within an accuracy
|
|
// of 6 * MACHEPS * abs ( C ) + 2 * T.
|
|
//
|
|
// Thanks to Thomas Secretin for pointing out a transcription error in the
|
|
// setting of the value of P, 11 February 2013.
|
|
//
|
|
// Licensing:
|
|
//
|
|
// This code is distributed under the GNU LGPL license.
|
|
//
|
|
// Modified:
|
|
//
|
|
// 11 February 2013
|
|
//
|
|
// Author:
|
|
//
|
|
// Original FORTRAN77 version by Richard Brent.
|
|
// C++ version by John Burkardt.
|
|
//
|
|
// Reference:
|
|
//
|
|
// Richard Brent,
|
|
// Algorithms for Minimization Without Derivatives,
|
|
// Dover, 2002,
|
|
// ISBN: 0-486-41998-3,
|
|
// LC: QA402.5.B74.
|
|
//
|
|
// Parameters:
|
|
//
|
|
// Input, double A, B, the endpoints of the change of sign interval.
|
|
//
|
|
// Input, double T, a positive error tolerance.
|
|
//
|
|
// Input, func_base& F, the name of a user-supplied c++ functor
|
|
// whose zero is being sought. The input and output
|
|
// of F() are of type double.
|
|
//
|
|
// Output, double ZERO, the estimated value of a zero of
|
|
// the function F.
|
|
//
|
|
{
|
|
double a, b, t;
|
|
double c;
|
|
double d;
|
|
double e;
|
|
double fa;
|
|
double fb;
|
|
double fc;
|
|
double m;
|
|
double macheps;
|
|
double p;
|
|
double q;
|
|
double r;
|
|
double s;
|
|
double sa;
|
|
double sb;
|
|
double tol;
|
|
int i = 0;
|
|
//
|
|
// Make local copies of A and B.
|
|
//
|
|
a = 0.;
|
|
b = ssize/exposure;
|
|
t = 1e-7;
|
|
|
|
sa = a;
|
|
sb = b;
|
|
fa = lkl_rate_condition(sa, sp, bp, ssize) - exposure;
|
|
fb = lkl_rate_condition(sb, sp, bp, ssize) - exposure;
|
|
|
|
c = sa;
|
|
fc = fa;
|
|
e = sb - sa;
|
|
d = e;
|
|
|
|
macheps = r8_epsilon ( );
|
|
|
|
for ( ; ; )
|
|
{
|
|
i += 1;
|
|
if ( fabs ( fc ) < fabs ( fb ) )
|
|
{
|
|
sa = sb;
|
|
sb = c;
|
|
c = sa;
|
|
fa = fb;
|
|
fb = fc;
|
|
fc = fa;
|
|
}
|
|
|
|
tol = 2.0 * macheps * fabs ( sb ) + t;
|
|
m = 0.5 * ( c - sb );
|
|
|
|
if ( fabs ( m ) <= tol || fb == 0.0 )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if ( fabs ( e ) < tol || fabs ( fa ) <= fabs ( fb ) )
|
|
{
|
|
e = m;
|
|
d = e;
|
|
}
|
|
else
|
|
{
|
|
s = fb / fa;
|
|
|
|
if ( sa == c )
|
|
{
|
|
p = 2.0 * m * s;
|
|
q = 1.0 - s;
|
|
}
|
|
else
|
|
{
|
|
q = fa / fc;
|
|
r = fb / fc;
|
|
p = s * ( 2.0 * m * q * ( q - r ) - ( sb - sa ) * ( r - 1.0 ) );
|
|
q = ( q - 1.0 ) * ( r - 1.0 ) * ( s - 1.0 );
|
|
}
|
|
|
|
if ( 0.0 < p )
|
|
{
|
|
q = - q;
|
|
}
|
|
else
|
|
{
|
|
p = - p;
|
|
}
|
|
|
|
s = e;
|
|
e = d;
|
|
|
|
if ( 2.0 * p < 3.0 * m * q - fabs ( tol * q ) &&
|
|
p < fabs ( 0.5 * s * q ) )
|
|
{
|
|
d = p / q;
|
|
}
|
|
else
|
|
{
|
|
e = m;
|
|
d = e;
|
|
}
|
|
}
|
|
sa = sb;
|
|
fa = fb;
|
|
|
|
if ( tol < fabs ( d ) )
|
|
{
|
|
sb = sb + d;
|
|
}
|
|
else if ( 0.0 < m )
|
|
{
|
|
sb = sb + tol;
|
|
}
|
|
else
|
|
{
|
|
sb = sb - tol;
|
|
}
|
|
|
|
fb = lkl_rate_condition(sb, sp, bp, ssize) - exposure;
|
|
|
|
if ( ( 0.0 < fb && 0.0 < fc ) || ( fb <= 0.0 && fc <= 0.0 ) )
|
|
{
|
|
c = sa;
|
|
fc = fa;
|
|
e = sb - sa;
|
|
d = e;
|
|
}
|
|
}
|
|
/*printf("it counter %d\n", i);*/
|
|
return sb;
|
|
}
|
|
|
|
double get_phc_solution(double r, double e, double *s, double *b, int size)
|
|
{
|
|
int i;
|
|
double rnew = r;
|
|
for (i = 0; i < 200; i++)
|
|
{
|
|
rnew = lkl_rate_condition(r, s, b, size)*r/e;
|
|
if ((fabs(rnew - r) < 1e-7) | (rnew*e < 1.)) break;
|
|
r = rnew;
|
|
};
|
|
/*printf("it counter %d\n", i);*/
|
|
|
|
//printf("%d %e %e\n", size, s[0], r);
|
|
return rnew;
|
|
}
|
|
|
|
double get_phc_solution_pkr(double r, double e, double *pk, int size)
|
|
{
|
|
int i;
|
|
double rnew = r;
|
|
for (i = 0; i < 200; i++)
|
|
{
|
|
rnew = lkl_rate_condition_pkr(r, pk, size)*r/e;
|
|
//printf("rnew %d %f\n", i, rnew*e);
|
|
if ((fabs(rnew - r) < 1e-7) | (rnew*e < 0.001)) break;
|
|
//if ((fabs(rnew - r) < 1e-7) | (rnew*e < 1.)) break;
|
|
r = rnew;
|
|
};
|
|
/*printf("it counter %d\n", i);*/
|
|
|
|
//printf("%d %e %e\n", size, s[0], r);
|
|
return rnew;
|
|
}
|
|
|