2
/* Copyright (C) 2006 Dave Nomura
5
This program is free software; you can redistribute it and/or
6
modify it under the terms of the GNU General Public License as
7
published by the Free Software Foundation; either version 2 of the
8
License, or (at your option) any later version.
10
This program is distributed in the hope that it will be useful, but
11
WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
General Public License for more details.
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20
The GNU General Public License is contained in the file COPYING.
27
typedef enum { FALSE=0, TRUE } bool_t;
30
FADDS, FSUBS, FMULS, FDIVS,
31
FMADDS, FMSUBS, FNMADDS, FNMSUBS,
32
FADD, FSUB, FMUL, FDIV, FMADD,
33
FMSUB, FNMADD, FNMSUB, FSQRT
37
TO_NEAREST=0, TO_ZERO, TO_PLUS_INFINITY, TO_MINUS_INFINITY } round_mode_t;
38
char *round_mode_name[] = { "near", "zero", "+inf", "-inf" };
40
const char *flt_op_names[] = {
41
"fadds", "fsubs", "fmuls", "fdivs",
42
"fmadds", "fmsubs", "fnmadds", "fnmsubs",
43
"fadd", "fsub", "fmul", "fdiv", "fmadd", "fmsub", "fnmadd",
47
typedef unsigned int fpscr_t;
63
unsigned int frac_hi:20;
64
unsigned int frac_lo:32;
72
void assert_fail(const char *msg,
73
const char* expr, const char* file, int line, const char*fn);
75
#define STRING(__str) #__str
76
#define assert(msg, expr) \
77
((void) ((expr) ? 0 : \
78
(assert_fail (msg, STRING(expr), \
80
__PRETTY_FUNCTION__), 0)))
82
double dbl_denorm_small;
85
bool_t long_is_64_bits = sizeof(long) == 8;
87
void assert_fail (msg, expr, file, line, fn)
94
printf( "\n%s: %s:%d (%s): Assertion `%s' failed.\n",
95
msg, file, line, fn, expr );
98
void set_rounding_mode(round_mode_t mode)
102
asm volatile("mtfsfi 7, 0");
105
asm volatile("mtfsfi 7, 1");
107
case TO_PLUS_INFINITY:
108
asm volatile("mtfsfi 7, 2");
110
case TO_MINUS_INFINITY:
111
asm volatile("mtfsfi 7, 3");
116
void print_double(char *msg, double dbl)
121
printf("%15s : dbl %-20a = %c(%4d, %05x%08x)\n",
122
msg, D.dbl, (D.layout.sign == 0 ? '+' : '-'),
123
D.layout.exp, D.layout.frac_hi, D.layout.frac_lo);
126
void print_single(char *msg, float *flt)
131
/* NOTE: for the purposes of comparing the fraction of a single with
132
** a double left shift the .frac so that hex digits are grouped
133
** from left to right. this is necessary because the size of a
134
** single mantissa (23) bits is not a multiple of 4
136
printf("%15s : flt %-20a = %c(%4d, %06x)\n",
137
msg, F.flt, (F.layout.sign == 0 ? '+' : '-'), F.layout.exp, F.layout.frac << 1);
140
int check_dbl_to_flt_round(round_mode_t mode, double dbl, float *expected)
147
set_rounding_mode(mode);
152
if ((R.layout.sign != E.layout.sign) ||
153
(R.layout.exp != E.layout.exp) ||
154
(R.layout.frac != E.layout.frac)) {
163
printf("%s:%s:(double)(%-20a) = %20a",
164
round_mode_name[mode], result, R.flt, dbl);
166
print_single("\n\texpected", &E.flt);
167
print_single("\n\trounded ", &R.flt);
173
int test_dbl_to_float_convert(char *msg, float *base)
176
double half = (double)denorm_small/2;
178
double D_hi = (double)*base + half + qtr;
179
double D_lo = (double)*base + half - qtr;
181
float F_hi = F_lo + denorm_small;
185
** .....+-----+-----+-----+-----+---....
190
** F_lo and F_hi are two consecutive single float model numbers
191
** denorm_small distance apart. D_lo and D_hi are two numbers
192
** within that range that are not representable as single floats
193
** and will be rounded to either F_lo or F_hi.
195
printf("-------------------------- %s --------------------------\n", msg);
197
print_double("D_lo", D_lo);
198
print_double("D_hi", D_hi);
199
print_single("F_lo", &F_lo);
200
print_single("F_hi", &F_hi);
203
/* round to nearest */
204
status |= check_dbl_to_flt_round(TO_NEAREST, D_hi, &F_hi);
205
status |= check_dbl_to_flt_round(TO_NEAREST, D_lo, &F_lo);
208
status |= check_dbl_to_flt_round(TO_ZERO, D_hi, (D_hi > 0 ? &F_lo : &F_hi));
209
status |= check_dbl_to_flt_round(TO_ZERO, D_lo, (D_hi > 0 ? &F_lo : &F_hi));
212
status |= check_dbl_to_flt_round(TO_PLUS_INFINITY, D_hi, &F_hi);
213
status |= check_dbl_to_flt_round(TO_PLUS_INFINITY, D_lo, &F_hi);
216
status |= check_dbl_to_flt_round(TO_MINUS_INFINITY, D_hi, &F_lo);
217
status |= check_dbl_to_flt_round(TO_MINUS_INFINITY, D_lo, &F_lo);
227
/* small is the smallest denormalized single float number */
231
denorm_small = F.flt; /* == 2^(-149) */
233
print_double("float small", F.flt);
238
D.layout.frac_hi = 0;
239
D.layout.frac_lo = 1;
240
dbl_denorm_small = D.dbl; /* == 2^(-1022) */
242
print_double("double small", D.dbl);
245
/* n_small is the smallest normalized single precision float */
250
int check_int_to_flt_round(round_mode_t mode, long L, float *expected)
254
char *int_name = "int";
259
set_rounding_mode(mode);
262
for (iter = 0; iter < 2; iter++) {
264
R.flt = (iter == 0 ? (float)I : (float)L);
266
if ((R.layout.sign != E.layout.sign) ||
267
(R.layout.exp != E.layout.exp) ||
268
(R.layout.frac != E.layout.frac)) {
275
printf("%s:%s:(float)(%4s)%9d = %11.1f",
276
round_mode_name[mode], result, int_name, I, R.flt);
278
print_single("\n\texpected: %.1f ", &E.flt);
279
print_single("\n\trounded ", &R.flt);
284
if (!long_is_64_bits) break;
290
int check_long_to_dbl_round(round_mode_t mode, long L, double *expected)
296
set_rounding_mode(mode);
301
if ((R.layout.sign != E.layout.sign) ||
302
(R.layout.exp != E.layout.exp) ||
303
(R.layout.frac_lo != E.layout.frac_lo) ||
304
(R.layout.frac_hi != E.layout.frac_hi)) {
311
printf("%s:%s:(double)(%18ld) = %20.1f",
312
round_mode_name[mode], result, L, R.dbl);
314
printf("\n\texpected %.1f : ", E.dbl);
320
int test_int_to_float_convert(char *msg)
323
int int24_hi = 0x03ff0fff;
324
int int24_lo = 0x03ff0ffd;
325
float pos_flt_lo = 67047420.0;
326
float pos_flt_hi = 67047424.0;
327
float neg_flt_lo = -67047420.0;
328
float neg_flt_hi = -67047424.0;
330
printf("-------------------------- %s --------------------------\n", msg);
331
status |= check_int_to_flt_round(TO_NEAREST, int24_lo, &pos_flt_lo);
332
status |= check_int_to_flt_round(TO_NEAREST, int24_hi, &pos_flt_hi);
333
status |= check_int_to_flt_round(TO_ZERO, int24_lo, &pos_flt_lo);
334
status |= check_int_to_flt_round(TO_ZERO, int24_hi, &pos_flt_lo);
335
status |= check_int_to_flt_round(TO_PLUS_INFINITY, int24_lo, &pos_flt_hi);
336
status |= check_int_to_flt_round(TO_PLUS_INFINITY, int24_hi, &pos_flt_hi);
337
status |= check_int_to_flt_round(TO_MINUS_INFINITY, int24_lo, &pos_flt_lo);
338
status |= check_int_to_flt_round(TO_MINUS_INFINITY, int24_hi, &pos_flt_lo);
340
status |= check_int_to_flt_round(TO_NEAREST, -int24_lo, &neg_flt_lo);
341
status |= check_int_to_flt_round(TO_NEAREST, -int24_hi, &neg_flt_hi);
342
status |= check_int_to_flt_round(TO_ZERO, -int24_lo, &neg_flt_lo);
343
status |= check_int_to_flt_round(TO_ZERO, -int24_hi, &neg_flt_lo);
344
status |= check_int_to_flt_round(TO_PLUS_INFINITY, -int24_lo, &neg_flt_lo);
345
status |= check_int_to_flt_round(TO_PLUS_INFINITY, -int24_hi, &neg_flt_lo);
346
status |= check_int_to_flt_round(TO_MINUS_INFINITY, -int24_lo, &neg_flt_hi);
347
status |= check_int_to_flt_round(TO_MINUS_INFINITY, -int24_hi, &neg_flt_hi);
352
int test_long_to_double_convert(char *msg)
355
long long55_hi = 0x07ff0ffffffffff;
356
long long55_lo = 0x07ff0fffffffffd;
357
double pos_dbl_lo = 36012304344547324.0;
358
double pos_dbl_hi = 36012304344547328.0;
359
double neg_dbl_lo = -36012304344547324.0;
360
double neg_dbl_hi = -36012304344547328.0;
362
printf("-------------------------- %s --------------------------\n", msg);
363
status |= check_long_to_dbl_round(TO_NEAREST, long55_lo, &pos_dbl_lo);
364
status |= check_long_to_dbl_round(TO_NEAREST, long55_hi, &pos_dbl_hi);
365
status |= check_long_to_dbl_round(TO_ZERO, long55_lo, &pos_dbl_lo);
366
status |= check_long_to_dbl_round(TO_ZERO, long55_hi, &pos_dbl_lo);
367
status |= check_long_to_dbl_round(TO_PLUS_INFINITY, long55_lo, &pos_dbl_hi);
368
status |= check_long_to_dbl_round(TO_PLUS_INFINITY, long55_hi, &pos_dbl_hi);
369
status |= check_long_to_dbl_round(TO_MINUS_INFINITY, long55_lo, &pos_dbl_lo);
370
status |= check_long_to_dbl_round(TO_MINUS_INFINITY, long55_hi, &pos_dbl_lo);
372
status |= check_long_to_dbl_round(TO_NEAREST, -long55_lo, &neg_dbl_lo);
373
status |= check_long_to_dbl_round(TO_NEAREST, -long55_hi, &neg_dbl_hi);
374
status |= check_long_to_dbl_round(TO_ZERO, -long55_lo, &neg_dbl_lo);
375
status |= check_long_to_dbl_round(TO_ZERO, -long55_hi, &neg_dbl_lo);
376
status |= check_long_to_dbl_round(TO_PLUS_INFINITY, -long55_lo, &neg_dbl_lo);
377
status |= check_long_to_dbl_round(TO_PLUS_INFINITY, -long55_hi, &neg_dbl_lo);
378
status |= check_long_to_dbl_round(TO_MINUS_INFINITY, -long55_lo, &neg_dbl_hi);
379
status |= check_long_to_dbl_round(TO_MINUS_INFINITY, -long55_hi, &neg_dbl_hi);
384
int check_single_arithmetic_op(flt_op_t op)
389
double qtr, half, fA, fB, fD;
392
bool_t two_args = TRUE;
393
float whole = denorm_small;
397
op" %0, %1, %2\n\t" \
398
: "=f"(fD) : "f"(fA) , "f"(fB));
402
: "=f"(fD) : "f"(fA));
404
half = (double)whole/2;
408
print_double("qtr", qtr);
409
print_double("whole", whole);
410
print_double("2*whole", 2*whole);
413
for (mode = TO_NEAREST; mode <= TO_MINUS_INFINITY; mode++)
414
for (s = -1; s < 2; s += 2)
415
for (q = 1; q < 4; q += 2) {
418
double hi = s*2*whole;
427
fB = s*(q == 1 ? 3 : 1)*qtr;
438
assert("check_single_arithmetic_op: unexpected op",
445
expected = (q == 1 ? lo : hi);
450
case TO_PLUS_INFINITY:
451
expected = (s == 1 ? hi : lo);
453
case TO_MINUS_INFINITY:
454
expected = (s == 1 ? lo : hi);
458
set_rounding_mode(mode);
461
** do the double precision dual operation just for comparison
486
assert("check_single_arithmetic_op: unexpected op",
495
if ((R.layout.sign != E.layout.sign) ||
496
(R.layout.exp != E.layout.exp) ||
497
(R.layout.frac_lo != E.layout.frac_lo) ||
498
(R.layout.frac_hi != E.layout.frac_hi)) {
506
printf("%s:%s:%s(%-13a",
507
round_mode_name[mode], result, flt_op_names[op], fA);
508
if (two_args) printf(", %-13a", fB);
509
printf(") = %-13a", R.dbl);
510
if (status) printf("\n\texpected %a", E.dbl);
514
print_double("hi", hi);
515
print_double("lo", lo);
516
print_double("expected", expected);
517
print_double("got", R.dbl);
518
print_double("double result", fD);
525
int check_single_guarded_arithmetic_op(flt_op_t op)
534
dbl_overlay Res, Exp;
535
double fA, fB, fC, fD;
540
fdivs_t divs_guard_cases[16] = {
541
{ 105, 56, 0x700000 }, /* : 0 */
542
{ 100, 57, 0x608FB8 }, /* : 1 */
543
{ 000, 00, 0x000000 }, /* : X */
544
{ 100, 52, 0x762762 }, /* : 3 */
545
{ 000, 00, 0x000000 }, /* : X */
546
{ 100, 55, 0x68BA2E }, /* : 5 */
547
{ 000, 00, 0x000000 }, /* : X */
548
{ 100, 51, 0x7AFAFA }, /* : 7 */
549
{ 000, 00, 0x000000 }, /* : X */
550
{ 100, 56, 0x649249 }, /* : 9 */
551
{ 000, 00, 0x000000 }, /* : X */
552
{ 100, 54, 0x6D097B }, /* : B */
553
{ 000, 00, 0x000000 }, /* : X */
554
{ 100, 59, 0x58F2FB }, /* : D */
555
{ 000, 00, 0x000000 }, /* : X */
556
{ 101, 52, 0x789D89 } /* : F */
559
/* 0x1.00000 00000000p-3 */
560
/* set up the invariant fields of B, the arg to cause rounding */
562
B.layout.exp = 124; /* -3 */
564
/* set up args so result is always Z = 1.200000000000<g>p+0 */
571
op" %0, %1, %2, %3\n\t" \
572
: "=f"(fD) : "f"(fA) , "f"(fB), "f"(fC));
576
op" %0, %1, %2\n\t" \
577
: "=f"(fD) : "f"(fA) , "f"(fB));
582
: "=f"(fD) : "f"(fA));
584
for (mode = TO_NEAREST; mode <= TO_MINUS_INFINITY; mode++)
585
for (s = -1; s < 2; s += 2)
586
for (g = 0; g < 16; g += 1) {
587
double lo, hi, expected;
593
** one argument will have exponent = 0 as will the result (by
594
** design) so choose the other argument with exponent -3 to
595
** force a 3 bit shift for scaling leaving us with 3 guard bits
596
** and the LSB bit at the bottom of the manitssa.
600
/* 1p+0 + 1.00000<g>p-3 */
606
/* set up Z to be truncated result */
608
/* mask off LSB from resulting guard bits */
611
Z.layout.frac = 0x100000 | (g >> 3);
614
/* 1.200002p+0 - 1.000000000000<g>p-3 */
616
/* add enough to avoid scaling of the result */
617
A.layout.frac |= 0x2;
623
/* set up Z to be truncated result */
625
Z.layout.frac = guard>>3;
627
/* mask off LSB from resulting guard bits */
637
/* set up Z to be truncated result */
639
Z.layout.frac = 0x100000;
640
Z.layout.frac |= g + (g>>3);
644
/* g >> 3 == LSB, g & 7 == guard bits */
646
if ((guard & 1) == 0) {
647
/* special case: guard bit X = 0 */
648
A.flt = denorm_small;
653
Z.layout.frac |= (g >> 3);
655
fA = s*divs_guard_cases[g].num;
656
fB = divs_guard_cases[g].den;
659
Z.layout.frac = divs_guard_cases[g].frac;
675
fC = (op == FMADDS || op == FNMADDS ? s : -s)*A.flt;
677
/* set up Z to be truncated result */
678
z_sign = (op == FNMADDS || op == FNMSUBS ? -s : s);
679
guard = ((g & 7) + 0x4) & 7;
681
Z.layout.frac = 0x500000;
682
Z.layout.frac |= g + (g>>3) + ((g & 7)>> 2 ? 1 : 0);
685
assert("check_single_arithmetic_op: unexpected op",
690
/* get LSB for tie breaking */
691
LSB = Z.layout.frac & 1;
693
/* set up hi and lo */
700
/* look at 3 guard bits to determine expected rounding */
703
case 1: case 2: case 3:
706
case 4: /* tie: round to even */
707
if (debug) printf("tie: LSB = %d\n", LSB);
708
expected = (LSB == 0 ? lo : hi);
710
case 5: case 6: case 7:
714
assert("check_single_guarded_arithmetic_op: unexpected guard",
721
case TO_PLUS_INFINITY:
726
expected = (s == 1 ? hi : lo);
729
case TO_MINUS_INFINITY:
734
expected = (s == 1 ? lo : hi);
739
set_rounding_mode(mode);
742
** do the double precision dual operation just for comparison
779
assert("check_single_guarded_arithmetic_op: unexpected op",
789
if ((Res.layout.sign != Exp.layout.sign) ||
790
(Res.layout.exp != Exp.layout.exp) ||
791
(Res.layout.frac_lo != Exp.layout.frac_lo) ||
792
(Res.layout.frac_hi != Exp.layout.frac_hi)) {
800
printf("%s:%s:%s(%-13f",
801
round_mode_name[mode], result, flt_op_names[op], fA);
802
if (arg_count > 1) printf(", %-13a", fB);
803
if (arg_count > 2) printf(", %-13a", fC);
804
printf(") = %-13a", Res.dbl);
805
if (status) printf("\n\texpected %a", Exp.dbl);
809
print_double("hi", hi);
810
print_double("lo", lo);
811
print_double("expected", expected);
812
print_double("got", Res.dbl);
819
int check_double_guarded_arithmetic_op(flt_op_t op)
822
int num, den, hi, lo;
832
dbl_overlay Res, Exp;
833
double fA, fB, fC, fD;
837
fdiv_t div_guard_cases[16] = {
838
{ 62, 62, 0x00000, 0x00000000 }, /* 0 */
839
{ 64, 62, 0x08421, 0x08421084 }, /* 1 */
840
{ 66, 62, 0x10842, 0x10842108 }, /* 2 */
841
{ 100, 62, 0x9ce73, 0x9ce739ce }, /* 3 */
842
{ 100, 62, 0x9ce73, 0x9ce739ce }, /* X */
843
{ 102, 62, 0xa5294, 0xa5294a52 }, /* 5 */
844
{ 106, 62, 0xb5ad6, 0xb5ad6b5a }, /* 6 */
845
{ 108, 62, 0xbdef7, 0xbdef7bde }, /* 7 */
846
{ 108, 108, 0x00000, 0x00000000 }, /* 8 */
847
{ 112, 62, 0xce739, 0xce739ce7 }, /* 9 */
848
{ 114, 62, 0xd6b5a, 0xd6b5ad6b }, /* A */
849
{ 116, 62, 0xdef7b, 0xdef7bdef }, /* B */
850
{ 84, 62, 0x5ad6b, 0x5ad6b5ad }, /* X */
851
{ 118, 62, 0xe739c, 0xe739ce73 }, /* D */
852
{ 90, 62, 0x739ce, 0x739ce739 }, /* E */
853
{ 92, 62, 0x7bdef, 0x7bdef7bd } /* F */
857
fsqrt_t sqrt_guard_cases[16] = {
858
{ 0x1.08800p0, 0, 0x04371, 0xd9ab72fb}, /* :0 B8.8440 */
859
{ 0x0.D2200p0, -1, 0xcfdca, 0xf353049e}, /* :1 A4.6910 */
860
{ 0x1.A8220p0, 0, 0x49830, 0x2b49cd6d}, /* :2 E9.D411 */
861
{ 0x1.05A20p0, 0, 0x02cd1, 0x3b44f3bf}, /* :3 B7.82D1 */
862
{ 0x0.CA820p0, -1, 0xc7607, 0x3cec0937}, /* :4 A1.6541 */
863
{ 0x1.DCA20p0, 0, 0x5d4f8, 0xd4e4c2b2}, /* :5 F7.EE51 */
864
{ 0x1.02C80p0, 0, 0x01630, 0x9cde7483}, /* :6 B6.8164 */
865
{ 0x0.DC800p0, -1, 0xdb2cf, 0xe686fe7c}, /* :7 A8.6E40 */
866
{ 0x0.CF920p0, -1, 0xcd089, 0xb6860626}, /* :8 A3.67C9 */
867
{ 0x1.1D020p0, 0, 0x0e1d6, 0x2e78ed9d}, /* :9 BF.8E81 */
868
{ 0x0.E1C80p0, -1, 0xe0d52, 0x6020fb6b}, /* :A AA.70E4 */
869
{ 0x0.C8000p0, -1, 0xc48c6, 0x001f0abf}, /* :B A0.6400 */
870
{ 0x1.48520p0, 0, 0x21e9e, 0xd813e2e2}, /* :C CD.A429 */
871
{ 0x0.F4C20p0, -1, 0xf4a1b, 0x09bbf0b0}, /* :D B1.7A61 */
872
{ 0x0.CD080p0, -1, 0xca348, 0x79b907ae}, /* :E A2.6684 */
873
{ 0x1.76B20p0, 0, 0x35b67, 0x81aed827} /* :F DB.BB59 */
876
/* 0x1.00000 00000000p-3 */
877
/* set up the invariant fields of B, the arg to cause rounding */
881
/* set up args so result is always Z = 1.200000000000<g>p+0 */
888
op" %0, %1, %2, %3\n\t" \
889
: "=f"(fD) : "f"(fA) , "f"(fB), "f"(fC));
893
op" %0, %1, %2\n\t" \
894
: "=f"(fD) : "f"(fA) , "f"(fB));
899
: "=f"(fD) : "f"(fA));
901
for (mode = TO_NEAREST; mode <= TO_MINUS_INFINITY; mode++)
902
for (s = (op != FSQRT ? -1 : 1); s < 2; s += 2)
903
for (g = 0; g < 16; g += 1) {
904
double lo, hi, expected;
910
** one argument will have exponent = 0 as will the result (by
911
** design) so choose the other argument with exponent -3 to
912
** force a 3 bit shift for scaling leaving us with 3 guard bits
913
** and the LSB bit at the bottom of the manitssa.
917
/* 1p+0 + 1.000000000000<g>p-3 */
918
B.layout.frac_lo = g;
923
/* set up Z to be truncated result */
925
/* mask off LSB from resulting guard bits */
928
Z.layout.frac_hi = 0x20000;
929
Z.layout.frac_lo = g >> 3;
933
/* 1.2000000000002p+0 - 1.000000000000<g>p-3 */
935
/* add enough to avoid scaling of the result */
936
A.layout.frac_lo = 0x2;
939
B.layout.frac_lo = g;
942
/* set up Z to be truncated result */
944
Z.layout.frac_hi = 0x0;
945
Z.layout.frac_lo = guard>>3;
947
/* mask off LSB from resulting guard bits */
953
A.layout.frac_lo = g;
957
/* set up Z to be truncated result */
959
Z.layout.frac_hi = 0x20000;
960
Z.layout.frac_lo = g + (g>>3);
969
A.layout.frac_lo = g;
973
/* 1.0000000000001p-1 */
975
A.layout.frac_lo = 1;
976
fC = (op == FMADD || op == FNMADD ? s : -s)*A.dbl;
978
/* set up Z to be truncated result */
979
z_sign = (op == FNMADD || op == FNMSUB ? -s : s);
980
guard = ((g & 7) + 0x4) & 7;
982
Z.layout.frac_hi = 0xa0000;
983
Z.layout.frac_lo = g + (g>>3) + ((g & 7)>> 2 ? 1 : 0);
986
/* g >> 3 == LSB, g & 7 == guard bits */
989
/* special case guard bits == 4, inexact tie */
993
fA = dbl_denorm_small + 2*dbl_denorm_small;
994
Z.layout.frac_lo = 0x1;
996
fA = dbl_denorm_small;
999
fA = s*div_guard_cases[g].num;
1000
fB = div_guard_cases[g].den;
1003
s*div_guard_cases[g].num,
1004
div_guard_cases[g].den);
1006
Z.layout.frac_hi = div_guard_cases[g].hi;
1007
Z.layout.frac_lo = div_guard_cases[g].lo;
1011
fA = s*sqrt_guard_cases[g].arg;
1013
Z.layout.exp = sqrt_guard_cases[g].exp + 1023;
1014
Z.layout.frac_hi = sqrt_guard_cases[g].hi;
1015
Z.layout.frac_lo = sqrt_guard_cases[g].lo;
1017
if (g & 1) guard |= 1;
1018
/* don't have test cases for when X bit = 0 */
1019
if (guard == 0 || guard == 4) continue;
1022
assert("check_double_guarded_arithmetic_op: unexpected op",
1027
/* get LSB for tie breaking */
1028
LSB = Z.layout.frac_lo & 1;
1030
/* set up hi and lo */
1032
Z.layout.frac_lo += 1;
1037
/* look at 3 guard bits to determine expected rounding */
1040
case 1: case 2: case 3:
1043
case 4: /* tie: round to even */
1044
if (debug) printf("tie: LSB = %d\n", LSB);
1045
expected = (LSB == 0 ? lo : hi);
1047
case 5: case 6: case 7:
1051
assert("check_double_guarded_arithmetic_op: unexpected guard",
1058
case TO_PLUS_INFINITY:
1063
expected = (s == 1 ? hi : lo);
1066
case TO_MINUS_INFINITY:
1071
expected = (s == 1 ? lo : hi);
1076
set_rounding_mode(mode);
1079
** do the double precision dual operation just for comparison
1120
assert("check_double_guarded_arithmetic_op: unexpected op",
1130
if ((Res.layout.sign != Exp.layout.sign) ||
1131
(Res.layout.exp != Exp.layout.exp) ||
1132
(Res.layout.frac_lo != Exp.layout.frac_lo) ||
1133
(Res.layout.frac_hi != Exp.layout.frac_hi)) {
1141
printf("%s:%s:%s(%-13a",
1142
round_mode_name[mode], result, flt_op_names[op], fA);
1143
if (arg_count > 1) printf(", %-13a", fB);
1144
if (arg_count > 2) printf(", %-13a", fC);
1145
printf(") = %-13a", Res.dbl);
1146
if (status) printf("\n\texpected %a", Exp.dbl);
1150
print_double("hi", hi);
1151
print_double("lo", lo);
1152
print_double("expected", expected);
1153
print_double("got", Res.dbl);
1160
int test_float_arithmetic_ops()
1166
** choose FP operands whose result should be rounded to either
1170
printf("-------------------------- %s --------------------------\n",
1171
"test rounding of float operators without guard bits");
1172
for (op = FADDS; op <= FDIVS; op++) {
1173
status |= check_single_arithmetic_op(op);
1176
printf("-------------------------- %s --------------------------\n",
1177
"test rounding of float operators with guard bits");
1178
for (op = FADDS; op <= FNMSUBS; op++) {
1179
status |= check_single_guarded_arithmetic_op(op);
1182
printf("-------------------------- %s --------------------------\n",
1183
"test rounding of double operators with guard bits");
1184
for (op = FADD; op <= FSQRT; op++) {
1185
status |= check_double_guarded_arithmetic_op(op);
1198
status |= test_dbl_to_float_convert("test denormalized convert", &denorm_small);
1199
status |= test_dbl_to_float_convert("test normalized convert", &norm_small);
1200
status |= test_int_to_float_convert("test (float)int convert");
1201
status |= test_int_to_float_convert("test (float)int convert");
1203
#ifdef __powerpc64__
1204
status |= test_long_to_double_convert("test (double)long convert");
1206
status |= test_float_arithmetic_ops();