| 1 | /* |
|---|
| 2 | * util.c |
|---|
| 3 | * |
|---|
| 4 | * |
|---|
| 5 | * Part of TREE-PUZZLE 5.0 (June 2000) |
|---|
| 6 | * |
|---|
| 7 | * (c) 1999-2000 by Heiko A. Schmidt, Korbinian Strimmer, |
|---|
| 8 | * M. Vingron, and Arndt von Haeseler |
|---|
| 9 | * (c) 1995-1999 by Korbinian Strimmer and Arndt von Haeseler |
|---|
| 10 | * |
|---|
| 11 | * All parts of the source except where indicated are distributed under |
|---|
| 12 | * the GNU public licence. See http://www.opensource.org for details. |
|---|
| 13 | */ |
|---|
| 14 | |
|---|
| 15 | |
|---|
| 16 | #include "util.h" |
|---|
| 17 | |
|---|
| 18 | #define STDOUT stdout |
|---|
| 19 | #ifndef PARALLEL /* because printf() runs significantly faster */ |
|---|
| 20 | /* than fprintf(stdout) on an Apple McIntosh */ |
|---|
| 21 | /* (HS) */ |
|---|
| 22 | # define FPRINTF printf |
|---|
| 23 | # define STDOUTFILE |
|---|
| 24 | #else |
|---|
| 25 | # define FPRINTF fprintf |
|---|
| 26 | # define STDOUTFILE STDOUT, |
|---|
| 27 | extern int PP_NumProcs; |
|---|
| 28 | extern int PP_Myid; |
|---|
| 29 | long int PP_randn; |
|---|
| 30 | long int PP_rand; |
|---|
| 31 | #endif |
|---|
| 32 | |
|---|
| 33 | |
|---|
| 34 | /* |
|---|
| 35 | * memory allocation error handler |
|---|
| 36 | */ |
|---|
| 37 | |
|---|
| 38 | void maerror(const char *message) |
|---|
| 39 | { |
|---|
| 40 | FPRINTF(STDOUTFILE "\n\n\nUnable to proceed (lack of memory: %s)\n\n", message); |
|---|
| 41 | FPRINTF(STDOUTFILE "Hint for Macintosh users:\n"); |
|---|
| 42 | FPRINTF(STDOUTFILE "Use the <Get Info> command of the Finder to increase the memory partition!\n\n"); |
|---|
| 43 | exit(1); |
|---|
| 44 | } |
|---|
| 45 | |
|---|
| 46 | |
|---|
| 47 | /* |
|---|
| 48 | * memory allocate double vectors, matrices, and cubes |
|---|
| 49 | */ |
|---|
| 50 | |
|---|
| 51 | dvector new_dvector(int n) |
|---|
| 52 | { |
|---|
| 53 | dvector v; |
|---|
| 54 | |
|---|
| 55 | v = (dvector) malloc((unsigned) (n * sizeof(double))); |
|---|
| 56 | if (v == NULL) maerror("step 1 in new_dvector"); |
|---|
| 57 | |
|---|
| 58 | return v; |
|---|
| 59 | } |
|---|
| 60 | |
|---|
| 61 | dmatrix new_dmatrix(int nrow, int ncol) |
|---|
| 62 | { |
|---|
| 63 | int i; |
|---|
| 64 | dmatrix m; |
|---|
| 65 | |
|---|
| 66 | m = (dmatrix) malloc((unsigned) (nrow * sizeof(dvector))); |
|---|
| 67 | if (m == NULL) maerror("step 1 in in new_dmatrix"); |
|---|
| 68 | |
|---|
| 69 | *m = (dvector) malloc((unsigned) (nrow * ncol * sizeof(double))); |
|---|
| 70 | if (*m == NULL) maerror("step 2 in in new_dmatrix"); |
|---|
| 71 | |
|---|
| 72 | for (i = 1; i < nrow; i++) m[i] = m[i-1] + ncol; |
|---|
| 73 | |
|---|
| 74 | return m; |
|---|
| 75 | } |
|---|
| 76 | |
|---|
| 77 | dcube new_dcube(int ntri, int nrow, int ncol) |
|---|
| 78 | { |
|---|
| 79 | int i, j; |
|---|
| 80 | dcube c; |
|---|
| 81 | |
|---|
| 82 | c = (dcube) malloc((unsigned) (ntri * sizeof(dmatrix))); |
|---|
| 83 | if (c == NULL) maerror("step 1 in in new_dcube"); |
|---|
| 84 | |
|---|
| 85 | *c = (dmatrix) malloc((unsigned) (ntri * nrow * sizeof(dvector))); |
|---|
| 86 | if (*c == NULL) maerror("step 2 in in new_dcube"); |
|---|
| 87 | |
|---|
| 88 | **c = (dvector) malloc((unsigned) (ntri * nrow * ncol * sizeof(double))); |
|---|
| 89 | if (**c == NULL) maerror("step 3 in in new_dcube"); |
|---|
| 90 | |
|---|
| 91 | for (j = 1; j < nrow; j++) c[0][j] = c[0][j-1] + ncol; |
|---|
| 92 | |
|---|
| 93 | for (i = 1; i < ntri; i++) { |
|---|
| 94 | c[i] = c[i-1] + nrow; |
|---|
| 95 | c[i][0] = c[i-1][0] + nrow * ncol; |
|---|
| 96 | for (j = 1; j < nrow; j++) c[i][j] = c[i][j-1] + ncol; |
|---|
| 97 | } |
|---|
| 98 | |
|---|
| 99 | return c; |
|---|
| 100 | } |
|---|
| 101 | |
|---|
| 102 | void free_dvector(dvector v) |
|---|
| 103 | { |
|---|
| 104 | free((double *) v); |
|---|
| 105 | } |
|---|
| 106 | |
|---|
| 107 | void free_dmatrix(dmatrix m) |
|---|
| 108 | { |
|---|
| 109 | free((double *) *m); |
|---|
| 110 | free((double *) m); |
|---|
| 111 | } |
|---|
| 112 | |
|---|
| 113 | void free_dcube(dcube c) |
|---|
| 114 | { |
|---|
| 115 | free((double *) **c); |
|---|
| 116 | free((double *) *c); |
|---|
| 117 | free((double *) c); |
|---|
| 118 | } |
|---|
| 119 | |
|---|
| 120 | |
|---|
| 121 | /* |
|---|
| 122 | * memory allocate char vectors, matrices, and cubes |
|---|
| 123 | */ |
|---|
| 124 | |
|---|
| 125 | cvector new_cvector(int n) |
|---|
| 126 | { |
|---|
| 127 | cvector v; |
|---|
| 128 | |
|---|
| 129 | v = (cvector) malloc((unsigned)n * sizeof(char)); |
|---|
| 130 | if (v == NULL) maerror("step1 in new_cvector"); |
|---|
| 131 | |
|---|
| 132 | return v; |
|---|
| 133 | } |
|---|
| 134 | |
|---|
| 135 | cmatrix new_cmatrix(int nrow, int ncol) |
|---|
| 136 | { |
|---|
| 137 | int i; |
|---|
| 138 | cmatrix m; |
|---|
| 139 | |
|---|
| 140 | m = (cmatrix) malloc((unsigned) (nrow * sizeof(cvector))); |
|---|
| 141 | if (m == NULL) maerror("step 1 in new_cmatrix"); |
|---|
| 142 | |
|---|
| 143 | *m = (cvector) malloc((unsigned) (nrow * ncol * sizeof(char))); |
|---|
| 144 | if (*m == NULL) maerror("step 2 in new_cmatrix"); |
|---|
| 145 | |
|---|
| 146 | for (i = 1; i < nrow; i++) m[i] = m[i-1] + ncol; |
|---|
| 147 | |
|---|
| 148 | return m; |
|---|
| 149 | } |
|---|
| 150 | |
|---|
| 151 | ccube new_ccube(int ntri, int nrow, int ncol) |
|---|
| 152 | { |
|---|
| 153 | int i, j; |
|---|
| 154 | ccube c; |
|---|
| 155 | |
|---|
| 156 | c = (ccube) malloc((unsigned) (ntri * sizeof(cmatrix))); |
|---|
| 157 | if (c == NULL) maerror("step 1 in new_ccube"); |
|---|
| 158 | |
|---|
| 159 | *c = (cmatrix) malloc((unsigned) (ntri * nrow * sizeof(cvector))); |
|---|
| 160 | if (*c == NULL) maerror("step 2 in new_ccube"); |
|---|
| 161 | |
|---|
| 162 | **c = (cvector) malloc((unsigned) (ntri * nrow * ncol * sizeof(char))); |
|---|
| 163 | if (**c == NULL) maerror("step 3 in new_ccube"); |
|---|
| 164 | |
|---|
| 165 | for (j = 1; j < nrow; j++) c[0][j] = c[0][j-1] + ncol; |
|---|
| 166 | |
|---|
| 167 | for (i = 1; i < ntri; i++) { |
|---|
| 168 | c[i] = c[i-1] + nrow; |
|---|
| 169 | c[i][0] = c[i-1][0] + nrow * ncol; |
|---|
| 170 | for (j = 1; j < nrow; j++) c[i][j] = c[i][j-1] + ncol; |
|---|
| 171 | } |
|---|
| 172 | |
|---|
| 173 | return c; |
|---|
| 174 | } |
|---|
| 175 | |
|---|
| 176 | void free_cvector(cvector v) |
|---|
| 177 | { |
|---|
| 178 | free((char *) v); |
|---|
| 179 | } |
|---|
| 180 | |
|---|
| 181 | void free_cmatrix(cmatrix m) |
|---|
| 182 | { |
|---|
| 183 | free((char *) *m); |
|---|
| 184 | free((char *) m); |
|---|
| 185 | } |
|---|
| 186 | |
|---|
| 187 | void free_ccube(ccube c) |
|---|
| 188 | { |
|---|
| 189 | free((char *) **c); |
|---|
| 190 | free((char *) *c); |
|---|
| 191 | free((char *) c); |
|---|
| 192 | } |
|---|
| 193 | |
|---|
| 194 | |
|---|
| 195 | /* |
|---|
| 196 | * memory allocate int vectors, matrices, and cubes |
|---|
| 197 | */ |
|---|
| 198 | |
|---|
| 199 | ivector new_ivector(int n) |
|---|
| 200 | { |
|---|
| 201 | ivector v; |
|---|
| 202 | |
|---|
| 203 | v = (ivector) malloc((unsigned) (n * sizeof(int))); |
|---|
| 204 | if (v == NULL) maerror("step 1 in new_ivector"); |
|---|
| 205 | |
|---|
| 206 | return v; |
|---|
| 207 | } |
|---|
| 208 | |
|---|
| 209 | imatrix new_imatrix(int nrow, int ncol) |
|---|
| 210 | { |
|---|
| 211 | int i; |
|---|
| 212 | imatrix m; |
|---|
| 213 | |
|---|
| 214 | m = (imatrix) malloc((unsigned) (nrow * sizeof(ivector))); |
|---|
| 215 | if (m == NULL) maerror("step 1 in new_imatrix"); |
|---|
| 216 | |
|---|
| 217 | *m = (ivector) malloc((unsigned) (nrow * ncol * sizeof(int))); |
|---|
| 218 | if (*m == NULL) maerror("step 2 in new_imatrix"); |
|---|
| 219 | |
|---|
| 220 | for (i = 1; i < nrow; i++) m[i] = m[i-1] + ncol; |
|---|
| 221 | |
|---|
| 222 | return m; |
|---|
| 223 | } |
|---|
| 224 | |
|---|
| 225 | icube new_icube(int ntri, int nrow, int ncol) |
|---|
| 226 | { |
|---|
| 227 | int i, j; |
|---|
| 228 | icube c; |
|---|
| 229 | |
|---|
| 230 | c = (icube) malloc((unsigned) (ntri * sizeof(imatrix))); |
|---|
| 231 | if (c == NULL) maerror("step 1 in new_icube"); |
|---|
| 232 | |
|---|
| 233 | *c = (imatrix) malloc((unsigned) (ntri * nrow * sizeof(ivector))); |
|---|
| 234 | if (*c == NULL) maerror("step 2 in new_icube"); |
|---|
| 235 | |
|---|
| 236 | **c = (ivector) malloc((unsigned) (ntri * nrow * ncol * sizeof(int))); |
|---|
| 237 | if (**c == NULL) maerror("step 3 in new_icube"); |
|---|
| 238 | |
|---|
| 239 | for (j = 1; j < nrow; j++) c[0][j] = c[0][j-1] + ncol; |
|---|
| 240 | |
|---|
| 241 | for (i = 1; i < ntri; i++) { |
|---|
| 242 | c[i] = c[i-1] + nrow; |
|---|
| 243 | c[i][0] = c[i-1][0] + nrow * ncol; |
|---|
| 244 | for (j = 1; j < nrow; j++) c[i][j] = c[i][j-1] + ncol; |
|---|
| 245 | } |
|---|
| 246 | |
|---|
| 247 | return c; |
|---|
| 248 | } |
|---|
| 249 | |
|---|
| 250 | void free_ivector(ivector v) |
|---|
| 251 | { |
|---|
| 252 | free((int *) v); |
|---|
| 253 | } |
|---|
| 254 | |
|---|
| 255 | void free_imatrix(imatrix m) |
|---|
| 256 | { |
|---|
| 257 | free((int *) *m); |
|---|
| 258 | free((int *) m); |
|---|
| 259 | } |
|---|
| 260 | |
|---|
| 261 | void free_icube(icube c) |
|---|
| 262 | { |
|---|
| 263 | free((int *) **c); |
|---|
| 264 | free((int *) *c); |
|---|
| 265 | free((int *) c); |
|---|
| 266 | } |
|---|
| 267 | |
|---|
| 268 | |
|---|
| 269 | /* |
|---|
| 270 | * memory allocate uli vectors, matrices, and cubes |
|---|
| 271 | */ |
|---|
| 272 | |
|---|
| 273 | ulivector new_ulivector(int n) |
|---|
| 274 | { |
|---|
| 275 | ulivector v; |
|---|
| 276 | |
|---|
| 277 | v = (ulivector) malloc((unsigned) (n * sizeof(uli))); |
|---|
| 278 | if (v == NULL) maerror("step 1 in new_ulivector"); |
|---|
| 279 | |
|---|
| 280 | return v; |
|---|
| 281 | } |
|---|
| 282 | |
|---|
| 283 | ulimatrix new_ulimatrix(int nrow, int ncol) |
|---|
| 284 | { |
|---|
| 285 | int i; |
|---|
| 286 | ulimatrix m; |
|---|
| 287 | |
|---|
| 288 | m = (ulimatrix) malloc((unsigned) (nrow * sizeof(ulivector))); |
|---|
| 289 | if (m == NULL) maerror("step 1 in new_ulimatrix"); |
|---|
| 290 | |
|---|
| 291 | *m = (ulivector) malloc((unsigned) (nrow * ncol * sizeof(uli))); |
|---|
| 292 | if (*m == NULL) maerror("step 2 in new_ulimatrix"); |
|---|
| 293 | |
|---|
| 294 | for (i = 1; i < nrow; i++) m[i] = m[i-1] + ncol; |
|---|
| 295 | |
|---|
| 296 | return m; |
|---|
| 297 | } |
|---|
| 298 | |
|---|
| 299 | ulicube new_ulicube(int ntri, int nrow, int ncol) |
|---|
| 300 | { |
|---|
| 301 | int i, j; |
|---|
| 302 | ulicube c; |
|---|
| 303 | |
|---|
| 304 | c = (ulicube) malloc((unsigned) (ntri * sizeof(ulimatrix))); |
|---|
| 305 | if (c == NULL) maerror("step 1 in new_ulicube"); |
|---|
| 306 | |
|---|
| 307 | *c = (ulimatrix) malloc((unsigned) (ntri * nrow * sizeof(ulivector))); |
|---|
| 308 | if (*c == NULL) maerror("step 2 in new_ulicube"); |
|---|
| 309 | |
|---|
| 310 | **c = (ulivector) malloc((unsigned) (ntri * nrow * ncol * sizeof(uli))); |
|---|
| 311 | if (**c == NULL) maerror("step 3 in new_ulicube"); |
|---|
| 312 | |
|---|
| 313 | for (j = 1; j < nrow; j++) c[0][j] = c[0][j-1] + ncol; |
|---|
| 314 | |
|---|
| 315 | for (i = 1; i < ntri; i++) { |
|---|
| 316 | c[i] = c[i-1] + nrow; |
|---|
| 317 | c[i][0] = c[i-1][0] + nrow * ncol; |
|---|
| 318 | for (j = 1; j < nrow; j++) c[i][j] = c[i][j-1] + ncol; |
|---|
| 319 | } |
|---|
| 320 | |
|---|
| 321 | return c; |
|---|
| 322 | } |
|---|
| 323 | |
|---|
| 324 | void free_ulivector(ulivector v) |
|---|
| 325 | { |
|---|
| 326 | free((uli *) v); |
|---|
| 327 | } |
|---|
| 328 | |
|---|
| 329 | void free_ulimatrix(ulimatrix m) |
|---|
| 330 | { |
|---|
| 331 | free((uli *) *m); |
|---|
| 332 | free((uli *) m); |
|---|
| 333 | } |
|---|
| 334 | |
|---|
| 335 | void free_ulicube(ulicube c) |
|---|
| 336 | { |
|---|
| 337 | free((uli *) **c); |
|---|
| 338 | free((uli *) *c); |
|---|
| 339 | free((uli *) c); |
|---|
| 340 | } |
|---|
| 341 | |
|---|
| 342 | |
|---|
| 343 | /******************************************************************************/ |
|---|
| 344 | /* random numbers generator (Numerical recipes) */ |
|---|
| 345 | /******************************************************************************/ |
|---|
| 346 | |
|---|
| 347 | /* definitions */ |
|---|
| 348 | #define IM1 2147483563 |
|---|
| 349 | #define IM2 2147483399 |
|---|
| 350 | #define AM (1.0/IM1) |
|---|
| 351 | #define IMM1 (IM1-1) |
|---|
| 352 | #define IA1 40014 |
|---|
| 353 | #define IA2 40692 |
|---|
| 354 | #define IQ1 53668 |
|---|
| 355 | #define IQ2 52774 |
|---|
| 356 | #define IR1 12211 |
|---|
| 357 | #define IR2 3791 |
|---|
| 358 | #define NTAB 32 |
|---|
| 359 | #define NDIV (1+IMM1/NTAB) |
|---|
| 360 | #define EPS 1.2e-7 |
|---|
| 361 | #define RNMX (1.0-EPS) |
|---|
| 362 | |
|---|
| 363 | /* variable */ |
|---|
| 364 | long idum; |
|---|
| 365 | |
|---|
| 366 | double randomunitinterval() |
|---|
| 367 | /* Long period (> 2e18) random number generator. Returns a uniform random |
|---|
| 368 | deviate between 0.0 and 1.0 (exclusive of endpoint values). |
|---|
| 369 | |
|---|
| 370 | Source: |
|---|
| 371 | Press et al., "Numerical recipes in C", Cambridge University Press, 1992 |
|---|
| 372 | (chapter 7 "Random numbers", ran2 random number generator) */ |
|---|
| 373 | { |
|---|
| 374 | int j; |
|---|
| 375 | long k; |
|---|
| 376 | static long idum2=123456789; |
|---|
| 377 | static long iy=0; |
|---|
| 378 | static long iv[NTAB]; |
|---|
| 379 | double temp; |
|---|
| 380 | |
|---|
| 381 | if (idum <= 0) { |
|---|
| 382 | if (-(idum) < 1) |
|---|
| 383 | idum=1; |
|---|
| 384 | else |
|---|
| 385 | idum=-(idum); |
|---|
| 386 | idum2=(idum); |
|---|
| 387 | for (j=NTAB+7;j>=0;j--) { |
|---|
| 388 | k=(idum)/IQ1; |
|---|
| 389 | idum=IA1*(idum-k*IQ1)-k*IR1; |
|---|
| 390 | if (idum < 0) |
|---|
| 391 | idum += IM1; |
|---|
| 392 | if (j < NTAB) |
|---|
| 393 | iv[j] = idum; |
|---|
| 394 | } |
|---|
| 395 | iy=iv[0]; |
|---|
| 396 | } |
|---|
| 397 | k=(idum)/IQ1; |
|---|
| 398 | idum=IA1*(idum-k*IQ1)-k*IR1; |
|---|
| 399 | if (idum < 0) |
|---|
| 400 | idum += IM1; |
|---|
| 401 | k=idum2/IQ2; |
|---|
| 402 | idum2=IA2*(idum2-k*IQ2)-k*IR2; |
|---|
| 403 | if (idum2 < 0) |
|---|
| 404 | idum2 += IM2; |
|---|
| 405 | j=iy/NDIV; |
|---|
| 406 | iy=iv[j]-idum2; |
|---|
| 407 | iv[j] = idum; |
|---|
| 408 | if (iy < 1) |
|---|
| 409 | iy += IMM1; |
|---|
| 410 | if ((temp=AM*iy) > RNMX) |
|---|
| 411 | return RNMX; |
|---|
| 412 | else |
|---|
| 413 | return temp; |
|---|
| 414 | } |
|---|
| 415 | |
|---|
| 416 | #undef IM1 |
|---|
| 417 | #undef IM2 |
|---|
| 418 | #undef AM |
|---|
| 419 | #undef IMM1 |
|---|
| 420 | #undef IA1 |
|---|
| 421 | #undef IA2 |
|---|
| 422 | #undef IQ1 |
|---|
| 423 | #undef IQ2 |
|---|
| 424 | #undef IR1 |
|---|
| 425 | #undef IR2 |
|---|
| 426 | #undef NTAB |
|---|
| 427 | #undef NDIV |
|---|
| 428 | #undef EPS |
|---|
| 429 | #undef RNMX |
|---|
| 430 | |
|---|
| 431 | int initrandom(int seed) |
|---|
| 432 | { |
|---|
| 433 | srand((unsigned) time(NULL)); |
|---|
| 434 | if (seed < 0) |
|---|
| 435 | seed = rand(); |
|---|
| 436 | idum=-(long) seed; |
|---|
| 437 | # ifdef PARALLEL |
|---|
| 438 | { |
|---|
| 439 | int n; |
|---|
| 440 | for (n=0; n<PP_Myid; n++) |
|---|
| 441 | (void) randomunitinterval(); |
|---|
| 442 | # ifdef PVERBOSE1 |
|---|
| 443 | fprintf(stderr, "(%2d) !!! random seed set to %d, %dx drawn !!!\n", PP_Myid, seed, n); |
|---|
| 444 | # endif |
|---|
| 445 | } |
|---|
| 446 | # else |
|---|
| 447 | # ifdef PVERBOSE1 |
|---|
| 448 | fprintf(stderr, "!!! random seed set to %d !!!\n", seed); |
|---|
| 449 | # endif |
|---|
| 450 | # endif |
|---|
| 451 | return (seed); |
|---|
| 452 | } /* initrandom */ |
|---|
| 453 | |
|---|
| 454 | |
|---|
| 455 | /* returns a random integer in the range [0; n - 1] */ |
|---|
| 456 | int randominteger(int n) |
|---|
| 457 | { |
|---|
| 458 | int t; |
|---|
| 459 | # ifndef FIXEDINTRAND |
|---|
| 460 | # ifndef PARALLEL |
|---|
| 461 | t = (int) floor(randomunitinterval()*n); |
|---|
| 462 | return t; |
|---|
| 463 | # else |
|---|
| 464 | int m; |
|---|
| 465 | for (m=1; m<PP_NumProcs; m++) |
|---|
| 466 | (void) randomunitinterval(); |
|---|
| 467 | PP_randn+=(m-1); PP_rand++; |
|---|
| 468 | return (int) floor(randomunitinterval()*n); |
|---|
| 469 | # endif |
|---|
| 470 | # else |
|---|
| 471 | fprintf(stderr, "!!! fixed \"random\" integers for testing purposes !!!\n"); |
|---|
| 472 | return (int)0; |
|---|
| 473 | # endif /* FIXEDINTRAND */ |
|---|
| 474 | } |
|---|
| 475 | |
|---|
| 476 | /* Draw s numbers from the set 0,1,2,..,t-1 and put them |
|---|
| 477 | into slist (every number can be drawn only one time) */ |
|---|
| 478 | void chooser(int t, int s, ivector slist) |
|---|
| 479 | { |
|---|
| 480 | int i, j, k, l; |
|---|
| 481 | ivector isfree; |
|---|
| 482 | |
|---|
| 483 | isfree = new_ivector(t); |
|---|
| 484 | for (i = 0; i < t; i++) isfree[i] = TRUE; |
|---|
| 485 | for (i = 0; i < s; i++) { |
|---|
| 486 | /* random integer in the range [0, t-1-i] */ |
|---|
| 487 | j = randominteger(t-i); |
|---|
| 488 | k = -1; |
|---|
| 489 | l = -1; |
|---|
| 490 | do { |
|---|
| 491 | k++; |
|---|
| 492 | if (isfree[k] == TRUE) l++; |
|---|
| 493 | } while ( l != j); |
|---|
| 494 | slist[i] = k; |
|---|
| 495 | isfree[k] = FALSE; |
|---|
| 496 | } |
|---|
| 497 | free_ivector(isfree); |
|---|
| 498 | } |
|---|
| 499 | |
|---|
| 500 | /* a realloc function that works also on non-ANSI compilers */ |
|---|
| 501 | void *myrealloc(void *p, size_t s) |
|---|
| 502 | { |
|---|
| 503 | if (p == NULL) return malloc(s); |
|---|
| 504 | else return realloc(p, s); |
|---|
| 505 | } |
|---|
| 506 | |
|---|
| 507 | /* safer variant of gets */ |
|---|
| 508 | /* Reads characters from stdin until a newline character or EOF |
|---|
| 509 | is received. The newline is not made part of the string. |
|---|
| 510 | If an error occurs a null string \0 is returned */ |
|---|
| 511 | cvector mygets() |
|---|
| 512 | { |
|---|
| 513 | int c, n; |
|---|
| 514 | cvector str; |
|---|
| 515 | |
|---|
| 516 | str = new_cvector(100); |
|---|
| 517 | |
|---|
| 518 | n = 0; |
|---|
| 519 | c = getchar(); |
|---|
| 520 | while (c != '\n' && c != '\r' && n < 99 && c != EOF && !ferror(stdin)) |
|---|
| 521 | { |
|---|
| 522 | str[n] = (char) c; |
|---|
| 523 | c = getchar(); |
|---|
| 524 | n++; |
|---|
| 525 | } |
|---|
| 526 | if (c == EOF || ferror(stdin)) |
|---|
| 527 | { |
|---|
| 528 | str[0] = '\0'; |
|---|
| 529 | } |
|---|
| 530 | else |
|---|
| 531 | { |
|---|
| 532 | str[n] = '\0'; |
|---|
| 533 | } |
|---|
| 534 | |
|---|
| 535 | return str; |
|---|
| 536 | } |
|---|
| 537 | |
|---|
| 538 | |
|---|
| 539 | |
|---|
| 540 | /******************************************************************************/ |
|---|
| 541 | /* minimization of a function by Brents method (Numerical Recipes) */ |
|---|
| 542 | /******************************************************************************/ |
|---|
| 543 | |
|---|
| 544 | double brent(double, double, double, double (*f )(double ), double, double *, double *, double, double, double); |
|---|
| 545 | |
|---|
| 546 | |
|---|
| 547 | #define ITMAX 100 |
|---|
| 548 | #define CGOLD 0.3819660 |
|---|
| 549 | #define GOLD 1.618034 |
|---|
| 550 | #define GLIMIT 100.0 |
|---|
| 551 | #define TINY 1.0e-20 |
|---|
| 552 | #define ZEPS 1.0e-10 |
|---|
| 553 | #define SHFT(a,b,c,d) (a)=(b);(b)=(c);(c)=(d); |
|---|
| 554 | #define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a)) |
|---|
| 555 | |
|---|
| 556 | /* Brents method in one dimension */ |
|---|
| 557 | double brent(double ax, double bx, double cx, double (*f)(double), double tol, |
|---|
| 558 | double *foptx, double *f2optx, double fax, double fbx, double fcx) |
|---|
| 559 | { |
|---|
| 560 | int iter; |
|---|
| 561 | double a,b,d=0,etemp,fu,fv,fw,fx,p,q,r,tol1,tol2,u,v,w,x,xm; |
|---|
| 562 | double xw,wv,vx; |
|---|
| 563 | double e=0.0; |
|---|
| 564 | |
|---|
| 565 | a=(ax < cx ? ax : cx); |
|---|
| 566 | b=(ax > cx ? ax : cx); |
|---|
| 567 | x=bx; |
|---|
| 568 | fx=fbx; |
|---|
| 569 | if (fax < fcx) { |
|---|
| 570 | w=ax; |
|---|
| 571 | fw=fax; |
|---|
| 572 | v=cx; |
|---|
| 573 | fv=fcx; |
|---|
| 574 | } else { |
|---|
| 575 | w=cx; |
|---|
| 576 | fw=fcx; |
|---|
| 577 | v=ax; |
|---|
| 578 | fv=fax; |
|---|
| 579 | } |
|---|
| 580 | for (iter=1;iter<=ITMAX;iter++) { |
|---|
| 581 | xm=0.5*(a+b); |
|---|
| 582 | tol2=2.0*(tol1=tol*fabs(x)+ZEPS); |
|---|
| 583 | if (fabs(x-xm) <= (tol2-0.5*(b-a))) { |
|---|
| 584 | *foptx = fx; |
|---|
| 585 | xw = x-w; |
|---|
| 586 | wv = w-v; |
|---|
| 587 | vx = v-x; |
|---|
| 588 | *f2optx = 2.0*(fv*xw + fx*wv + fw*vx)/ |
|---|
| 589 | (v*v*xw + x*x*wv + w*w*vx); |
|---|
| 590 | return x; |
|---|
| 591 | } |
|---|
| 592 | if (fabs(e) > tol1) { |
|---|
| 593 | r=(x-w)*(fx-fv); |
|---|
| 594 | q=(x-v)*(fx-fw); |
|---|
| 595 | p=(x-v)*q-(x-w)*r; |
|---|
| 596 | q=2.0*(q-r); |
|---|
| 597 | if (q > 0.0) p = -p; |
|---|
| 598 | q=fabs(q); |
|---|
| 599 | etemp=e; |
|---|
| 600 | e=d; |
|---|
| 601 | if (fabs(p) >= fabs(0.5*q*etemp) || p <= q*(a-x) || p >= q*(b-x)) |
|---|
| 602 | d=CGOLD*(e=(x >= xm ? a-x : b-x)); |
|---|
| 603 | else { |
|---|
| 604 | d=p/q; |
|---|
| 605 | u=x+d; |
|---|
| 606 | if (u-a < tol2 || b-u < tol2) |
|---|
| 607 | d=SIGN(tol1,xm-x); |
|---|
| 608 | } |
|---|
| 609 | } else { |
|---|
| 610 | d=CGOLD*(e=(x >= xm ? a-x : b-x)); |
|---|
| 611 | } |
|---|
| 612 | u=(fabs(d) >= tol1 ? x+d : x+SIGN(tol1,d)); |
|---|
| 613 | fu=(*f)(u); |
|---|
| 614 | if (fu <= fx) { |
|---|
| 615 | if (u >= x) a=x; else b=x; |
|---|
| 616 | SHFT(v,w,x,u) |
|---|
| 617 | SHFT(fv,fw,fx,fu) |
|---|
| 618 | } else { |
|---|
| 619 | if (u < x) a=u; else b=u; |
|---|
| 620 | if (fu <= fw || w == x) { |
|---|
| 621 | v=w; |
|---|
| 622 | w=u; |
|---|
| 623 | fv=fw; |
|---|
| 624 | fw=fu; |
|---|
| 625 | } else if (fu <= fv || v == x || v == w) { |
|---|
| 626 | v=u; |
|---|
| 627 | fv=fu; |
|---|
| 628 | } |
|---|
| 629 | } |
|---|
| 630 | } |
|---|
| 631 | *foptx = fx; |
|---|
| 632 | xw = x-w; |
|---|
| 633 | wv = w-v; |
|---|
| 634 | vx = v-x; |
|---|
| 635 | *f2optx = 2.0*(fv*xw + fx*wv + fw*vx)/ |
|---|
| 636 | (v*v*xw + x*x*wv + w*w*vx); |
|---|
| 637 | return x; |
|---|
| 638 | } |
|---|
| 639 | #undef ITMAX |
|---|
| 640 | #undef CGOLD |
|---|
| 641 | #undef ZEPS |
|---|
| 642 | #undef SHFT |
|---|
| 643 | #undef SIGN |
|---|
| 644 | #undef GOLD |
|---|
| 645 | #undef GLIMIT |
|---|
| 646 | #undef TINY |
|---|
| 647 | |
|---|
| 648 | /* one-dimensional minimization - as input a lower and an upper limit and a trial |
|---|
| 649 | value for the minimum is needed: xmin < xguess < xmax |
|---|
| 650 | the function and a fractional tolerance has to be specified |
|---|
| 651 | onedimenmin returns the optimal x value and the value of the function |
|---|
| 652 | and its second derivative at this point |
|---|
| 653 | */ |
|---|
| 654 | double onedimenmin(double xmin, double xguess, double xmax, double (*f)(double), |
|---|
| 655 | double tol, double *fx, double *f2x) |
|---|
| 656 | { |
|---|
| 657 | double eps, optx, ax, bx, cx, fa, fb, fc; |
|---|
| 658 | |
|---|
| 659 | /* first attempt to bracketize minimum */ |
|---|
| 660 | eps = xguess*tol*50.0; |
|---|
| 661 | ax = xguess - eps; |
|---|
| 662 | if (ax < xmin) ax = xmin; |
|---|
| 663 | bx = xguess; |
|---|
| 664 | cx = xguess + eps; |
|---|
| 665 | if (cx > xmax) cx = xmax; |
|---|
| 666 | |
|---|
| 667 | /* check if this works */ |
|---|
| 668 | fa = (*f)(ax); |
|---|
| 669 | fb = (*f)(bx); |
|---|
| 670 | fc = (*f)(cx); |
|---|
| 671 | |
|---|
| 672 | /* if it works use these borders else be conservative */ |
|---|
| 673 | if ((fa < fb) || (fc < fb)) { |
|---|
| 674 | if (ax != xmin) fa = (*f)(xmin); |
|---|
| 675 | if (cx != xmax) fc = (*f)(xmax); |
|---|
| 676 | optx = brent(xmin, xguess, xmax, f, tol, fx, f2x, fa, fb, fc); |
|---|
| 677 | } else |
|---|
| 678 | optx = brent(ax, bx, cx, f, tol, fx, f2x, fa, fb, fc); |
|---|
| 679 | |
|---|
| 680 | return optx; /* return optimal x */ |
|---|
| 681 | } |
|---|
| 682 | |
|---|
| 683 | /* two-dimensional minimization with borders and calculations of standard errors */ |
|---|
| 684 | /* we optimize along basis vectors - not very optimal but it seems to work well */ |
|---|
| 685 | void twodimenmin(double tol, |
|---|
| 686 | int active1, double min1, double *x1, double max1, double (*func1)(double), double *err1, |
|---|
| 687 | int active2, double min2, double *x2, double max2, double (*func2)(double), double *err2) |
|---|
| 688 | { |
|---|
| 689 | int it, nump, change; |
|---|
| 690 | double x1old, x2old; |
|---|
| 691 | double fx, f2x; |
|---|
| 692 | |
|---|
| 693 | it = 0; |
|---|
| 694 | nump = 0; |
|---|
| 695 | |
|---|
| 696 | /* count number of parameters */ |
|---|
| 697 | if (active1) nump++; |
|---|
| 698 | if (active2) nump++; |
|---|
| 699 | |
|---|
| 700 | do { /* repeat until nothing changes any more */ |
|---|
| 701 | it++; |
|---|
| 702 | change = FALSE; |
|---|
| 703 | |
|---|
| 704 | /* optimize first variable */ |
|---|
| 705 | if (active1) { |
|---|
| 706 | |
|---|
| 707 | if ((*x1) <= min1) (*x1) = min1 + 0.2*(max1-min1); |
|---|
| 708 | if ((*x1) >= max1) (*x1) = max1 - 0.2*(max1-min1); |
|---|
| 709 | x1old = (*x1); |
|---|
| 710 | (*x1) = onedimenmin(min1, (*x1), max1, func1, tol, &fx, &f2x); |
|---|
| 711 | if ((*x1) < min1) (*x1) = min1; |
|---|
| 712 | if ((*x1) > max1) (*x1) = max1; |
|---|
| 713 | /* same tolerance as 1D minimization */ |
|---|
| 714 | if (fabs((*x1) - x1old) > 3.3*tol) change = TRUE; |
|---|
| 715 | |
|---|
| 716 | /* standard error */ |
|---|
| 717 | f2x = fabs(f2x); |
|---|
| 718 | if (1.0/(max1*max1) < f2x) (*err1) = sqrt(1.0/f2x); |
|---|
| 719 | else (*err1) = max1; |
|---|
| 720 | |
|---|
| 721 | } |
|---|
| 722 | |
|---|
| 723 | /* optimize second variable */ |
|---|
| 724 | if (active2) { |
|---|
| 725 | |
|---|
| 726 | if ((*x2) <= min2) (*x2) = min2 + 0.2*(max2-min2); |
|---|
| 727 | if ((*x2) >= max2) (*x2) = max2 - 0.2*(max2-min2); |
|---|
| 728 | x2old = (*x2); |
|---|
| 729 | (*x2) = onedimenmin(min2, (*x2), max2, func2, tol, &fx, &f2x); |
|---|
| 730 | if ((*x2) < min2) (*x2) = min2; |
|---|
| 731 | if ((*x2) > max2) (*x2) = max2; |
|---|
| 732 | /* same tolerance as 1D minimization */ |
|---|
| 733 | if (fabs((*x2) - x2old) > 3.3*tol) change = TRUE; |
|---|
| 734 | |
|---|
| 735 | /* standard error */ |
|---|
| 736 | f2x = fabs(f2x); |
|---|
| 737 | if (1.0/(max2*max2) < f2x) (*err2) = sqrt(1.0/f2x); |
|---|
| 738 | else (*err2) = max2; |
|---|
| 739 | |
|---|
| 740 | } |
|---|
| 741 | |
|---|
| 742 | if (nump == 1) return; |
|---|
| 743 | |
|---|
| 744 | } while (it != MAXITS && change); |
|---|
| 745 | |
|---|
| 746 | return; |
|---|
| 747 | } |
|---|
| 748 | |
|---|