123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include "soft-fp.h"
- #include "single.h"
- #include "double.h"
- #include <fpu_control.h>
- /*======================================================================*/
- /* declarations for the functions we are testing */
- double __adddf3(double, double);
- double __subdf3(double, double);
- double __muldf3(double, double);
- double __divdf3(double, double);
- double __negdf2(double);
- double __sqrtdf2(double);
- double __negdf3(double a, double dummy) { return __negdf2(a); }
- double __sqrtdf3(double a, double dummy) { return __sqrtdf2(a); }
- float __addsf3(float, float);
- float __subsf3(float, float);
- float __mulsf3(float, float);
- float __divsf3(float, float);
- float __negsf2(float);
- float __sqrtsf2(float);
- float __negsf3(float a, float dummy) { return __negsf2(a); }
- float __sqrtsf3(float a, float dummy) { return __sqrtsf2(a); }
- int __fixdfsi(double);
- int __fixsfsi(float);
- double __floatsidf(int);
- float __floatsisf(int);
- double __extendsfdf2(float);
- float __truncdfsf2(double);
- int __eqdf2(double, double);
- int __nedf2(double, double);
- int __gtdf2(double, double);
- int __gedf2(double, double);
- int __ltdf2(double, double);
- int __ledf2(double, double);
- int __eqsf2(float, float);
- int __nesf2(float, float);
- int __gtsf2(float, float);
- int __gesf2(float, float);
- int __ltsf2(float, float);
- int __lesf2(float, float);
- /*======================================================================*/
- /* definitions for functions we are checking against */
- double r_adddf3(double a, double b) { return a + b; }
- double r_subdf3(double a, double b) { return a - b; }
- double r_muldf3(double a, double b) { return a * b; }
- double r_divdf3(double a, double b) { return a / b; }
- double r_negdf3(double a, double b) { return -a; }
- double sqrt(double x);
- double r_sqrtdf3(double a, double b) { return sqrt(a); }
- float r_addsf3(float a, float b) { return a + b; }
- float r_subsf3(float a, float b) { return a - b; }
- float r_mulsf3(float a, float b) { return a * b; }
- float r_divsf3(float a, float b) { return a / b; }
- float r_negsf3(float a, float b) { return -a; }
- float sqrtf(float x);
- float r_sqrtsf3(float a, float b) { return sqrtf(a); }
- int r_fixdfsi(double a) { return (int)a; }
- int r_fixsfsi(float a) { return (int)a; }
- double r_floatsidf(int a) { return (double)a; }
- float r_floatsisf(int a) { return (float)a; }
- double r_extendsfdf2(float a) { return (double)a; }
- float r_truncdfsf2(double a) { return (float)a; }
- int r_eqdf2(double a, double b) { return !(a == b); }
- int r_nedf2(double a, double b) { return a != b; }
- int r_gtdf2(double a, double b) { return a > b; }
- int r_gedf2(double a, double b) { return (a >= b) - 1; }
- int r_ltdf2(double a, double b) { return -(a < b); }
- int r_ledf2(double a, double b) { return 1 - (a <= b); }
- int r_eqsf2(float a, float b) { return !(a == b); }
- int r_nesf2(float a, float b) { return a != b; }
- int r_gtsf2(float a, float b) { return a > b; }
- int r_gesf2(float a, float b) { return (a >= b) - 1; }
- int r_ltsf2(float a, float b) { return -(a < b); }
- int r_lesf2(float a, float b) { return 1 - (a <= b); }
- /*======================================================================*/
- void print_float(float x)
- {
- union _FP_UNION_S ux;
- ux.flt = x;
- printf("%-20.8e %X %02X %06lX",
- x, ux.bits.sign, ux.bits.exp, (unsigned long)ux.bits.frac);
- }
- void print_double(double x)
- {
- union _FP_UNION_D ux;
- ux.flt = x;
- #if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
- printf("%-30.18e %X %04X %06lX%08lX",
- x, ux.bits.sign, ux.bits.exp,
- (unsigned long)ux.bits.frac1, (unsigned long)ux.bits.frac0);
- #else
- printf("%-30.18e %X %04X %014lX",
- x, ux.bits.sign, ux.bits.exp,
- (unsigned long)ux.bits.frac);
- #endif
- }
- float rand_float(void)
- {
- union {
- union _FP_UNION_S u;
- int i;
- } u;
- u.i = lrand48() << 1;
- if (u.u.bits.exp == _FP_EXPMAX_S)
- u.u.bits.exp--;
- else if (u.u.bits.exp == 0 && u.u.bits.frac != 0)
- u.u.bits.exp++;
- return u.u.flt;
- }
- double rand_double(void)
- {
- union {
- union _FP_UNION_D u;
- int i[2];
- } u;
- u.i[0] = lrand48() << 1;
- u.i[1] = lrand48() << 1;
- if (u.u.bits.exp == _FP_EXPMAX_D)
- u.u.bits.exp--;
- #if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
- else if (u.u.bits.exp == 0 && !(u.u.bits.frac0 == 0 && u.u.bits.frac1 == 0))
- u.u.bits.exp++;
- #else
- else if (u.u.bits.exp == 0 && u.u.bits.frac != 0)
- u.u.bits.exp++;
- #endif
- return u.u.flt;
- }
- #define NSPECIALS 10
- float gen_special_float(int i)
- {
- FP_DECL_EX;
- FP_DECL_S(X);
- float x;
- switch (i & ~1)
- {
- case 0:
- X_c = FP_CLS_NAN; X_f = 0x1234;
- break;
- case 2:
- X_c = FP_CLS_NAN; X_f = 0x1;
- break;
- case 4:
- X_c = FP_CLS_INF;
- break;
- case 6:
- X_c = FP_CLS_ZERO;
- break;
- case 8:
- X_c = FP_CLS_NORMAL; X_e = 0;
- X_f = 0x4321;
- break;
- }
- X_s = (i & 1);
- FP_PACK_S(x, X);
- return x;
- }
- double gen_special_double(int i)
- {
- FP_DECL_EX;
- FP_DECL_D(X);
- double x;
- switch (i & ~1)
- {
- case 0:
- X_c = FP_CLS_NAN;
- #if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
- __FP_FRAC_SET_2(X, _FP_QNANNEGATEDP ? 0 : _FP_QNANBIT_D, 0x1234);
- #else
- _FP_FRAC_SET_1(X, (_FP_QNANNEGATEDP ? 0 : _FP_QNANBIT_D) | 0x1234);
- #endif
- break;
- case 2:
- X_c = FP_CLS_NAN;
- #if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
- __FP_FRAC_SET_2(X, _FP_QNANNEGATEDP ? 0 : _FP_QNANBIT_D, 0x1);
- #else
- _FP_FRAC_SET_1(X, (_FP_QNANNEGATEDP ? 0 : _FP_QNANBIT_D) | 0x1);
- #endif
- break;
- case 4:
- X_c = FP_CLS_INF;
- break;
- case 6:
- X_c = FP_CLS_ZERO;
- break;
- case 8:
- X_c = FP_CLS_NORMAL; X_e = 0;
- #if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
- __FP_FRAC_SET_2(X, 0, 0x87654321);
- #else
- _FP_FRAC_SET_1(X, 0x87654321);
- #endif
- break;
- }
- X_s = (i & 1);
- FP_PACK_D(x, X);
- return x;
- }
- float build_float(const char *s, const char *e, const char *f)
- {
- union _FP_UNION_S u;
- u.bits.sign = strtoul(s, 0, 16);
- u.bits.exp = strtoul(e, 0, 16);
- u.bits.frac = strtoul(f, 0, 16);
- return u.flt;
- }
- double build_double(const char *s, const char *e, const char *f)
- {
- union _FP_UNION_D u;
- u.bits.sign = strtoul(s, 0, 16);
- u.bits.exp = strtoul(e, 0, 16);
- #if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
- {
- size_t len = strlen(f)+1;
- char *dup = memcpy(alloca(len), f, len);
- char *low = dup + len - _FP_W_TYPE_SIZE/4 - 1;
- u.bits.frac0 = strtoul(low, 0, 16);
- *low = 0;
- u.bits.frac1 = strtoul(dup, 0, 16);
- }
- #else
- u.bits.frac = strtoul(f, 0, 16);
- #endif
- return u.flt;
- }
- /*======================================================================*/
- fpu_control_t fcw0, fcw1;
- void test_float_arith(float (*tf)(float, float),
- float (*rf)(float, float),
- float x, float y)
- {
- float tr, rr;
- rr = (*rf)(x, y);
- tr = (*tf)(x, y);
- if (memcmp(&tr, &rr, sizeof(float)) != 0)
- {
- fputs("error:\n\tx = ", stdout); print_float(x);
- fputs("\n\ty = ", stdout); print_float(y);
- fputs("\n\ttrue = ", stdout); print_float(rr);
- fputs("\n\tfalse = ", stdout); print_float(tr);
- putchar('\n');
- }
- }
- void test_double_arith(double (*tf)(double, double),
- double (*rf)(double, double),
- double x, double y)
- {
- double tr, rr;
- #ifdef __i386__
- /* Don't worry. Even this does not make it error free
- on ia32. If the result is denormal, it will not
- honour the double precision and generate bad results
- anyway. On the other side, who wants to use ia32
- for IEEE math? I don't. */
- _FPU_GETCW(fcw0);
- fcw1 = ((fcw0 & ~_FPU_EXTENDED) | _FPU_DOUBLE);
- _FPU_SETCW(fcw1);
- #endif
- rr = (*rf)(x, y);
- #ifdef __i386__
- _FPU_SETCW(fcw0);
- #endif
- tr = (*tf)(x, y);
- if (memcmp(&tr, &rr, sizeof(double)) != 0)
- {
- fputs("error:\n\tx = ", stdout); print_double(x);
- fputs("\n\ty = ", stdout); print_double(y);
- fputs("\n\ttrue = ", stdout); print_double(rr);
- fputs("\n\tfalse = ", stdout); print_double(tr);
- putchar('\n');
- }
- }
- void test_float_double_conv(float x)
- {
- double tr, rr;
- rr = r_extendsfdf2(x);
- tr = __extendsfdf2(x);
- if (memcmp(&tr, &rr, sizeof(double)) != 0)
- {
- fputs("error:\n\tx = ", stdout); print_float(x);
- fputs("\n\ttrue = ", stdout); print_double(rr);
- fputs("\n\tfalse = ", stdout); print_double(tr);
- putchar('\n');
- }
- }
- void test_double_float_conv(double x)
- {
- float tr, rr;
- rr = r_truncdfsf2(x);
- tr = __truncdfsf2(x);
- if (memcmp(&tr, &rr, sizeof(float)) != 0)
- {
- fputs("error:\n\tx = ", stdout); print_double(x);
- fputs("\n\ttrue = ", stdout); print_float(rr);
- fputs("\n\tfalse = ", stdout); print_float(tr);
- putchar('\n');
- }
- }
- void test_int_float_conv(int x)
- {
- float tr, rr;
- rr = r_floatsisf(x);
- tr = __floatsisf(x);
- if (memcmp(&tr, &rr, sizeof(float)) != 0)
- {
- printf("error\n\tx = %d", x);
- fputs("\n\ttrue = ", stdout); print_float(rr);
- fputs("\n\tfalse = ", stdout); print_float(tr);
- putchar('\n');
- }
- }
- void test_int_double_conv(int x)
- {
- double tr, rr;
- rr = r_floatsidf(x);
- tr = __floatsidf(x);
- if (memcmp(&tr, &rr, sizeof(double)) != 0)
- {
- printf("error\n\tx = %d", x);
- fputs("\n\ttrue = ", stdout); print_double(rr);
- fputs("\n\tfalse = ", stdout); print_double(tr);
- putchar('\n');
- }
- }
- void test_float_int_conv(float x)
- {
- int tr, rr;
- rr = r_fixsfsi(x);
- tr = __fixsfsi(x);
- if (rr != tr)
- {
- fputs("error:\n\tx = ", stdout); print_float(x);
- printf("\n\ttrue = %d\n\tfalse = %d\n", rr, tr);
- }
- }
- void test_double_int_conv(double x)
- {
- int tr, rr;
- rr = r_fixsfsi(x);
- tr = __fixsfsi(x);
- if (rr != tr)
- {
- fputs("error:\n\tx = ", stdout); print_double(x);
- printf("\n\ttrue = %d\n\tfalse = %d\n", rr, tr);
- }
- }
- int eq0(int x) { return x == 0; }
- int ne0(int x) { return x != 0; }
- int le0(int x) { return x <= 0; }
- int lt0(int x) { return x < 0; }
- int ge0(int x) { return x >= 0; }
- int gt0(int x) { return x > 0; }
- void test_float_cmp(int (*tf)(float, float),
- int (*rf)(float, float),
- int (*cmp0)(int),
- float x, float y)
- {
- int tr, rr;
- rr = (*rf)(x, y);
- tr = (*tf)(x, y);
- if (cmp0(rr) != cmp0(tr))
- {
- fputs("error:\n\tx = ", stdout); print_float(x);
- fputs("\n\ty = ", stdout); print_float(y);
- printf("\n\ttrue = %d\n\tfalse = %d\n", rr, tr);
- }
- }
- void test_double_cmp(int (*tf)(double, double),
- int (*rf)(double, double),
- int (*cmp0)(int),
- double x, double y)
- {
- int tr, rr;
- rr = (*rf)(x, y);
- tr = (*tf)(x, y);
- if (cmp0(rr) != cmp0(tr))
- {
- fputs("error:\n\tx = ", stdout); print_double(x);
- fputs("\n\ty = ", stdout); print_double(y);
- printf("\n\ttrue = %d\n\tfalse = %d\n", rr, tr);
- }
- }
- /*======================================================================*/
- int main(int ac, char **av)
- {
- #ifdef __alpha__
- __ieee_set_fp_control(0);
- #endif
- av++, ac--;
- switch (*(*av)++)
- {
- {
- float (*r)(float, float);
- float (*t)(float, float);
- do {
- case 'a': r = r_addsf3; t = __addsf3; break;
- case 's': r = r_subsf3; t = __subsf3; break;
- case 'm': r = r_mulsf3; t = __mulsf3; break;
- case 'd': r = r_divsf3; t = __divsf3; break;
- case 'r': r = r_sqrtsf3; t = __sqrtsf3; break;
- case 'j': r = r_negsf3; t = __negsf3; break;
- } while (0);
- switch (*(*av)++)
- {
- case 'n':
- {
- int count = (ac > 1 ? atoi(av[1]) : 100);
- while (count--)
- test_float_arith(t, r, rand_float(), rand_float());
- }
- break;
- case 's':
- {
- int i, j;
- for (i = 0; i < NSPECIALS; i++)
- for (j = 0; j < NSPECIALS; j++)
- test_float_arith(t, r, gen_special_float(i),
- gen_special_float(j));
- }
- break;
- case 0:
- if (ac < 7) abort();
- test_float_arith(t, r, build_float(av[1], av[2], av[3]),
- build_float(av[4], av[5], av[6]));
- break;
- }
- }
- break;
- {
- double (*r)(double, double);
- double (*t)(double, double);
- do {
- case 'A': r = r_adddf3; t = __adddf3; break;
- case 'S': r = r_subdf3; t = __subdf3; break;
- case 'M': r = r_muldf3; t = __muldf3; break;
- case 'D': r = r_divdf3; t = __divdf3; break;
- case 'R': r = r_sqrtdf3; t = __sqrtdf3; break;
- case 'J': r = r_negdf3; t = __negdf3; break;
- } while (0);
- switch (*(*av)++)
- {
- case 'n':
- {
- int count = (ac > 1 ? atoi(av[1]) : 100);
- while (count--)
- test_double_arith(t, r, rand_double(), rand_double());
- }
- break;
- case 's':
- {
- int i, j;
- for (i = 0; i < NSPECIALS; i++)
- for (j = 0; j < NSPECIALS; j++)
- test_double_arith(t, r, gen_special_double(i),
- gen_special_double(j));
- }
- break;
- case 0:
- if (ac < 7) abort();
- test_double_arith(t, r, build_double(av[1], av[2], av[3]),
- build_double(av[4], av[5], av[6]));
- break;
- }
- }
- break;
- case 'c':
- switch (*(*av)++)
- {
- case 'n':
- {
- int count = (ac > 1 ? atoi(av[1]) : 100);
- while (count--)
- test_float_double_conv(rand_float());
- }
- break;
- case 's':
- {
- int i;
- for (i = 0; i < NSPECIALS; i++)
- test_float_double_conv(gen_special_float(i));
- }
- break;
- case 0:
- if (ac < 4) abort();
- test_float_double_conv(build_float(av[1], av[2], av[3]));
- break;
- }
- break;
- case 'C':
- switch (*(*av)++)
- {
- case 'n':
- {
- int count = (ac > 1 ? atoi(av[1]) : 100);
- while (count--)
- test_double_float_conv(rand_double());
- }
- break;
- case 's':
- {
- int i;
- for (i = 0; i < NSPECIALS; i++)
- test_double_float_conv(gen_special_double(i));
- }
- break;
- case 0:
- if (ac < 4) abort();
- test_double_float_conv(build_double(av[1], av[2], av[3]));
- break;
- }
- break;
- case 'i':
- switch (*(*av)++)
- {
- case 'n':
- {
- int count = (ac > 1 ? atoi(av[1]) : 100);
- while (count--)
- test_int_float_conv(lrand48() << 1);
- }
- break;
- case 0:
- if (ac < 2) abort();
- test_int_float_conv(strtol(av[1], 0, 0));
- break;
- }
- break;
- case 'I':
- switch (*(*av)++)
- {
- case 'n':
- {
- int count = (ac > 1 ? atoi(av[1]) : 100);
- while (count--)
- test_int_double_conv(lrand48() << 1);
- }
- break;
- case 0:
- if (ac < 2) abort();
- test_int_double_conv(strtol(av[1], 0, 0));
- break;
- }
- break;
- case 'f':
- switch (*(*av)++)
- {
- case 'n':
- {
- int count = (ac > 1 ? atoi(av[1]) : 100);
- while (count--)
- test_float_int_conv(rand_float());
- }
- break;
- case 's':
- {
- int i;
- for (i = 0; i < NSPECIALS; i++)
- test_float_int_conv(gen_special_float(i));
- }
- break;
- case 0:
- if (ac < 4) abort();
- test_float_int_conv(build_float(av[1], av[2], av[3]));
- break;
- }
- break;
- case 'F':
- switch (*(*av)++)
- {
- case 'n':
- {
- int count = (ac > 1 ? atoi(av[1]) : 100);
- while (count--)
- test_double_int_conv(rand_double());
- }
- break;
- case 's':
- {
- int i;
- for (i = 0; i < NSPECIALS; i++)
- test_double_int_conv(gen_special_double(i));
- }
- break;
- case 0:
- if (ac < 4) abort();
- test_double_int_conv(build_double(av[1], av[2], av[3]));
- break;
- }
- break;
- {
- int (*r)(float, float);
- int (*t)(float, float);
- int (*c)(int);
- do {
- case 'e': r = r_eqsf2; t = __eqsf2; c = eq0; break;
- case 'n': r = r_nesf2; t = __nesf2; c = ne0; break;
- case 'l':
- switch (*(*av)++)
- {
- case 'e': r = r_lesf2; t = __lesf2; c = le0; break;
- case 't': r = r_ltsf2; t = __ltsf2; c = lt0; break;
- }
- break;
- case 'g':
- switch (*(*av)++)
- {
- case 'e': r = r_gesf2; t = __gesf2; c = ge0; break;
- case 't': r = r_gtsf2; t = __gtsf2; c = gt0; break;
- }
- break;
- } while (0);
- switch (*(*av)++)
- {
- case 'n':
- {
- int count = (ac > 1 ? atoi(av[1]) : 100);
- while (count--)
- test_float_cmp(t, r, c, rand_float(), rand_float());
- }
- break;
- case 's':
- {
- int i, j;
- for (i = 0; i < NSPECIALS; i++)
- for (j = 0; j < NSPECIALS; j++)
- test_float_cmp(t, r, c, gen_special_float(i),
- gen_special_float(j));
- }
- break;
- case 0:
- if (ac < 7) abort();
- test_float_cmp(t, r, c, build_float(av[1], av[2], av[3]),
- build_float(av[4], av[5], av[6]));
- break;
- }
- }
- break;
- {
- int (*r)(double, double);
- int (*t)(double, double);
- int (*c)(int);
- do {
- case 'E': r = r_eqdf2; t = __eqdf2; c = eq0; break;
- case 'N': r = r_nedf2; t = __nedf2; c = ne0; break;
- case 'L':
- switch (*(*av)++)
- {
- case 'E': r = r_ledf2; t = __ledf2; c = le0; break;
- case 'T': r = r_ltdf2; t = __ltdf2; c = lt0; break;
- }
- break;
- case 'G':
- switch (*(*av)++)
- {
- case 'E': r = r_gedf2; t = __gedf2; c = ge0; break;
- case 'T': r = r_gtdf2; t = __gtdf2; c = gt0; break;
- }
- break;
- } while (0);
- switch (*(*av)++)
- {
- case 'n':
- {
- int count = (ac > 1 ? atoi(av[1]) : 100);
- while (count--)
- test_double_cmp(t, r, c, rand_double(), rand_double());
- }
- break;
- case 's':
- {
- int i, j;
- for (i = 0; i < NSPECIALS; i++)
- for (j = 0; j < NSPECIALS; j++)
- test_double_cmp(t, r, c, gen_special_double(i),
- gen_special_double(j));
- }
- break;
- case 0:
- if (ac < 7) abort();
- test_double_cmp(t, r, c, build_double(av[1], av[2], av[3]),
- build_double(av[4], av[5], av[6]));
- break;
- }
- }
- break;
- default:
- abort();
- }
- return 0;
- }
|