| 1 | From beerli@genetics.washington.edu Tue Mar 13 15:47:38 2001 |
|---|
| 2 | Received: from darwin.genetics.washington.edu (darwin.genetics.washington.edu [128.95.144.42]) |
|---|
| 3 | by evolution.genetics.washington.edu (8.9.3/8.9.3) with ESMTP id PAA17484 |
|---|
| 4 | for <joe@evolution.genetics.washington.edu>; Tue, 13 Mar 2001 15:47:38 -0800 (PST) |
|---|
| 5 | Received: from localhost (beerli@localhost) |
|---|
| 6 | by darwin.genetics.washington.edu (8.9.3/8.9.3) with ESMTP id PAA10268 |
|---|
| 7 | for <joe@evolution.genetics.washington.edu>; Tue, 13 Mar 2001 15:47:38 -0800 |
|---|
| 8 | X-Authentication-Warning: darwin.genetics.washington.edu: beerli owned process doing -bs |
|---|
| 9 | Date: Tue, 13 Mar 2001 15:47:38 -0800 (PST) |
|---|
| 10 | From: Peter Beerli <beerli@genetics.washington.edu> |
|---|
| 11 | To: Felsenstein Joe <joe@evolution.genetics.washington.edu> |
|---|
| 12 | Subject: hermite a fini laguerre |
|---|
| 13 | Message-ID: <Pine.LNX.4.30.0103131538570.8726-100000@darwin.genetics.washington.edu> |
|---|
| 14 | MIME-Version: 1.0 |
|---|
| 15 | Content-Type: TEXT/PLAIN; charset=US-ASCII |
|---|
| 16 | Status: RO |
|---|
| 17 | |
|---|
| 18 | I have two files included below, |
|---|
| 19 | and you certainly need to adapt them for phylip. |
|---|
| 20 | |
|---|
| 21 | the hermit stuff contains the word hermite |
|---|
| 22 | and its main function is |
|---|
| 23 | |
|---|
| 24 | inthermitcat() |
|---|
| 25 | |
|---|
| 26 | |
|---|
| 27 | I ripped the initgammacat into a simple driver. |
|---|
| 28 | laguerre.c contains a simple test program that |
|---|
| 29 | can be compiled using |
|---|
| 30 | gcc -DLAGUERRE_TEST laguerre.c -o laguerretest -lm |
|---|
| 31 | |
|---|
| 32 | Peter |
|---|
| 33 | -- |
|---|
| 34 | |
|---|
| 35 | /* laguerre.h */ |
|---|
| 36 | #ifndef _LAGUERRE_H_ |
|---|
| 37 | #define _LAGUERRE_H_ |
|---|
| 38 | /*------------------------------------------------------ |
|---|
| 39 | Maximum likelihood estimation |
|---|
| 40 | of migration rate and effectice population size |
|---|
| 41 | using a Metropolis-Hastings Monte Carlo algorithm |
|---|
| 42 | ------------------------------------------------------- |
|---|
| 43 | Laguerre integration R O U T I N E S |
|---|
| 44 | |
|---|
| 45 | Peter Beerli 2000, Seattle |
|---|
| 46 | beerli@genetics.washington.edu |
|---|
| 47 | $Id: hermite.c 5458 2008-07-16 15:24:20Z westram $ |
|---|
| 48 | -------------------------------------------------------*/ |
|---|
| 49 | |
|---|
| 50 | extern void integrate_laguerre(long categs, double *rate, |
|---|
| 51 | double *probcat, |
|---|
| 52 | double (*func)(double, helper_fmt *), |
|---|
| 53 | helper_fmt *helper, double *result, |
|---|
| 54 | double *rmax); |
|---|
| 55 | extern void initgammacat (long categs, double alpha, double theta1, |
|---|
| 56 | double *rate, double *probcat); |
|---|
| 57 | |
|---|
| 58 | #endif |
|---|
| 59 | |
|---|
| 60 | |
|---|
| 61 | /* laguerre.c */ |
|---|
| 62 | /* |
|---|
| 63 | (mutation) rates following a Gamma distribution |
|---|
| 64 | using orthogonal polynomials for finding rates and |
|---|
| 65 | LOG(probabilities) |
|---|
| 66 | [based on initgammacat of Joe Felsenstein] |
|---|
| 67 | |
|---|
| 68 | - Generalized Laguerre (routine by Joe Felsenstein 2000) |
|---|
| 69 | defining points for a Gamma distribution with |
|---|
| 70 | shape parameter alpha and location parameter beta=1/alpha |
|---|
| 71 | [mean=1, std = 1/alpha^2] |
|---|
| 72 | - Hermite (approximates a normal and is activated when |
|---|
| 73 | the shape parameter alpha is > 100.) |
|---|
| 74 | |
|---|
| 75 | Part of Migrate (Lamarc package) |
|---|
| 76 | http://evolution.genetics.washington.edu/lamarc.html |
|---|
| 77 | |
|---|
| 78 | Peter Beerli, Seattle 2001 |
|---|
| 79 | $Id: hermite.c 5458 2008-07-16 15:24:20Z westram $ |
|---|
| 80 | */ |
|---|
| 81 | #include "migration.h" |
|---|
| 82 | #include "laguerre.h" |
|---|
| 83 | #include "tools.h" |
|---|
| 84 | |
|---|
| 85 | #define SQRTPI 1.7724538509055160273 |
|---|
| 86 | #define SQRT2 1.4142135623730950488 |
|---|
| 87 | |
|---|
| 88 | |
|---|
| 89 | /*this triggers the test main() |
|---|
| 90 | and is called with |
|---|
| 91 | gcc -DLAGUERRE_TEST -g laguerre.c -o laguerre -lm*/ |
|---|
| 92 | |
|---|
| 93 | #ifdef LAGUERRE_TEST |
|---|
| 94 | /* at the end is a test main to help test if the root/weights finding |
|---|
| 95 | is OK*/ |
|---|
| 96 | |
|---|
| 97 | /* if machine has lgamma() use it otherwise use lgamma from |
|---|
| 98 | tools.h*/ |
|---|
| 99 | #undef LGAMMA |
|---|
| 100 | #define LGAMMA lgamma |
|---|
| 101 | |
|---|
| 102 | |
|---|
| 103 | /* for migrate this is defined in tools.h */ |
|---|
| 104 | double |
|---|
| 105 | logfac (long n) |
|---|
| 106 | { |
|---|
| 107 | /* log(n!) values were calculated with Mathematica |
|---|
| 108 | with a precision of 30 digits */ |
|---|
| 109 | switch (n) |
|---|
| 110 | { |
|---|
| 111 | case 0: |
|---|
| 112 | return 0.; |
|---|
| 113 | case 1: |
|---|
| 114 | return 0.; |
|---|
| 115 | case 2: |
|---|
| 116 | return 0.693147180559945309417232121458; |
|---|
| 117 | case 3: |
|---|
| 118 | return 1.791759469228055000812477358381; |
|---|
| 119 | case 4: |
|---|
| 120 | return 3.1780538303479456196469416013; |
|---|
| 121 | case 5: |
|---|
| 122 | return 4.78749174278204599424770093452; |
|---|
| 123 | case 6: |
|---|
| 124 | return 6.5792512120101009950601782929; |
|---|
| 125 | case 7: |
|---|
| 126 | return 8.52516136106541430016553103635; |
|---|
| 127 | case 8: |
|---|
| 128 | return 10.60460290274525022841722740072; |
|---|
| 129 | case 9: |
|---|
| 130 | return 12.80182748008146961120771787457; |
|---|
| 131 | case 10: |
|---|
| 132 | return 15.10441257307551529522570932925; |
|---|
| 133 | case 11: |
|---|
| 134 | return 17.50230784587388583928765290722; |
|---|
| 135 | case 12: |
|---|
| 136 | return 19.98721449566188614951736238706; |
|---|
| 137 | default: |
|---|
| 138 | return LGAMMA(n + 1.); |
|---|
| 139 | } |
|---|
| 140 | } |
|---|
| 141 | #endif |
|---|
| 142 | |
|---|
| 143 | /* prototypes */ |
|---|
| 144 | double hermite(long n, double x); |
|---|
| 145 | void root_hermite(long n, double *hroot); |
|---|
| 146 | double halfroot(double (*func)(long m, double x), |
|---|
| 147 | long n, double startx, double delta); |
|---|
| 148 | void hermite_weight(long n, double * hroot, double * weights); |
|---|
| 149 | void inithermitcat(long categs, double alpha, double theta1, |
|---|
| 150 | double *rate, double *probcat); |
|---|
| 151 | |
|---|
| 152 | double glaguerre (long m, double b, double x); |
|---|
| 153 | void initlaguerrecat(long categs, double alpha, double theta1, |
|---|
| 154 | double *rate, double *probcat); |
|---|
| 155 | void roots_laguerre(long m, double b, double **lgroot); |
|---|
| 156 | |
|---|
| 157 | void initgammacat (long categs, double alpha, double theta1, |
|---|
| 158 | double *rate, double *probcat); |
|---|
| 159 | |
|---|
| 160 | void integrate_laguerre(long categs, double *rate, |
|---|
| 161 | double *probcat, |
|---|
| 162 | double (*func)(double theta, helper_fmt * b), |
|---|
| 163 | helper_fmt *helper, double *result, double *rmax); |
|---|
| 164 | |
|---|
| 165 | |
|---|
| 166 | /*------------------------------------------------------ |
|---|
| 167 | Generalized Laguerre polynomial computed recursively. |
|---|
| 168 | For use by initgammacat |
|---|
| 169 | */ |
|---|
| 170 | double |
|---|
| 171 | glaguerre (long m, double b, double x) |
|---|
| 172 | { |
|---|
| 173 | long i; |
|---|
| 174 | double gln, glnm1, glnp1; /* L_n, L_(n-1), L_(n+1) */ |
|---|
| 175 | |
|---|
| 176 | if (m == 0) |
|---|
| 177 | return 1.0; |
|---|
| 178 | else |
|---|
| 179 | { |
|---|
| 180 | if (m == 1) |
|---|
| 181 | return 1.0 + b - x; |
|---|
| 182 | else |
|---|
| 183 | { |
|---|
| 184 | gln = 1.0 + b - x; |
|---|
| 185 | glnm1 = 1.0; |
|---|
| 186 | for (i = 2; i <= m; i++) |
|---|
| 187 | { |
|---|
| 188 | glnp1 = |
|---|
| 189 | ((2 * (i - 1) + b + 1.0 - x) * gln - (i - 1 + b) * glnm1) / i; |
|---|
| 190 | glnm1 = gln; |
|---|
| 191 | gln = glnp1; |
|---|
| 192 | } |
|---|
| 193 | return gln; |
|---|
| 194 | } |
|---|
| 195 | } |
|---|
| 196 | } /* glaguerre */ |
|---|
| 197 | |
|---|
| 198 | |
|---|
| 199 | /* calculates hermite polynomial with degree n and parameter x */ |
|---|
| 200 | /* seems to be unprecise for n>13 -> root finder does not converge*/ |
|---|
| 201 | double hermite(long n, double x) |
|---|
| 202 | { |
|---|
| 203 | double h1 = 1.; |
|---|
| 204 | double h2 = 2. * x; |
|---|
| 205 | double xx = 2. * x; |
|---|
| 206 | long i; |
|---|
| 207 | for(i = 1; i < n; i++) |
|---|
| 208 | { |
|---|
| 209 | xx = 2. * x * h2 - 2. * (i) * h1; |
|---|
| 210 | h1 = h2; |
|---|
| 211 | h2 = xx; |
|---|
| 212 | } |
|---|
| 213 | return xx; |
|---|
| 214 | } |
|---|
| 215 | |
|---|
| 216 | void root_hermite(long n, double *hroot) |
|---|
| 217 | { |
|---|
| 218 | long z=0; |
|---|
| 219 | long ii; |
|---|
| 220 | long start; |
|---|
| 221 | if(n % 2 == 0) |
|---|
| 222 | { |
|---|
| 223 | start = n/2; |
|---|
| 224 | z = 1; |
|---|
| 225 | } |
|---|
| 226 | else |
|---|
| 227 | { |
|---|
| 228 | start = n/2 + 1; |
|---|
| 229 | z=2; |
|---|
| 230 | hroot[start-1] = 0.0; |
|---|
| 231 | } |
|---|
| 232 | for(ii=start; ii<n; ii++) |
|---|
| 233 | { |
|---|
| 234 | /* search only upwards*/ |
|---|
| 235 | hroot[ii] = halfroot(hermite,n,hroot[ii-1]+EPSILON, 1./n); |
|---|
| 236 | hroot[start - z] = -hroot[ii]; |
|---|
| 237 | z++; |
|---|
| 238 | } |
|---|
| 239 | } |
|---|
| 240 | |
|---|
| 241 | /*searches from the bound (startx) only in one direction |
|---|
| 242 | (by positive or negative delta, which results in |
|---|
| 243 | other-bound=startx+delta) |
|---|
| 244 | delta should be small. |
|---|
| 245 | (*func) is a function with two arguments |
|---|
| 246 | */ |
|---|
| 247 | double |
|---|
| 248 | halfroot(double (*func)(long m, double x), |
|---|
| 249 | long n, double startx, |
|---|
| 250 | double delta) |
|---|
| 251 | { |
|---|
| 252 | double xl; |
|---|
| 253 | double xu; |
|---|
| 254 | double xm; |
|---|
| 255 | double fu; |
|---|
| 256 | double fl; |
|---|
| 257 | double fm = 100000.; |
|---|
| 258 | double gradient; |
|---|
| 259 | boolean down; |
|---|
| 260 | /* decide if we search above or below startx and escapes to trace back |
|---|
| 261 | to the starting point that most often will be |
|---|
| 262 | the root from the previous calculation*/ |
|---|
| 263 | if(delta < 0) |
|---|
| 264 | { |
|---|
| 265 | xu = startx; |
|---|
| 266 | xl = xu + delta; |
|---|
| 267 | } |
|---|
| 268 | else |
|---|
| 269 | { |
|---|
| 270 | xl = startx; |
|---|
| 271 | xu = xl + delta; |
|---|
| 272 | } |
|---|
| 273 | delta = fabs(delta); |
|---|
| 274 | fu = (*func)(n, xu); |
|---|
| 275 | fl = (*func)(n, xl); |
|---|
| 276 | gradient = (fl-fu)/(xl-xu); |
|---|
| 277 | |
|---|
| 278 | while(fabs(fm) > EPSILON) |
|---|
| 279 | { |
|---|
| 280 | /* is root outside of our bracket?*/ |
|---|
| 281 | if((fu<0.0 && fl<0.0) || (fu>0.0 && fl > 0.0)) |
|---|
| 282 | { |
|---|
| 283 | xu += delta; |
|---|
| 284 | fu = (*func)(n, xu); |
|---|
| 285 | fl = (*func)(n, xl); |
|---|
| 286 | gradient = (fl-fu)/(xl-xu); |
|---|
| 287 | down = gradient < 0 ? TRUE : FALSE; |
|---|
| 288 | } |
|---|
| 289 | else |
|---|
| 290 | { |
|---|
| 291 | xm = xl - fl / gradient; |
|---|
| 292 | fm = (*func)(n, xm); |
|---|
| 293 | if(down) |
|---|
| 294 | { |
|---|
| 295 | if(fm > 0.) |
|---|
| 296 | { |
|---|
| 297 | xl = xm; |
|---|
| 298 | fl = fm; |
|---|
| 299 | } |
|---|
| 300 | else |
|---|
| 301 | { |
|---|
| 302 | xu = xm; |
|---|
| 303 | fu = fm; |
|---|
| 304 | } |
|---|
| 305 | } |
|---|
| 306 | else |
|---|
| 307 | { |
|---|
| 308 | if(fm > 0.) |
|---|
| 309 | { |
|---|
| 310 | xu = xm; |
|---|
| 311 | fu = fm; |
|---|
| 312 | } |
|---|
| 313 | else |
|---|
| 314 | { |
|---|
| 315 | xl = xm; |
|---|
| 316 | fl = fm; |
|---|
| 317 | } |
|---|
| 318 | } |
|---|
| 319 | gradient = (fl-fu)/(xl-xu); |
|---|
| 320 | } |
|---|
| 321 | } |
|---|
| 322 | return xm; |
|---|
| 323 | } |
|---|
| 324 | |
|---|
| 325 | |
|---|
| 326 | // calculate the weights for the hermite polynomial |
|---|
| 327 | // at the roots |
|---|
| 328 | // using formula Abramowitz and Stegun chapter 25.4.46 p.890 |
|---|
| 329 | void hermite_weight(long n, double * hroot, double * weights) |
|---|
| 330 | { |
|---|
| 331 | long i; |
|---|
| 332 | double hr2; |
|---|
| 333 | double nominator = exp(LOG2 * ( n-1.) + logfac(n)) * SQRTPI / (n*n); |
|---|
| 334 | for(i=0;i<n; i++) |
|---|
| 335 | { |
|---|
| 336 | hr2 = hermite(n-1, hroot[i]); |
|---|
| 337 | weights[i] = nominator / (hr2*hr2); |
|---|
| 338 | } |
|---|
| 339 | } |
|---|
| 340 | |
|---|
| 341 | /* calculates rates and LOG(probabilities) */ |
|---|
| 342 | void |
|---|
| 343 | inithermitcat(long categs, double alpha, double theta1, |
|---|
| 344 | double *rate, double *probcat) |
|---|
| 345 | { |
|---|
| 346 | long i; |
|---|
| 347 | double *hroot; |
|---|
| 348 | double std = SQRT2 * theta1/sqrt(alpha); |
|---|
| 349 | hroot = (double *) calloc(categs+1,sizeof(double)); |
|---|
| 350 | root_hermite(categs, hroot); // calculate roots |
|---|
| 351 | hermite_weight(categs, hroot, probcat); // set weights |
|---|
| 352 | for(i=0;i<categs;i++) // set rates |
|---|
| 353 | { |
|---|
| 354 | rate[i] = theta1 + std * hroot[i]; |
|---|
| 355 | probcat[i] = log(probcat[i]); |
|---|
| 356 | } |
|---|
| 357 | free(hroot); |
|---|
| 358 | } |
|---|
| 359 | |
|---|
| 360 | void |
|---|
| 361 | roots_laguerre(long m, double b, double **lgroot) |
|---|
| 362 | { |
|---|
| 363 | /* For use by initgammacat. |
|---|
| 364 | Get roots of m-th Generalized Laguerre polynomial, given roots |
|---|
| 365 | of (m-1)-th, these are to be stored in lgroot[m][] */ |
|---|
| 366 | long i; |
|---|
| 367 | double upper, lower, x, y; |
|---|
| 368 | boolean dwn=FALSE; |
|---|
| 369 | double tmp; |
|---|
| 370 | /* is function declining in this interval? */ |
|---|
| 371 | if (m == 1) |
|---|
| 372 | { |
|---|
| 373 | lgroot[1][1] = 1.0 + b; |
|---|
| 374 | } |
|---|
| 375 | else |
|---|
| 376 | { |
|---|
| 377 | dwn = TRUE; |
|---|
| 378 | for (i = 1; i <= m; i++) |
|---|
| 379 | { |
|---|
| 380 | if (i < m) |
|---|
| 381 | { |
|---|
| 382 | if (i == 1) |
|---|
| 383 | lower = 0.0; |
|---|
| 384 | else |
|---|
| 385 | lower = lgroot[m - 1][i - 1]; |
|---|
| 386 | upper = lgroot[m - 1][i]; |
|---|
| 387 | } |
|---|
| 388 | else |
|---|
| 389 | { /* i == m, must search above */ |
|---|
| 390 | lower = lgroot[m - 1][i - 1]; |
|---|
| 391 | x = lgroot[m - 1][m - 1]; |
|---|
| 392 | do |
|---|
| 393 | { |
|---|
| 394 | x = 2.0 * x; |
|---|
| 395 | y = glaguerre (m, b, x); |
|---|
| 396 | } |
|---|
| 397 | while ((dwn && (y > 0.0)) || ((!dwn) && (y < 0.0))); |
|---|
| 398 | upper = x; |
|---|
| 399 | } |
|---|
| 400 | while (upper - lower > 0.000000001) |
|---|
| 401 | { |
|---|
| 402 | x = (upper + lower) / 2.0; |
|---|
| 403 | if ((tmp=glaguerre (m, b, x)) > 0.0) |
|---|
| 404 | { |
|---|
| 405 | if (dwn) |
|---|
| 406 | lower = x; |
|---|
| 407 | else |
|---|
| 408 | upper = x; |
|---|
| 409 | } |
|---|
| 410 | else |
|---|
| 411 | { |
|---|
| 412 | if (dwn) |
|---|
| 413 | upper = x; |
|---|
| 414 | else |
|---|
| 415 | lower = x; |
|---|
| 416 | } |
|---|
| 417 | } |
|---|
| 418 | lgroot[m][i] = (lower + upper) / 2.0; |
|---|
| 419 | dwn = !dwn; /* switch for next one */ |
|---|
| 420 | } |
|---|
| 421 | } |
|---|
| 422 | } /* root_laguerre */ |
|---|
| 423 | |
|---|
| 424 | |
|---|
| 425 | void |
|---|
| 426 | initgammacat (long categs, double alpha, double theta1, |
|---|
| 427 | double *rate, double *probcat) |
|---|
| 428 | { |
|---|
| 429 | /* calculate rates and probabilities to approximate Gamma distribution |
|---|
| 430 | of rates with "categs" categories and shape parameter "alpha" using |
|---|
| 431 | rates and weights from Generalized Laguerre quadrature */ |
|---|
| 432 | |
|---|
| 433 | if(alpha>=100.) |
|---|
| 434 | { |
|---|
| 435 | inithermitcat(categs, alpha, theta1, rate, probcat); |
|---|
| 436 | } |
|---|
| 437 | else |
|---|
| 438 | { |
|---|
| 439 | initlaguerrecat(categs, alpha, theta1, rate, probcat); |
|---|
| 440 | } |
|---|
| 441 | } |
|---|
| 442 | |
|---|
| 443 | void |
|---|
| 444 | initlaguerrecat(long categs, double alpha, double theta1, double *rate, |
|---|
| 445 | double *probcat) |
|---|
| 446 | { |
|---|
| 447 | long i; |
|---|
| 448 | double **lgroot; /* roots of GLaguerre polynomials */ |
|---|
| 449 | double f, x, xi, y; |
|---|
| 450 | |
|---|
| 451 | lgroot = (double **) calloc(categs+1,sizeof(double*)); |
|---|
| 452 | lgroot[0] = (double *) calloc((categs+1)*(categs+1),sizeof(double)); |
|---|
| 453 | for(i=1;i<categs+1;i++) |
|---|
| 454 | { |
|---|
| 455 | lgroot[i] = lgroot[0] + i * (categs+1); |
|---|
| 456 | } |
|---|
| 457 | lgroot[1][1] = 1.0 + alpha; |
|---|
| 458 | for (i = 2; i <= categs; i++) |
|---|
| 459 | roots_laguerre (i, alpha, lgroot); /* get roots for L^(a)_n */ |
|---|
| 460 | /* here get weights */ |
|---|
| 461 | /* Gamma weights are |
|---|
| 462 | (1+a)(1+a/2) ... (1+a/n)*x_i/((n+1)^2 [L_{n+1}^a(x_i)]^2) */ |
|---|
| 463 | f = 1; |
|---|
| 464 | for (i = 1; i <= categs; i++) |
|---|
| 465 | f *= (1.0 + alpha / i); |
|---|
| 466 | for (i = 1; i <= categs; i++) |
|---|
| 467 | { |
|---|
| 468 | xi = lgroot[categs][i]; |
|---|
| 469 | y = glaguerre (categs + 1, alpha, xi); |
|---|
| 470 | x = f * xi / ((categs + 1) * (categs + 1) * y * y); |
|---|
| 471 | rate[i - 1] = xi / (1.0 + alpha); |
|---|
| 472 | probcat[i - 1] = x; |
|---|
| 473 | } |
|---|
| 474 | for(i=0;i<categs;i++) |
|---|
| 475 | { |
|---|
| 476 | probcat[i] = log(probcat[i]); |
|---|
| 477 | rate[i] *= theta1; |
|---|
| 478 | } |
|---|
| 479 | free(lgroot[0]); |
|---|
| 480 | free(lgroot); |
|---|
| 481 | } /* initgammacat */ |
|---|
| 482 | |
|---|
| 483 | |
|---|
| 484 | void integrate_laguerre(long categs, double *rate, |
|---|
| 485 | double *probcat, |
|---|
| 486 | double (*func)(double theta, helper_fmt * b), |
|---|
| 487 | helper_fmt *helper, double *result, double *rmax) |
|---|
| 488 | { |
|---|
| 489 | double sum=0.; |
|---|
| 490 | long i; |
|---|
| 491 | double *temp; |
|---|
| 492 | int *stemp; |
|---|
| 493 | *rmax = -DBL_MAX; |
|---|
| 494 | |
|---|
| 495 | temp = (double *) calloc(categs, sizeof(double)); |
|---|
| 496 | stemp = (int *) calloc(categs, sizeof(int)); |
|---|
| 497 | for(i=0;i<categs;i++) |
|---|
| 498 | { |
|---|
| 499 | temp[i] = (*func)(rate[i], (void *)helper); |
|---|
| 500 | stemp[i] = helper->sign; |
|---|
| 501 | if(temp[i] > *rmax) |
|---|
| 502 | *rmax = temp[i]; |
|---|
| 503 | } |
|---|
| 504 | for(i=0;i<categs;i++) |
|---|
| 505 | { |
|---|
| 506 | sum += ((double) stemp[i]) * probcat[i] * exp(temp[i] - *rmax); |
|---|
| 507 | } |
|---|
| 508 | free(temp); |
|---|
| 509 | free(stemp); |
|---|
| 510 | *result = sum; |
|---|
| 511 | } |
|---|
| 512 | |
|---|
| 513 | |
|---|
| 514 | /* initgammacat test function*/ |
|---|
| 515 | #ifdef LAGUERRE_TEST |
|---|
| 516 | int main() |
|---|
| 517 | { |
|---|
| 518 | long categs=10; |
|---|
| 519 | double alpha; |
|---|
| 520 | double theta1; |
|---|
| 521 | double *rate; |
|---|
| 522 | double *probcat; |
|---|
| 523 | long i; |
|---|
| 524 | printf("Enter alpha, theta1, and categs\n"); |
|---|
| 525 | fscanf(stdin,"%lf%lf%li",&alpha,&theta1,&categs); |
|---|
| 526 | rate = (double *) calloc(categs+1,sizeof(double)); |
|---|
| 527 | probcat = (double *) calloc(categs+1,sizeof(double)); |
|---|
| 528 | initgammacat(categs, alpha, theta1, rate,probcat); |
|---|
| 529 | for(i=0;i<categs;i++) |
|---|
| 530 | { |
|---|
| 531 | printf("%20.20f %20.20f\n",rate[i],probcat[i]); |
|---|
| 532 | } |
|---|
| 533 | return 0; |
|---|
| 534 | } |
|---|
| 535 | #endif |
|---|
| 536 | |
|---|
| 537 | |
|---|
| 538 | |
|---|
| 539 | |
|---|
| 540 | |
|---|
| 541 | |
|---|
| 542 | |
|---|
| 543 | |
|---|
| 544 | |
|---|
| 545 | |
|---|
| 546 | |
|---|
| 547 | |
|---|