8 #include <sys/sigcontext.h>
13 /* maximum allowed FP difference for our tests */
14 #define EPSILON 0.00000000023283064365386962890625 /* 2^(-32) */
16 static void quit(void)
25 printf("%d errors\n", errct
);
30 #define ERR(x, y) e(__LINE__, (x), (y))
32 static void e(int n
, double x
, double y
)
34 printf("Line %d, x=%.20g, y=%.20g\n", n
, x
, y
);
35 if (errct
++ > MAX_ERROR
)
37 printf("Too many errors; test aborted\n");
42 static void signal_handler(int signum
)
44 struct sigframe
*sigframe
;
47 sigframe
= (struct sigframe
*) ((char *) &signum
-
48 (char *) &((struct sigframe
*) NULL
)->sf_signo
);
49 printf("Signal %d at 0x%x\n", signum
, sigframe
->sf_scp
->sc_regs
.pc
);
55 /* handle signa again next time */
56 signal(signum
, signal_handler
);
59 static void test_fpclassify(double value
, int class, int test_sign
)
62 if (fpclassify(value
) != class) ERR(value
, 0);
65 if (fpclassify(-value
) != class) ERR(-value
, 0);
68 if (signbit(value
)) ERR(value
, 0);
69 if (!signbit(-value
)) ERR(-value
, 0);
73 /* Maximum normal double: (2 - 2^(-53)) * 2^1023 */
74 #define NORMAL_DOUBLE_MAX 1.797693134862315708145274237317e+308
76 /* Minimum normal double: 2^(-1022) */
77 #define NORMAL_DOUBLE_MIN 2.2250738585072013830902327173324e-308
79 /* Maximum subnormal double: (1 - 2^(-53)) * 2^(-1022) */
80 #define SUBNORMAL_DOUBLE_MAX 2.2250738585072008890245868760859e-308
82 /* Minimum subnormal double: 2^(-52) * 2^(-1023) */
83 #define SUBNORMAL_DOUBLE_MIN 4.9406564584124654417656879286822e-324
85 static void test_fpclassify_values(void)
88 char negzero
[] = { 0, 0, 0, 0, 0, 0, 0, 0x80 };
90 /* test some corner cases for fpclassify and signbit */
91 test_fpclassify(INFINITY
, FP_INFINITE
, 1);
92 test_fpclassify(NAN
, FP_NAN
, 0);
93 test_fpclassify(0, FP_ZERO
, 0);
94 test_fpclassify(1, FP_NORMAL
, 1);
95 test_fpclassify(NORMAL_DOUBLE_MAX
, FP_NORMAL
, 1);
96 test_fpclassify(NORMAL_DOUBLE_MIN
, FP_NORMAL
, 1);
97 test_fpclassify(SUBNORMAL_DOUBLE_MAX
, FP_SUBNORMAL
, 1);
98 test_fpclassify(SUBNORMAL_DOUBLE_MIN
, FP_SUBNORMAL
, 1);
101 * unfortunately the minus operator does not change the sign of zero,
102 * so a special case is needed to test it
104 assert(sizeof(negzero
) == sizeof(double));
105 test_fpclassify(*(double *) negzero
, FP_ZERO
, 0);
106 if (!signbit(*(double *) negzero
)) ERR(0, 0);
108 /* test other small numbers for fpclassify and signbit */
110 while (d
>= NORMAL_DOUBLE_MIN
)
112 test_fpclassify(d
, FP_NORMAL
, 1);
115 while (d
>= SUBNORMAL_DOUBLE_MIN
)
117 test_fpclassify(d
, FP_SUBNORMAL
, 1);
120 test_fpclassify(d
, FP_ZERO
, 0);
122 /* test other large numbers for fpclassify and signbit */
124 while (d
<= NORMAL_DOUBLE_MAX
/ 10)
126 test_fpclassify(d
, FP_NORMAL
, 1);
131 /* expected rounding: up, down or identical */
136 static void test_round_value_mode_func(double value
, int mode
, double (*func
)(double), int exp
)
141 /* update and check rounding mode */
142 mode_old
= fegetround();
144 if (fegetround() != mode
) ERR(0, 0);
146 /* perform rounding */
147 rounded
= func(value
);
149 /* check direction of rounding */
152 case ROUND_EQ
: if (rounded
!= value
) ERR(value
, rounded
); break;
153 case ROUND_DN
: if (rounded
>= value
) ERR(value
, rounded
); break;
154 case ROUND_UP
: if (rounded
<= value
) ERR(value
, rounded
); break;
158 /* check whether the number is sufficiently close */
159 if (fabs(value
- rounded
) >= 1) ERR(value
, rounded
);
161 /* check whether the number is integer */
162 if (remainder(rounded
, 1)) ERR(value
, rounded
);
164 /* re-check and restore rounding mode */
165 if (fegetround() != mode
) ERR(0, 0);
166 fesetround(mode_old
);
169 static void test_round_value_mode(double value
, int mode
, int exp_nearbyint
,
170 int exp_ceil
, int exp_floor
, int exp_trunc
)
172 /* test both nearbyint and trunc */
173 test_round_value_mode_func(value
, mode
, nearbyint
, exp_nearbyint
);
174 test_round_value_mode_func(value
, mode
, ceil
, exp_ceil
);
175 test_round_value_mode_func(value
, mode
, floor
, exp_floor
);
176 test_round_value_mode_func(value
, mode
, trunc
, exp_trunc
);
179 static void test_round_value(double value
, int exp_down
, int exp_near
, int exp_up
, int exp_trunc
)
181 /* test each rounding mode */
182 test_round_value_mode(value
, FE_DOWNWARD
, exp_down
, exp_up
, exp_down
, exp_trunc
);
183 test_round_value_mode(value
, FE_TONEAREST
, exp_near
, exp_up
, exp_down
, exp_trunc
);
184 test_round_value_mode(value
, FE_UPWARD
, exp_up
, exp_up
, exp_down
, exp_trunc
);
185 test_round_value_mode(value
, FE_TOWARDZERO
, exp_trunc
, exp_up
, exp_down
, exp_trunc
);
188 static void test_round_values(void)
192 /* test various values */
193 for (i
= -100000; i
< 100000; i
++)
195 test_round_value(i
+ 0.00, ROUND_EQ
, ROUND_EQ
, ROUND_EQ
, ROUND_EQ
);
196 test_round_value(i
+ 0.25, ROUND_DN
, ROUND_DN
, ROUND_UP
, (i
>= 0) ? ROUND_DN
: ROUND_UP
);
197 test_round_value(i
+ 0.50, ROUND_DN
, (i
% 2) ? ROUND_UP
: ROUND_DN
, ROUND_UP
, (i
>= 0) ? ROUND_DN
: ROUND_UP
);
198 test_round_value(i
+ 0.75, ROUND_DN
, ROUND_UP
, ROUND_UP
, (i
>= 0) ? ROUND_DN
: ROUND_UP
);
202 static void test_remainder_value(double x
, double y
)
209 /* compute remainder using the function */
210 r1
= remainder(x
, y
);
212 /* compute remainder using alternative approach */
213 mode_old
= fegetround();
214 fesetround(FE_TONEAREST
);
215 r2
= x
- nearbyint(x
/ y
) * y
;
216 fesetround(mode_old
);
218 /* Compare results */
219 if (fabs(r1
- r2
) > EPSILON
&& fabs(r1
+ r2
) > EPSILON
)
221 printf("%.20g != %.20g\n", r1
, r2
);
226 static void test_remainder_values_y(double x
)
230 /* try various rational and transcendental values for y (except zero) */
231 for (i
= -50; i
<= 50; i
++)
233 for (j
= 1; j
< 10; j
++)
235 test_remainder_value(x
, (double) i
/ (double) j
);
236 test_remainder_value(x
, i
* M_E
+ j
* M_PI
);
240 static void test_remainder_values_xy(void)
244 /* try various rational and transcendental values for x */
245 for (i
= -50; i
<= 50; i
++)
246 for (j
= 1; j
< 10; j
++)
248 test_remainder_values_y((double) i
/ (double) j
);
249 test_remainder_values_y(i
* M_E
+ j
* M_PI
);
253 int main(int argc
, char **argv
)
261 /* no FPU errors, please */
262 if (feholdexcept(&fenv
) < 0) ERR(0, 0);
264 /* some signals count as errors */
265 for (i
= 0; i
< _NSIG
; i
++)
266 if (i
!= SIGINT
&& i
!= SIGTERM
&& i
!= SIGKILL
)
267 signal(i
, signal_handler
);
269 /* test various floating point support functions */
270 test_fpclassify_values();
271 test_remainder_values_xy();