Viewing file: pr36584.c (4.65 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/* { dg-do run } */ /* { dg-options "-O2 -lm" } */ /* { dg-options "-O2 -msse2 -mfpmath=sse" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */ /* { dg-require-effective-target sse2_runtime { target { { i?86-*-* x86_64-*-* } && ia32 } } } */
extern double fabs (double); extern void abort (void);
const int MAX_ITERATIONS = 50; const double SMALL_ENOUGH = 1.0e-10; const double RELERROR = 1.0e-12;
typedef struct p { int ord; double coef[7]; } polynomial;
static double polyeval (double x, int n, double *Coeffs) { register int i; double val;
val = Coeffs[n]; for (i = n - 1; i >= 0; i--) val = val * x + Coeffs[i];
return (val); }
static int regula_falsa (int order, double *coef, double a, double b, double *val) { int its; double fa, fb, x, fx, lfx;
fa = polyeval (a, order, coef); fb = polyeval (b, order, coef);
if (fa * fb > 0.0) return 0;
if (fabs (fa) < SMALL_ENOUGH) { *val = a; return 1; }
if (fabs (fb) < SMALL_ENOUGH) { *val = b; return 1; }
lfx = fa;
for (its = 0; its < MAX_ITERATIONS; its++) { x = (fb * a - fa * b) / (fb - fa); fx = polyeval (x, order, coef); if (fabs (x) > RELERROR) { if (fabs (fx / x) < RELERROR) { *val = x; return 1; } } else { if (fabs (fx) < RELERROR) { *val = x; return 1; } }
if (fa < 0) { if (fx < 0) { a = x; fa = fx; if ((lfx * fx) > 0) fb /= 2; } else { b = x; fb = fx; if ((lfx * fx) > 0) fa /= 2; } } else { if (fx < 0) { b = x; fb = fx; if ((lfx * fx) > 0) fa /= 2; } else { a = x; fa = fx; if ((lfx * fx) > 0) fb /= 2; } }
if (fabs (b - a) < RELERROR) { *val = x; return 1; }
lfx = fx; }
return 0; }
static int numchanges (int np, polynomial * sseq, double a) { int changes; double f, lf; polynomial *s; changes = 0;
lf = polyeval (a, sseq[0].ord, sseq[0].coef);
for (s = sseq + 1; s <= sseq + np; s++) { f = polyeval (a, s->ord, s->coef); if (lf == 0.0 || lf * f < 0) changes++;
lf = f; }
return changes; }
int sbisect (int np, polynomial * sseq, double min_value, double max_value, int atmin, int atmax, double *roots) { double mid; int n1, n2, its, atmid;
if ((atmin - atmax) == 1) { if (regula_falsa (sseq->ord, sseq->coef, min_value, max_value, roots)) return 1; else { for (its = 0; its < MAX_ITERATIONS; its++) { mid = (min_value + max_value) / 2; atmid = numchanges (np, sseq, mid); if ((atmid < atmax) || (atmid > atmin)) return 0;
if (fabs (mid) > RELERROR) { if (fabs ((max_value - min_value) / mid) < RELERROR) { roots[0] = mid; return 1; } } else { if (fabs (max_value - min_value) < RELERROR) { roots[0] = mid; return 1; } }
if ((atmin - atmid) == 0) min_value = mid; else max_value = mid; }
roots[0] = mid; return 1; } }
for (its = 0; its < MAX_ITERATIONS; its++) { mid = (min_value + max_value) / 2; atmid = numchanges (np, sseq, mid); if ((atmid < atmax) || (atmid > atmin)) return 0;
if (fabs (mid) > RELERROR) { if (fabs ((max_value - min_value) / mid) < RELERROR) { roots[0] = mid; return 1; } } else { if (fabs (max_value - min_value) < RELERROR) { roots[0] = mid; return 1; } }
n1 = atmin - atmid; n2 = atmid - atmax;
if ((n1 != 0) && (n2 != 0)) { n1 = sbisect (np, sseq, min_value, mid, atmin, atmid, roots); n2 = sbisect (np, sseq, mid, max_value, atmid, atmax, &roots[n1]);
return (n1 + n2); }
if (n1 == 0) min_value = mid; else max_value = mid; }
roots[0] = mid; return 1; }
int main () { polynomial sseq[7] = { {6, {0.15735259075109281, -5.1185263411378736, 1.8516070705868664, 7.348009172322695, -2.2152395279161343, -2.7543325329350692, 1.0}}, {5, {-0.8530877235229789, 0.61720235686228875, 3.6740045861613475, -1.4768263519440896, -2.2952771107792245, 1.0}}, {4, {0.13072124257049417, 2.2220687798791126, -1.6299431586726509, -1.6718404582408546, 1.0}}, {3, {0.86776597575462633, -2.1051099695282511, -0.49008580100694688, 1.0}}, {2, {-11.117984175064155, 10.89886635045883, 1.0}}, {1, {0.94453099602191237, -1.0}}, {0, {-0.068471716890574186}} };
double roots[7]; int nroots;
nroots = sbisect (6, sseq, 0.0, 10000000.0, 5, 1, roots); if (nroots != 4) abort ();
return 0; }
|