00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #define PRINT_LEVEL 0
00030 #define MAX_ORDER 16
00031 #define MAXPOW 32
00032 #define SMALL_ENOUGH 1.0e-18
00033
00034
00035
00036
00037 typedef struct p {
00038 int ord;
00039 double coef[MAX_ORDER+1];
00040 } poly;
00041
00042 double RELERROR;
00043 int MAXIT, MAX_ITER_SECANT;
00044
00045 void initialize_sturm(double *tol_secant, int *max_iter_sturm, int *max_iter_secant);
00046 void solve_sturm(int *p_order, int *n_root, double *poly_coeffs, double *roots);
00047 double hyper_tan(double a, double x);
00048 static int modp(poly *u, poly *v, poly *r);
00049 int buildsturm(int ord, poly *sseq);
00050 int numroots(int np, poly *sseq, int *atneg, int *atpos);
00051 int numchanges(int np, poly *sseq, double a);
00052 void sbisect(int np, poly *sseq, double min, double max, int atmin, int atmax, double *roots);
00053 double evalpoly(int ord, double *coef, double x);
00054 int modrf(int ord, double *coef, double a, double b, double *val);
00055
00056
00057 void initialize_sturm(double *tol_secant, int *max_iter_sturm, int *max_iter_secant)
00058 {
00059 RELERROR = *tol_secant;
00060 MAXIT = *max_iter_sturm;
00061 MAX_ITER_SECANT = *max_iter_secant;
00062 }
00063
00064 void solve_sturm(int *p_order, int *n_root, double *poly_coeffs, double *roots)
00065 {
00066 poly sseq[MAX_ORDER*2];
00067 double min, max;
00068 int order, i, j, nroots, nchanges, np, atmin, atmax;
00069
00070 order = *p_order;
00071
00072 for (i = order; i >= 0; i--)
00073 {
00074 sseq[0].coef[i] = poly_coeffs[i];
00075 }
00076
00077 if (PRINT_LEVEL > 0)
00078 {
00079 for (i = order; i >= 0; i--)
00080 {
00081 printf("coefficients in Sturm solver\n");
00082 printf("%d %lf\n", i, sseq[0].coef[i]);
00083 }
00084 }
00085
00086
00087
00088
00089 np = buildsturm(order, sseq);
00090
00091 if (PRINT_LEVEL > 0)
00092 {
00093 printf("Sturm sequence for:\n");
00094 for (i = order; i >= 0; i--)
00095 printf("%lf ", sseq[0].coef[i]);
00096 printf("\n\n");
00097 for (i = 0; i <= np; i++)
00098 {
00099 for (j = sseq[i].ord; j >= 0; j--)
00100 printf("%lf ", sseq[i].coef[j]);
00101 printf("\n");
00102 }
00103 printf("\n");
00104 }
00105
00106
00107
00108
00109
00110 nroots = numroots(np, sseq, &atmin, &atmax);
00111
00112
00113 if (nroots == 0)
00114 {
00115
00116 *n_root = nroots;
00117 return;
00118 }
00119
00120 if (PRINT_LEVEL > 0)
00121 printf("Number of real roots: %d\n", nroots);
00122
00123
00124
00125
00126 min = -1.0;
00127 nchanges = numchanges(np, sseq, min);
00128
00129 for (i = 0; nchanges != atmin && i != MAXPOW; i++) {
00130 min *= 10.0;
00131 nchanges = numchanges(np, sseq, min);
00132 }
00133
00134 if (nchanges != atmin) {
00135 printf("solve: unable to bracket all negative roots\n");
00136 atmin = nchanges;
00137 }
00138
00139 max = 1.0;
00140 nchanges = numchanges(np, sseq, max);
00141 for (i = 0; nchanges != atmax && i != MAXPOW; i++) {
00142 max *= 10.0;
00143 nchanges = numchanges(np, sseq, max);
00144 }
00145
00146 if (nchanges != atmax) {
00147 printf("solve: unable to bracket all positive roots\n");
00148 atmax = nchanges;
00149 }
00150
00151 nroots = atmin - atmax;
00152
00153
00154
00155
00156
00157 sbisect(np, sseq, min, max, atmin, atmax, roots);
00158
00159 *n_root = nroots;
00160
00161
00162
00163
00164 if (PRINT_LEVEL > 0)
00165 {
00166 if (nroots == 1) {
00167 printf("\n1 distinct real root at x = %f\n", roots[0]);
00168 } else {
00169 printf("\n%d distinct real roots for x: \n", nroots);
00170
00171 for (i = 0; i != nroots; i++)
00172 {
00173 printf("%f\n", roots[i]);
00174 }
00175 }
00176 }
00177
00178 return;
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 double hyper_tan(double a, double x)
00191 {
00192 double exp_x1, exp_x2, ax;
00193
00194 ax = a*x;
00195 if (ax > 100.0)
00196 {
00197 return(1.0);
00198 }
00199 else if (ax < -100.0)
00200 {
00201 return(-1.0);
00202 }
00203 else
00204 {
00205 exp_x1 = exp(ax);
00206 exp_x2 = exp(-ax);
00207 return (exp_x1 - exp_x2)/(exp_x1 + exp_x2);
00208 }
00209 }
00210
00211 static int modp(poly *u, poly *v, poly *r)
00212
00213 {
00214 int k, j;
00215 double *nr, *end, *uc;
00216
00217 nr = r->coef;
00218 end = &u->coef[u->ord];
00219
00220 uc = u->coef;
00221 while (uc <= end)
00222 *nr++ = *uc++;
00223
00224 if (v->coef[v->ord] < 0.0) {
00225
00226
00227 for (k = u->ord - v->ord - 1; k >= 0; k -= 2)
00228 r->coef[k] = -r->coef[k];
00229
00230 for (k = u->ord - v->ord; k >= 0; k--)
00231 for (j = v->ord + k - 1; j >= k; j--)
00232 r->coef[j] = -r->coef[j] - r->coef[v->ord + k]
00233 * v->coef[j - k];
00234 } else {
00235 for (k = u->ord - v->ord; k >= 0; k--)
00236 for (j = v->ord + k - 1; j >= k; j--)
00237 r->coef[j] -= r->coef[v->ord + k] * v->coef[j - k];
00238 }
00239
00240 k = v->ord - 1;
00241 while (k >= 0 && fabs(r->coef[k]) < SMALL_ENOUGH) {
00242 r->coef[k] = 0.0;
00243 k--;
00244 }
00245
00246 r->ord = (k < 0) ? 0 : k;
00247
00248 return(r->ord);
00249 }
00250
00251
00252
00253
00254
00255
00256
00257 int buildsturm(int ord, poly *sseq)
00258
00259
00260 {
00261 int i;
00262 double f, *fp, *fc;
00263 poly *sp;
00264
00265 sseq[0].ord = ord;
00266 sseq[1].ord = ord - 1;
00267
00268
00269
00270
00271
00272 f = fabs(sseq[0].coef[ord]*ord);
00273
00274 fp = sseq[1].coef;
00275 fc = sseq[0].coef + 1;
00276
00277 for (i = 1; i <= ord; i++)
00278 {
00279 *fp++ = *fc++ * i / f;
00280 }
00281
00282
00283
00284
00285
00286
00287 for (sp = sseq + 2; modp(sp - 2, sp - 1, sp); sp++) {
00288
00289
00290
00291
00292
00293 f = -fabs(sp->coef[sp->ord]);
00294 for (fp = &sp->coef[sp->ord]; fp >= sp->coef; fp--)
00295 *fp /= f;
00296 }
00297
00298 sp->coef[0] = -sp->coef[0];
00299
00300 return(sp - sseq);
00301 }
00302
00303
00304
00305
00306
00307
00308
00309 int numroots(int np, poly *sseq, int *atneg, int *atpos)
00310
00311
00312
00313 {
00314 int atposinf, atneginf;
00315 poly *s;
00316 double f, lf;
00317
00318 atposinf = atneginf = 0;
00319
00320
00321
00322
00323
00324 lf = sseq[0].coef[sseq[0].ord];
00325
00326 for (s = sseq + 1; s <= sseq + np; s++) {
00327 f = s->coef[s->ord];
00328 if (lf == 0.0 || lf * f < 0)
00329 atposinf++;
00330 lf = f;
00331 }
00332
00333
00334
00335
00336 if (sseq[0].ord & 1)
00337 lf = -sseq[0].coef[sseq[0].ord];
00338 else
00339 lf = sseq[0].coef[sseq[0].ord];
00340
00341 for (s = sseq + 1; s <= sseq + np; s++) {
00342 if (s->ord & 1)
00343 f = -s->coef[s->ord];
00344 else
00345 f = s->coef[s->ord];
00346 if (lf == 0.0 || lf * f < 0)
00347 atneginf++;
00348 lf = f;
00349 }
00350
00351 *atneg = atneginf;
00352 *atpos = atposinf;
00353
00354 return(atneginf - atposinf);
00355 }
00356
00357
00358
00359
00360
00361
00362
00363 int numchanges(int np, poly *sseq, double a)
00364
00365
00366
00367
00368 {
00369 int changes;
00370 double f, lf;
00371 poly *s;
00372
00373 changes = 0;
00374
00375 lf = evalpoly(sseq[0].ord, sseq[0].coef, a);
00376
00377 for (s = sseq + 1; s <= sseq + np; s++) {
00378 f = evalpoly(s->ord, s->coef, a);
00379 if (lf == 0.0 || lf * f < 0)
00380 changes++;
00381 lf = f;
00382
00383 }
00384
00385
00386 return(changes);
00387 }
00388
00389
00390
00391
00392
00393
00394
00395
00396 void sbisect(int np, poly *sseq, double min, double max, int atmin, int atmax, double *roots)
00397
00398
00399
00400
00401
00402 {
00403 double mid=0.;
00404 int n1 = 0, n2 = 0, its, atmid, nroot;
00405
00406 if ((nroot = atmin - atmax) == 1)
00407 {
00408
00409
00410
00411
00412
00413 if (modrf(sseq->ord, sseq->coef, min, max, &roots[0]))
00414 return;
00415
00416
00417
00418
00419
00420
00421 for (its = 0; its < MAXIT; its++)
00422 {
00423 mid = (min + max) / 2;
00424
00425 atmid = numchanges(np, sseq, mid);
00426
00427 if (fabs(mid) > RELERROR)
00428 {
00429 if (fabs((max - min) / mid) < RELERROR)
00430 {
00431 roots[0] = mid;
00432 return;
00433 }
00434 }
00435 else if (fabs(max - min) < RELERROR)
00436 {
00437 roots[0] = mid;
00438 return;
00439 }
00440
00441 if ((atmin - atmid) == 0)
00442 min = mid;
00443 else
00444 max = mid;
00445 }
00446
00447 if (its == MAXIT)
00448 {
00449 fprintf(stderr, "sbisect: overflow min %f max %f\
00450 diff %e nroot %d n1 %d n2 %d\n",
00451 min, max, max - min, nroot, n1, n2);
00452 roots[0] = mid;
00453 }
00454 return;
00455 }
00456
00457
00458
00459
00460
00461 for (its = 0; its < MAXIT; its++)
00462 {
00463
00464 mid = (min + max) / 2;
00465
00466 atmid = numchanges(np, sseq, mid);
00467
00468 n1 = atmin - atmid;
00469 n2 = atmid - atmax;
00470
00471 if (n1 != 0 && n2 != 0)
00472 {
00473 sbisect(np, sseq, min, mid, atmin, atmid, roots);
00474 sbisect(np, sseq, mid, max, atmid, atmax, &roots[n1]);
00475 break;
00476 }
00477
00478 if (n1 == 0)
00479 min = mid;
00480 else
00481 max = mid;
00482 }
00483
00484 if (its == MAXIT)
00485 {
00486
00487
00488
00489
00490
00491
00492 for (n1 = atmax; n1 < atmin; n1++)
00493 roots[n1 - atmax] = mid;
00494 }
00495 }
00496
00497
00498
00499
00500
00501
00502 double evalpoly(int ord, double *coef, double x)
00503
00504
00505 {
00506 double *fp, f;
00507
00508 fp = &coef[ord];
00509 f = *fp;
00510
00511 for (fp--; fp >= coef; fp--)
00512 f = x * f + *fp;
00513
00514 return(f);
00515 }
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526 int modrf(int ord, double *coef, double a, double b, double *val)
00527 {
00528 int its;
00529 double fa, fb, x, fx, lfx;
00530 double *fp, *scoef, *ecoef;
00531
00532 scoef = coef;
00533 ecoef = &coef[ord];
00534
00535 fb = fa = *ecoef;
00536 for (fp = ecoef - 1; fp >= scoef; fp--) {
00537 fa = a * fa + *fp;
00538 fb = b * fb + *fp;
00539 }
00540
00541
00542
00543
00544 if (fa * fb > 0.0)
00545 return(0);
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562 lfx = fa;
00563
00564 for (its = 0; its < MAX_ITER_SECANT; its++)
00565 {
00566 x = (fb * a - fa * b) / (fb - fa);
00567
00568
00569 if (x < a || x > b)
00570 x = 0.5 * (a+b);
00571
00572 fx = *ecoef;
00573 for (fp = ecoef - 1; fp >= scoef; fp--)
00574 fx = x * fx + *fp;
00575
00576 if (fabs(x) > RELERROR)
00577 {
00578 if (fabs(fx / x) < RELERROR)
00579 {
00580 *val = x;
00581
00582 return(1);
00583 }
00584 }
00585 else if (fabs(fx) < RELERROR)
00586 {
00587 *val = x;
00588
00589 return(1);
00590 }
00591
00592 if ((fa * fx) < 0)
00593 {
00594 b = x;
00595 fb = fx;
00596 if ((lfx * fx) > 0)
00597 fa /= 2;
00598 }
00599 else
00600 {
00601 a = x;
00602 fa = fx;
00603 if ((lfx * fx) > 0)
00604 fb /= 2;
00605 }
00606
00607 lfx = fx;
00608 }
00609
00610
00611
00612 return(0);
00613 }
00614