/**
* @file addlog.c
*
*
* @brief 対数値の高速和算関数
*
*
*
* @brief Rapid addition of log values
*
*
* @author Akinobu LEE
* @date Thu Feb 17 13:23:50 2005
*
* $Revision: 1.4 $
*
*/
/*
* Copyright (c) 1991-2012 Kawahara Lab., Kyoto University
* Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
* Copyright (c) 2005-2012 Julius project team, Nagoya Institute of Technology
* All rights reserved
*/
#include
#include
#define TBLSIZE 500000 ///< Table size (precision depends on this)
#define VRANGE 15 ///< Must be larger than -LOG_ADDMIN
#define TMAG 33333.3333 ///< TBLSIZE / VRANGE
static LOGPROB tbl[TBLSIZE]; ///< Table of @f$\log (1+e^x)@f$
static boolean built_tbl = FALSE;///< TRUE after tbl has built
/**
* @brief Generate a value tables of @f$\log (1+e^x)@f$.
*
* @f$x@f$ is from 0 to (- VRANGE), and table size is TBLSIZE.
*
*/
void
make_log_tbl()
{
LOGPROB f;
int i;
if (built_tbl == FALSE) {
jlog("Stat: addlog: generating addlog table (size = %d kB)\n", (TBLSIZE * sizeof(LOGPROB)) / 1024);
for (i=0;i TBLSIZE - 10) j_printf("%f: %d(%f)\n", f, i, tbl[i]);*/
}
jlog("Stat: addlog: addlog table generated\n");
built_tbl = TRUE;
}
}
/**
* Rapid computation of @f$\log (e^x + e^y)@f$.
*
* If value differs more than LOG_ADDMIN, the larger value will be returned
* as is.
*
* @param x [in] log value
* @param y [in] log value
*
* @return result value.
*/
LOGPROB
addlog(LOGPROB x, LOGPROB y)
{
/* return(log(exp(x)+exp(y))) */
LOGPROB tmp;
unsigned int idx;
if (x < y) {
if ((tmp = x - y) < LOG_ADDMIN) return y;
else {
idx = (unsigned int)((- tmp) * TMAG + 0.5);
/* jlog("%f == %f\n",tbl[idx],log(1 + exp(tmp))); */
return (y + tbl[idx]);
}
} else {
if ((tmp = y - x) < LOG_ADDMIN) return x;
else {
idx =(unsigned int)((- tmp) * TMAG + 0.5);
/* jlog("%f == %f\n",tbl[idx],log(1 + exp(tmp))); */
return (x + tbl[idx]);
}
}
}
/**
* Rapid computation of @f$\log (\sum_{i=1}^N e^{x_i})@f$.
*
* @param a [in] array of log values
* @param n [in] length of above
*
* @return the result value.
*/
LOGPROB
addlog_array(LOGPROB *a, int n)
{
LOGPROB tmp;
LOGPROB x,y;
unsigned int idx;
y = LOG_ZERO;
for(n--; n >= 0; n--) {
x = a[n];
if (x > y) {
tmp = x; x = y; y = tmp;
}
/* always y >= x */
if ((tmp = x - y) < LOG_ADDMIN) continue;
else {
idx = (unsigned int)((- tmp) * TMAG + 0.5);
y += tbl[idx];
}
}
return(y);
}