summaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg/pr36584.c
diff options
context:
space:
mode:
authorupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
committerupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
commit554fd8c5195424bdbcabf5de30fdc183aba391bd (patch)
tree976dc5ab7fddf506dadce60ae936f43f58787092 /gcc/testsuite/gcc.dg/pr36584.c
downloadcbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2
cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository.
Diffstat (limited to 'gcc/testsuite/gcc.dg/pr36584.c')
-rw-r--r--gcc/testsuite/gcc.dg/pr36584.c267
1 files changed, 267 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.dg/pr36584.c b/gcc/testsuite/gcc.dg/pr36584.c
new file mode 100644
index 000000000..c0b005db7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr36584.c
@@ -0,0 +1,267 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -lm" } */
+/* { dg-options "-O2 -msse2 -mfpmath=sse" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
+/* { dg-require-effective-target sse2_runtime { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
+
+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;
+}