Remove building with NOCRYPTO option
[minix.git] / minix / tests / test47.c
blob5e1d76348d994788390b59d70b1df7517a67e844
1 #include <assert.h>
2 #include <fenv.h>
3 #include <math.h>
4 #include <signal.h>
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <machine/frame.h>
10 int max_error = 4;
11 #include "common.h"
14 /* maximum allowed FP difference for our tests */
15 #define EPSILON 0.00000000023283064365386962890625 /* 2^(-32) */
17 #define ERR(x, y) e(__LINE__, (x), (y))
19 static void signal_handler(int signum)
21 struct sigframe_sigcontext *sigframe;
23 /* report signal */
24 sigframe = (struct sigframe_sigcontext *) ((char *) &signum -
25 (char *) &((struct sigframe_sigcontext *) NULL)->sf_signum);
26 printf("Signal %d at 0x%x\n", signum, sigframe->sf_scp->sc_eip);
28 /* count as error */
29 e(0);
30 fflush(stdout);
32 /* handle signa again next time */
33 signal(signum, signal_handler);
36 static void test_fpclassify(double value, int class, int test_sign)
38 /* test fpclassify */
39 if (fpclassify(value) != class) e(101);
40 if (test_sign)
42 if (fpclassify(-value) != class) e(102);
44 /* test signbit */
45 if (signbit(value)) e(103);
46 if (!signbit(-value)) e(104);
50 /* Maximum normal double: (2 - 2^(-53)) * 2^1023 */
51 #define NORMAL_DOUBLE_MAX 1.797693134862315708145274237317e+308
53 /* Minimum normal double: 2^(-1022) */
54 #define NORMAL_DOUBLE_MIN 2.2250738585072013830902327173324e-308
56 /* Maximum subnormal double: (1 - 2^(-53)) * 2^(-1022) */
57 #define SUBNORMAL_DOUBLE_MAX 2.2250738585072008890245868760859e-308
59 /* Minimum subnormal double: 2^(-52) * 2^(-1023) */
60 #define SUBNORMAL_DOUBLE_MIN 4.9406564584124654417656879286822e-324
62 static void test_fpclassify_values(void)
64 double d;
65 char negzero[] = { 0, 0, 0, 0, 0, 0, 0, 0x80 };
67 /* test some corner cases for fpclassify and signbit */
68 test_fpclassify(INFINITY, FP_INFINITE, 1);
69 test_fpclassify(NAN, FP_NAN, 0);
70 test_fpclassify(0, FP_ZERO, 0);
71 test_fpclassify(1, FP_NORMAL, 1);
72 test_fpclassify(NORMAL_DOUBLE_MAX, FP_NORMAL, 1);
73 test_fpclassify(NORMAL_DOUBLE_MIN, FP_NORMAL, 1);
74 test_fpclassify(SUBNORMAL_DOUBLE_MAX, FP_SUBNORMAL, 1);
75 test_fpclassify(SUBNORMAL_DOUBLE_MIN, FP_SUBNORMAL, 1);
77 /*
78 * unfortunately the minus operator does not change the sign of zero,
79 * so a special case is needed to test it
81 assert(sizeof(negzero) == sizeof(double));
82 test_fpclassify(*(double *) negzero, FP_ZERO, 0);
83 if (!signbit(*(double *) negzero)) e(4);
85 /* test other small numbers for fpclassify and signbit */
86 d = 1;
87 while (d >= NORMAL_DOUBLE_MIN)
89 test_fpclassify(d, FP_NORMAL, 1);
90 d /= 10;
92 while (d >= SUBNORMAL_DOUBLE_MIN)
94 test_fpclassify(d, FP_SUBNORMAL, 1);
95 d /= 10;
97 test_fpclassify(d, FP_ZERO, 0);
99 /* test other large numbers for fpclassify and signbit */
100 d = 1;
101 while (d <= NORMAL_DOUBLE_MAX / 10)
103 test_fpclassify(d, FP_NORMAL, 1);
104 d *= 10;
108 /* expected rounding: up, down or identical */
109 #define ROUND_EQ 1
110 #define ROUND_DN 2
111 #define ROUND_UP 3
113 static void test_round_value_mode_func(double value, int mode, double (*func)(double), int exp)
115 int mode_old;
116 double rounded;
118 /* update and check rounding mode */
119 mode_old = fegetround();
120 fesetround(mode);
121 if (fegetround() != mode) e(5);
123 /* perform rounding */
124 rounded = func(value);
126 /* check direction of rounding */
127 switch (exp)
129 case ROUND_EQ: if (rounded != value) e(6); break;
130 case ROUND_DN: if (rounded >= value) e(7); break;
131 case ROUND_UP: if (rounded <= value) e(8); break;
132 default: assert(0);
135 /* check whether the number is sufficiently close */
136 if (fabs(value - rounded) >= 1) e(9);
138 /* check whether the number is integer */
139 if (remainder(rounded, 1)) e(10);
141 /* re-check and restore rounding mode */
142 if (fegetround() != mode) e(11);
143 fesetround(mode_old);
146 static void test_round_value_mode(double value, int mode, int exp_nearbyint,
147 int exp_ceil, int exp_floor, int exp_trunc)
149 /* test both nearbyint and trunc */
150 #if 0
151 test_round_value_mode_func(value, mode, nearbyint, exp_nearbyint);
152 #endif
153 test_round_value_mode_func(value, mode, ceil, exp_ceil);
154 test_round_value_mode_func(value, mode, floor, exp_floor);
155 test_round_value_mode_func(value, mode, trunc, exp_trunc);
158 static void test_round_value(double value, int exp_down, int exp_near, int exp_up, int exp_trunc)
160 /* test each rounding mode */
161 test_round_value_mode(value, FE_DOWNWARD, exp_down, exp_up, exp_down, exp_trunc);
162 test_round_value_mode(value, FE_TONEAREST, exp_near, exp_up, exp_down, exp_trunc);
163 test_round_value_mode(value, FE_UPWARD, exp_up, exp_up, exp_down, exp_trunc);
164 test_round_value_mode(value, FE_TOWARDZERO, exp_trunc, exp_up, exp_down, exp_trunc);
167 static void test_round_values(void)
169 int i;
171 /* test various values */
172 for (i = -100000; i < 100000; i++)
174 test_round_value(i + 0.00, ROUND_EQ, ROUND_EQ, ROUND_EQ, ROUND_EQ);
175 test_round_value(i + 0.25, ROUND_DN, ROUND_DN, ROUND_UP, (i >= 0) ? ROUND_DN : ROUND_UP);
176 test_round_value(i + 0.50, ROUND_DN, (i % 2) ? ROUND_UP : ROUND_DN, ROUND_UP, (i >= 0) ? ROUND_DN : ROUND_UP);
177 test_round_value(i + 0.75, ROUND_DN, ROUND_UP, ROUND_UP, (i >= 0) ? ROUND_DN : ROUND_UP);
181 static void test_remainder_value(double x, double y)
183 int mode_old;
184 double r1, r2;
186 assert(y != 0);
188 /* compute remainder using the function */
189 r1 = remainder(x, y);
191 /* compute remainder using alternative approach */
192 mode_old = fegetround();
193 fesetround(FE_TONEAREST);
194 r2 = x - rint(x / y) * y;
195 fesetround(mode_old);
197 /* Compare results */
198 if (fabs(r1 - r2) > EPSILON && fabs(r1 + r2) > EPSILON)
200 printf("%.20g != %.20g\n", r1, r2);
201 e(13);
205 static void test_remainder_values_y(double x)
207 int i, j;
209 /* try various rational and transcendental values for y (except zero) */
210 for (i = -50; i <= 50; i++)
211 if (i != 0)
212 for (j = 1; j < 10; j++)
214 test_remainder_value(x, (double) i / (double) j);
215 test_remainder_value(x, i * M_E + j * M_PI);
219 static void test_remainder_values_xy(void)
221 int i, j;
223 /* try various rational and transcendental values for x */
224 for (i = -50; i <= 50; i++)
225 for (j = 1; j < 10; j++)
227 test_remainder_values_y((double) i / (double) j);
228 test_remainder_values_y(i * M_E + j * M_PI);
232 int main(int argc, char **argv)
234 fenv_t fenv;
235 int i;
237 start(47);
239 /* no FPU errors, please */
240 if (feholdexcept(&fenv) < 0) e(14);
242 /* some signals count as errors */
243 for (i = 0; i < _NSIG; i++)
244 if (i != SIGINT && i != SIGTERM && i != SIGKILL)
245 signal(i, signal_handler);
247 /* test various floating point support functions */
248 test_fpclassify_values();
249 test_remainder_values_xy();
250 test_round_values();
251 quit();
252 return -1;