/** * @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); }