/*******************************************************************************
*
* This file is part of the General Hidden Markov Model Library,
* GHMM version __VERSION__, see http://ghmm.org
*
* Filename: ghmm/ghmm/gauss_tail.c
* Authors: Bernhard Knab
*
* Copyright (C) 1998-2004 Alexander Schliep
* Copyright (C) 1998-2001 ZAIK/ZPR, Universitaet zu Koeln
* Copyright (C) 2002-2004 Max-Planck-Institut fuer Molekulare Genetik,
* Berlin
*
* Contact: schliep@ghmm.org
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* This file is version $Revision: 1453 $
* from $Date: 2005-11-20 08:33:04 -0500 (Sun, 20 Nov 2005) $
* last change by $Author: grunau $.
*
*******************************************************************************/
#ifdef HAVE_CONFIG_H
# include "../config.h"
#endif
#include <float.h>
#include <math.h>
#include "ghmm.h"
#include "randvar.h"
#include "ghmm_internals.h"
/*============================================================================*/
double ighmm_gtail_pmue (double mue, double A, double B, double eps)
{
double feps, u, Atil, Btil;
Atil = A + eps;
Btil = B + eps * A;
u = Btil - mue * Atil;
/* if (u < EPS_U) u = (double)EPS_U; DANGEROUS: would fudge the function value! */
if (u <= DBL_MIN)
return (mue - A);
feps = ighmm_rand_normal_density_trunc (-eps, mue, u, -eps);
return (A - mue - u * feps);
}
/*============================================================================*/
/* To avoid numerical ocillation:
Interpolate p(\mu) between 2 sampling points for PHI
NOTA BENE: This Version is very expensive and exact.
*/
double ighmm_gtail_pmue_interpol (double mue, double A, double B, double eps)
{
double u, Atil, Btil, z, z1, z2, m1, m2, u1, u2, p1, p2, pz;
int i1, i2;
Atil = A + eps;
Btil = B + eps * A;
u = Btil - mue * Atil;
/*if (u < EPS_U) u = (double)EPS_U; DANGEROUS: would fudge the function value! */
if (u <= DBL_MIN)
return (mue - A);
/* Compute like normally where mue positiv. */
if (mue >= 0.0)
return (A - mue - u * ighmm_rand_normal_density_trunc (-eps, mue, u, -eps));
/* Otherwise: Interpolate the function itself between 2 sampling points. */
z = (eps + mue) / sqrt (u);
i1 = (int) (fabs (z) * ighmm_rand_get_xfaktphi ());
if (i1 >= ighmm_rand_get_philen () - 1) {
i1 = (int) ighmm_rand_get_philen () - 1;
i2 = i1;
}
else
i2 = i1 + 1;
z1 = i1 / ighmm_rand_get_xfaktphi ();
z2 = i2 / ighmm_rand_get_xfaktphi ();
m1 = -z1 * sqrt (Btil + eps * Atil + Atil * Atil * z1 * z1 * 0.25)
-(eps + Atil * z1 * z1 * 0.5);
m2 = -z2 * sqrt (Btil + eps * Atil + Atil * Atil * z2 * z2 * 0.25)
-(eps + Atil * z2 * z2 * 0.5);
u1 = Btil - m1 * Atil;
u2 = Btil - m2 * Atil;
p1 = A - m1 - u1 * ighmm_rand_normal_density_trunc (-eps, m1, u1, -eps);
p2 = A - m1 - u1 * ighmm_rand_normal_density_trunc (-eps, m2, u2, -eps);
if (i1 >= ighmm_rand_get_philen () - 1)
pz = p1;
else {
pz = p1 + (fabs (z) - i1 * ighmm_rand_get_xstepphi ())
*(p2 - p1) / ighmm_rand_get_xstepphi ();
/* pz = p1; */
}
return (pz);
}
/*============================================================================*/
double ighmm_gtail_pmue_umin (double mue, double A, double B, double eps)
{
double feps, u;
u = GHMM_EPS_U;
feps = ighmm_rand_normal_density_trunc (-eps, mue, u, -eps);
return (A - mue - u * feps);
}