⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 specfun.cc

📁 The library is a C++/Python implementation of the variational building block framework introduced in
💻 CC
📖 第 1 页 / 共 2 页
字号:
//// This file is a part of the Bayes Blocks library//// Copyright (C) 2001-2006 Markus Harva, Antti Honkela, Alexander// Ilin, Tapani Raiko, Harri Valpola and Tomas 謘tman.//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2, or (at your option)// any later version.//// This program 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 General Public License (included in file License.txt in the// program package) for more details.///* * ==================================================== * Portions Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice  * is preserved. * ==================================================== *///// $Id: SpecFun.cc 5 2006-10-26 09:44:54Z ah $#include <math.h>#include "config.h"#include "SpecFun.h"const double DIGAMMA_S = 1e-5;const double DIGAMMA_C = 8.5;const double DIGAMMA_S3 = 1.0/12;const double DIGAMMA_S4 = 1.0/120;const double DIGAMMA_S5 = 1.0/252;const double DIGAMMA_D1 = -0.5772156649015328605195174;#ifndef M_PI#define M_PI 4*atan((double)1.0)#endif  // not defined M_PIdouble DiGamma(double x) {  double y = 0.0;  double r = 0.0;  double xn = x;  if (xn < 0) {    throw ValueException();  }  if (xn <= DIGAMMA_S)    y = DIGAMMA_D1 - 1.0 / xn;  else {    while (xn < DIGAMMA_C) {      y = y - 1.0 / xn;      xn = xn + 1;    }    r = 1.0 / xn;    y = y + log(xn) - .5 * r;    r = r * r;    y = y - r * (DIGAMMA_S3 - r * (DIGAMMA_S4 - r*DIGAMMA_S5));  }  return y;}double NormPdf(double x, double m, double v) {  return 1 / sqrt(2*M_PI*v) * exp(-Sqr(m - x) / (2 * v));}#ifdef BAD_MATHLIB/* @(#)er_lgamma.c 5.1 93/09/24 *//* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice  * is preserved. * ==================================================== */// static char rcsid[] = "NetBSD: e_lgamma_r.c,v 1.7 1995/05/10 20:45:42 jtc Exp";/* __ieee754_lgamma_r(x, signgamp) * Reentrant version of the logarithm of the Gamma function  * with user provide pointer for the sign of Gamma(x).  * * Method: *   1. Argument Reduction for 0 < x <= 8 * 	Since gamma(1+s)=s*gamma(s), for x in [0,8], we may  * 	reduce x to a number in [1.5,2.5] by * 		lgamma(1+s) = log(s) + lgamma(s) *	for example, *		lgamma(7.3) = log(6.3) + lgamma(6.3) *			    = log(6.3*5.3) + lgamma(5.3) *			    = log(6.3*5.3*4.3*3.3*2.3) + lgamma(2.3) *   2. Polynomial approximation of lgamma around its *	minimun ymin=1.461632144968362245 to maintain monotonicity. *	On [ymin-0.23, ymin+0.27] (i.e., [1.23164,1.73163]), use *		Let z = x-ymin; *		lgamma(x) = -1.214862905358496078218 + z^2*poly(z) *	where *		poly(z) is a 14 degree polynomial. *   2. Rational approximation in the primary interval [2,3] *	We use the following approximation: *		s = x-2.0; *		lgamma(x) = 0.5*s + s*P(s)/Q(s) *	with accuracy *		|P/Q - (lgamma(x)-0.5s)| < 2**-61.71 *	Our algorithms are based on the following observation * *                             zeta(2)-1    2    zeta(3)-1    3 * lgamma(2+s) = s*(1-Euler) + --------- * s  -  --------- * s  + ... *                                 2                 3 * *	where Euler = 0.5771... is the Euler constant, which is very *	close to 0.5. * *   3. For x>=8, we have *	lgamma(x)~(x-0.5)log(x)-x+0.5*log(2pi)+1/(12x)-1/(360x**3)+.... *	(better formula: *	   lgamma(x)~(x-0.5)*(log(x)-1)-.5*(log(2pi)-1) + ...) *	Let z = 1/x, then we approximation *		f(z) = lgamma(x) - (x-0.5)(log(x)-1) *	by *	  			    3       5             11 *		w = w0 + w1*z + w2*z  + w3*z  + ... + w6*z *	where  *		|w - f(z)| < 2**-58.74 *		 *   4. For negative x, since (G is gamma function) *		-x*G(-x)*G(x) = pi/sin(pi*x), * 	we have * 		G(x) = pi/(sin(pi*x)*(-x)*G(-x)) *	since G(-x) is positive, sign(G(x)) = sign(sin(pi*x)) for x<0 *	Hence, for x<0, signgam = sign(sin(pi*x)) and  *		lgamma(x) = log(|Gamma(x)|) *			  = log(pi/(|x*sin(pi*x)|)) - lgamma(-x); *	Note: one should avoid compute pi*(-x) directly in the  *	      computation of sin(pi*(-x)). *		 *   5. Special Cases *		lgamma(2+s) ~ s*(1-Euler) for tiny s *		lgamma(1)=lgamma(2)=0 *		lgamma(x) ~ -log(x) for tiny x *		lgamma(0) = lgamma(inf) = inf *	 	lgamma(-integer) = +-inf *	 */// ASSUME 32 bit intstypedef int int32_t;typedef unsigned int u_int32_t;// ASSUME little endian byte ordertypedef union {  double value;  struct   {    u_int32_t lsw;    u_int32_t msw;  } parts;} ieee_double_shape_type;#define EXTRACT_WORDS(ix0,ix1,d)				\do {								\  ieee_double_shape_type ew_u;					\  ew_u.value = (d);						\  (ix0) = ew_u.parts.msw;					\  (ix1) = ew_u.parts.lsw;					\} while (0)#define GET_HIGH_WORD(i,d)					\do {								\  ieee_double_shape_type gh_u;					\  gh_u.value = (d);						\  (i) = gh_u.parts.msw;						\} while (0)#define GET_LOW_WORD(i,d)					\do {								\  ieee_double_shape_type gl_u;					\  gl_u.value = (d);						\  (i) = gl_u.parts.lsw;						\} while (0)#define INSERT_WORDS(d,ix0,ix1)					\do {								\  ieee_double_shape_type iw_u;					\  iw_u.parts.msw = (ix0);					\  iw_u.parts.lsw = (ix1);					\  (d) = iw_u.value;						\} while (0)#define SET_LOW_WORD(d,v)					\do {								\  ieee_double_shape_type sl_u;					\  sl_u.value = (d);						\  sl_u.parts.lsw = (v);						\  (d) = sl_u.value;						\} while (0)#define __ieee754_log(x) log(x)#define __ieee754_exp(x) exp(x)static const double two52=  4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */half=  5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */one =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */pi  =  3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */a0  =  7.72156649015328655494e-02, /* 0x3FB3C467, 0xE37DB0C8 */a1  =  3.22467033424113591611e-01, /* 0x3FD4A34C, 0xC4A60FAD */a2  =  6.73523010531292681824e-02, /* 0x3FB13E00, 0x1A5562A7 */a3  =  2.05808084325167332806e-02, /* 0x3F951322, 0xAC92547B */a4  =  7.38555086081402883957e-03, /* 0x3F7E404F, 0xB68FEFE8 */a5  =  2.89051383673415629091e-03, /* 0x3F67ADD8, 0xCCB7926B */a6  =  1.19270763183362067845e-03, /* 0x3F538A94, 0x116F3F5D */a7  =  5.10069792153511336608e-04, /* 0x3F40B6C6, 0x89B99C00 */a8  =  2.20862790713908385557e-04, /* 0x3F2CF2EC, 0xED10E54D */a9  =  1.08011567247583939954e-04, /* 0x3F1C5088, 0x987DFB07 */a10 =  2.52144565451257326939e-05, /* 0x3EFA7074, 0x428CFA52 */a11 =  4.48640949618915160150e-05, /* 0x3F07858E, 0x90A45837 */tc  =  1.46163214496836224576e+00, /* 0x3FF762D8, 0x6356BE3F */tf  = -1.21486290535849611461e-01, /* 0xBFBF19B9, 0xBCC38A42 *//* tt = -(tail of tf) */tt  = -3.63867699703950536541e-18, /* 0xBC50C7CA, 0xA48A971F */t0  =  4.83836122723810047042e-01, /* 0x3FDEF72B, 0xC8EE38A2 */t1  = -1.47587722994593911752e-01, /* 0xBFC2E427, 0x8DC6C509 */t2  =  6.46249402391333854778e-02, /* 0x3FB08B42, 0x94D5419B */t3  = -3.27885410759859649565e-02, /* 0xBFA0C9A8, 0xDF35B713 */t4  =  1.79706750811820387126e-02, /* 0x3F9266E7, 0x970AF9EC */t5  = -1.03142241298341437450e-02, /* 0xBF851F9F, 0xBA91EC6A */t6  =  6.10053870246291332635e-03, /* 0x3F78FCE0, 0xE370E344 */t7  = -3.68452016781138256760e-03, /* 0xBF6E2EFF, 0xB3E914D7 */t8  =  2.25964780900612472250e-03, /* 0x3F6282D3, 0x2E15C915 */t9  = -1.40346469989232843813e-03, /* 0xBF56FE8E, 0xBF2D1AF1 */t10 =  8.81081882437654011382e-04, /* 0x3F4CDF0C, 0xEF61A8E9 */t11 = -5.38595305356740546715e-04, /* 0xBF41A610, 0x9C73E0EC */t12 =  3.15632070903625950361e-04, /* 0x3F34AF6D, 0x6C0EBBF7 */t13 = -3.12754168375120860518e-04, /* 0xBF347F24, 0xECC38C38 */t14 =  3.35529192635519073543e-04, /* 0x3F35FD3E, 0xE8C2D3F4 */u0  = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */u1  =  6.32827064025093366517e-01, /* 0x3FE4401E, 0x8B005DFF */u2  =  1.45492250137234768737e+00, /* 0x3FF7475C, 0xD119BD6F */u3  =  9.77717527963372745603e-01, /* 0x3FEF4976, 0x44EA8450 */u4  =  2.28963728064692451092e-01, /* 0x3FCD4EAE, 0xF6010924 */u5  =  1.33810918536787660377e-02, /* 0x3F8B678B, 0xBF2BAB09 */v1  =  2.45597793713041134822e+00, /* 0x4003A5D7, 0xC2BD619C */v2  =  2.12848976379893395361e+00, /* 0x40010725, 0xA42B18F5 */v3  =  7.69285150456672783825e-01, /* 0x3FE89DFB, 0xE45050AF */v4  =  1.04222645593369134254e-01, /* 0x3FBAAE55, 0xD6537C88 */v5  =  3.21709242282423911810e-03, /* 0x3F6A5ABB, 0x57D0CF61 */s0  = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */s1  =  2.14982415960608852501e-01, /* 0x3FCB848B, 0x36E20878 */s2  =  3.25778796408930981787e-01, /* 0x3FD4D98F, 0x4F139F59 */s3  =  1.46350472652464452805e-01, /* 0x3FC2BB9C, 0xBEE5F2F7 */s4  =  2.66422703033638609560e-02, /* 0x3F9B481C, 0x7E939961 */s5  =  1.84028451407337715652e-03, /* 0x3F5E26B6, 0x7368F239 */s6  =  3.19475326584100867617e-05, /* 0x3F00BFEC, 0xDD17E945 */r1  =  1.39200533467621045958e+00, /* 0x3FF645A7, 0x62C4AB74 */r2  =  7.21935547567138069525e-01, /* 0x3FE71A18, 0x93D3DCDC */r3  =  1.71933865632803078993e-01, /* 0x3FC601ED, 0xCCFBDF27 */r4  =  1.86459191715652901344e-02, /* 0x3F9317EA, 0x742ED475 */r5  =  7.77942496381893596434e-04, /* 0x3F497DDA, 0xCA41A95B */r6  =  7.32668430744625636189e-06, /* 0x3EDEBAF7, 0xA5B38140 */w0  =  4.18938533204672725052e-01, /* 0x3FDACFE3, 0x90C97D69 */w1  =  8.33333333333329678849e-02, /* 0x3FB55555, 0x5555553B */w2  = -2.77777777728775536470e-03, /* 0xBF66C16C, 0x16B02E5C */w3  =  7.93650558643019558500e-04, /* 0x3F4A019F, 0x98CF38B6 */w4  = -5.95187557450339963135e-04, /* 0xBF4380CB, 0x8C0FE741 */w5  =  8.36339918996282139126e-04, /* 0x3F4B67BA, 0x4CDAD5D1 */w6  = -1.63092934096575273989e-03; /* 0xBF5AB89D, 0x0B9E43E4 */static const double zero=  0.00000000000000000000e+00;static const double S1  = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */S2  =  8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */S3  = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */S4  =  2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */S5  = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */S6  =  1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */double__kernel_sin(double x, double y, int iy){	double z,r,v;	int32_t ix;	GET_HIGH_WORD(ix,x);	ix &= 0x7fffffff;			/* high word of x */	if(ix<0x3e400000)			/* |x| < 2**-27 */	   {if((int)x==0) return x;}		/* generate inexact */	z	=  x*x;	v	=  z*x;	r	=  S2+z*(S3+z*(S4+z*(S5+z*S6)));	if(iy==0) return x+v*(S1+z*r);	else      return x-((z*(half*y-v*r)-y)-v*S1);}static const double C1  =  4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */C2  = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */C3  =  2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */C4  = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */C5  =  2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */C6  = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */double__kernel_cos(double x, double y){	double a,hz,z,r,qx;	int32_t ix;	GET_HIGH_WORD(ix,x);	ix &= 0x7fffffff;			/* ix = |x|'s high word*/	if(ix<0x3e400000) {			/* if x < 2**27 */	    if(((int)x)==0) return one;		/* generate inexact */	}	z  = x*x;	r  = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6)))));	if(ix < 0x3FD33333) 			/* if |x| < 0.3 */ 	    return one - (0.5*z - (z*r - x*y));	else {	    if(ix > 0x3fe90000) {		/* x > 0.78125 */		qx = 0.28125;	    } else {	        INSERT_WORDS(qx,ix-0x00200000,0);	/* x/4 */	    }	    hz = 0.5*z-qx;	    a  = one-qx;	    return a - (hz - (z*r-x*y));	}}static doublesin_pi(double x){	double y,z;	int n,ix;	GET_HIGH_WORD(ix,x);	ix &= 0x7fffffff;	if(ix<0x3fd00000) return __kernel_sin(pi*x,zero,0);	y = -x;		/* x is assume negative */    /*     * argument reduction, make sure inexact flag not raised if input     * is an integer     */	z = floor(y);	if(z!=y) {				/* inexact anyway */	    y  *= 0.5;	    y   = 2.0*(y - floor(y));		/* y = |x| mod 2.0 */	    n   = (int) (y*4.0);	} else {            if(ix>=0x43400000) {                y = zero; n = 0;                 /* y must be even */            } else {                if(ix<0x43300000) z = y+two52;	/* exact */		GET_LOW_WORD(n,z);		n &= 1;                y  = n;                n<<= 2;            }        }	switch (n) {	    case 0:   y =  __kernel_sin(pi*y,zero,0); break;	    case 1:   	    case 2:   y =  __kernel_cos(pi*(0.5-y),zero); break;	    case 3:  	    case 4:   y =  __kernel_sin(pi*(one-y),zero,0); break;	    case 5:	    case 6:   y = -__kernel_cos(pi*(y-1.5),zero); break;	    default:  y =  __kernel_sin(pi*(y-2.0),zero,0); break;	    }	return -y;}doubleLogGamma(double x)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -