| @@ -8,26 +8,43 @@ | | | @@ -8,26 +8,43 @@ |
8 | #include <atf-c.h> | | 8 | #include <atf-c.h> |
9 | #include <fenv.h> | | 9 | #include <fenv.h> |
10 | #ifdef __HAVE_FENV | | 10 | #ifdef __HAVE_FENV |
11 | #include <math.h> | | 11 | #include <math.h> |
12 | #include <stdio.h> | | 12 | #include <stdio.h> |
13 | #include <stdlib.h> | | 13 | #include <stdlib.h> |
14 | | | 14 | |
15 | /*#pragma STDC FENV_ACCESS ON gcc?? */ | | 15 | /*#pragma STDC FENV_ACCESS ON gcc?? */ |
16 | | | 16 | |
17 | #define INT 9223L | | 17 | #define INT 9223L |
18 | | | 18 | |
19 | #define EPSILON 0.001 | | 19 | #define EPSILON 0.001 |
20 | | | 20 | |
| | | 21 | static const char * |
| | | 22 | rmname(int rm) |
| | | 23 | { |
| | | 24 | switch (rm) { |
| | | 25 | case FE_TOWARDZERO: |
| | | 26 | return "FE_TOWARDZERO"; |
| | | 27 | case FE_DOWNWARD: |
| | | 28 | return "FE_DOWNWARD"; |
| | | 29 | case FE_UPWARD: |
| | | 30 | return "FE_UPWARD"; |
| | | 31 | case FE_TONEAREST: |
| | | 32 | return "FE_TONEAREST"; |
| | | 33 | default: |
| | | 34 | return "unknown"; |
| | | 35 | } |
| | | 36 | } |
| | | 37 | |
21 | static const struct { | | 38 | static const struct { |
22 | int round_mode; | | 39 | int round_mode; |
23 | double input; | | 40 | double input; |
24 | long int expected; | | 41 | long int expected; |
25 | } values[] = { | | 42 | } values[] = { |
26 | { FE_DOWNWARD, 3.7, 3}, | | 43 | { FE_DOWNWARD, 3.7, 3}, |
27 | { FE_DOWNWARD, -3.7, -4}, | | 44 | { FE_DOWNWARD, -3.7, -4}, |
28 | { FE_DOWNWARD, +0, 0}, | | 45 | { FE_DOWNWARD, +0, 0}, |
29 | { FE_DOWNWARD, -INT-0.01, -INT-1}, | | 46 | { FE_DOWNWARD, -INT-0.01, -INT-1}, |
30 | { FE_DOWNWARD, +INT-0.01, INT-1}, | | 47 | { FE_DOWNWARD, +INT-0.01, INT-1}, |
31 | { FE_DOWNWARD, -INT+0.01, -INT}, | | 48 | { FE_DOWNWARD, -INT+0.01, -INT}, |
32 | { FE_DOWNWARD, +INT+0.01, INT}, | | 49 | { FE_DOWNWARD, +INT+0.01, INT}, |
33 | #if 0 /* cpu bugs? */ | | 50 | #if 0 /* cpu bugs? */ |
| @@ -86,49 +103,53 @@ ATF_TC_BODY(fe_round, tc) | | | @@ -86,49 +103,53 @@ ATF_TC_BODY(fe_round, tc) |
86 | | | 103 | |
87 | /* Do we get the same rounding mode out? */ | | 104 | /* Do we get the same rounding mode out? */ |
88 | ATF_CHECK_MSG( | | 105 | ATF_CHECK_MSG( |
89 | (fegetround() == values[i].round_mode), | | 106 | (fegetround() == values[i].round_mode), |
90 | "Didn't get the same rounding mode out!\n" | | 107 | "Didn't get the same rounding mode out!\n" |
91 | "(index %d) fed in %d rounding mode, got %d out\n", | | 108 | "(index %d) fed in %d rounding mode, got %d out\n", |
92 | i, values[i].round_mode, fegetround()); | | 109 | i, values[i].round_mode, fegetround()); |
93 | } | | 110 | } |
94 | } | | 111 | } |
95 | | | 112 | |
96 | ATF_TC(fe_nearbyint); | | 113 | ATF_TC(fe_nearbyint); |
97 | ATF_TC_HEAD(fe_nearbyint, tc) | | 114 | ATF_TC_HEAD(fe_nearbyint, tc) |
98 | { | | 115 | { |
99 | atf_tc_set_md_var(tc, "descr","Checking IEEE 754 rounding modes using nearbyint"); | | 116 | atf_tc_set_md_var(tc, "descr", |
| | | 117 | "Checking IEEE 754 rounding modes using nearbyint"); |
100 | } | | 118 | } |
101 | | | 119 | |
102 | ATF_TC_BODY(fe_nearbyint, tc) | | 120 | ATF_TC_BODY(fe_nearbyint, tc) |
103 | { | | 121 | { |
104 | double received; | | 122 | double received, ipart, fpart; |
105 | | | 123 | |
106 | for (unsigned int i = 0; i < __arraycount(values); i++) { | | 124 | for (unsigned int i = 0; i < __arraycount(values); i++) { |
107 | fesetround(values[i].round_mode); | | 125 | fesetround(values[i].round_mode); |
108 | | | 126 | |
109 | received = nearbyint(values[i].input); | | 127 | received = nearbyint(values[i].input); |
110 | ATF_CHECK_MSG( | | 128 | fpart = modf(received, &ipart); |
111 | (fabs(received - values[i].expected) < EPSILON), | | 129 | ATF_CHECK_MSG(fpart == 0, |
112 | "nearbyint rounding wrong, difference too large\n" | | 130 | "%s nearbyint(%f) has fractional part %f", |
113 | "input: %f (index %d): got %f, expected %ld\n", | | 131 | rmname(values[i].round_mode), values[i].input, fpart); |
114 | values[i].input, i, received, values[i].expected); | | 132 | ATF_CHECK_MSG((long int)received == values[i].expected, |
| | | 133 | "%s [%u] nearbyint(%f) got %f, expected %ld\n", |
| | | 134 | rmname(values[i].round_mode), |
| | | 135 | i, values[i].input, received, values[i].expected); |
115 | | | 136 | |
116 | /* Do we get the same rounding mode out? */ | | 137 | /* Do we get the same rounding mode out? */ |
117 | ATF_CHECK_MSG( | | 138 | ATF_CHECK_MSG(fegetround() == values[i].round_mode, |
118 | (fegetround() == values[i].round_mode), | | 139 | "[%u] set %d (%s), got %d (%s)", |
119 | "Didn't get the same rounding mode out!\n" | | 140 | i, |
120 | "(index %d) fed in %d rounding mode, got %d out\n", | | 141 | values[i].round_mode, rmname(values[i].round_mode), |
121 | i, values[i].round_mode, fegetround()); | | 142 | fegetround(), rmname(fegetround())); |
122 | } | | 143 | } |
123 | } | | 144 | } |
124 | | | 145 | |
125 | static const struct { | | 146 | static const struct { |
126 | double input; | | 147 | double input; |
127 | double toward; | | 148 | double toward; |
128 | double expected; | | 149 | double expected; |
129 | } values2[] = { | | 150 | } values2[] = { |
130 | { 10.0, 11.0, 10.0 }, | | 151 | { 10.0, 11.0, 10.0 }, |
131 | { -5.0, -6.0, -5.0 }, | | 152 | { -5.0, -6.0, -5.0 }, |
132 | }; | | 153 | }; |
133 | | | 154 | |
134 | ATF_TC(fe_nextafter); | | 155 | ATF_TC(fe_nextafter); |