1#include <stdio.h>
2#include <math.h>
3
4#define T(a,b) {__LINE__, a, b},
5#define length(a) (sizeof(a)/sizeof*(a))
6
7static struct {
8	int line;
9	float f;
10	int class;
11} tf[] = {
12	T(0.0/0.0, FP_NAN)
13	T(-0.0/0.0, FP_NAN)
14	T(1/0.0, FP_INFINITE)
15	T(-1/0.0, FP_INFINITE)
16	T(0x1.ffffp127, FP_NORMAL)
17	T(-0x1.ffffp127, FP_NORMAL)
18	T(0x1p-127, FP_SUBNORMAL)
19	T(-0x1p-127, FP_SUBNORMAL)
20	T(0.0, FP_ZERO)
21	T(-0.0, FP_ZERO)
22	T(3.14, FP_NORMAL)
23	T(-42, FP_NORMAL)
24};
25
26static struct {
27	int line;
28	double f;
29	int class;
30} td[] = {
31	T(0.0/0.0, FP_NAN)
32	T(-0.0/0.0, FP_NAN)
33	T(1/0.0, FP_INFINITE)
34	T(-1/0.0, FP_INFINITE)
35	T(0x1.ffffp1023, FP_NORMAL)
36	T(-0x1.ffffp1023, FP_NORMAL)
37	T(0x1p-1023, FP_SUBNORMAL)
38	T(-0x1p-1023, FP_SUBNORMAL)
39	T(0.0, FP_ZERO)
40	T(-0.0, FP_ZERO)
41	T(3.14, FP_NORMAL)
42	T(-42, FP_NORMAL)
43};
44
45static struct {
46	int line;
47	long double f;
48	int class;
49} tl[] = {
50	T(0.0/0.0, FP_NAN)
51	T(-0.0/0.0, FP_NAN)
52	T(1/0.0, FP_INFINITE)
53	T(-1/0.0, FP_INFINITE)
54#if LDBL_MAX_EXP==16384
55	T(0x1.ffffp16383L, FP_NORMAL)
56	T(-0x1.ffffp16383L, FP_NORMAL)
57	T(0x1p-16383L, FP_SUBNORMAL)
58	T(-0x1p-16383L, FP_SUBNORMAL)
59#elif LDBL_MAX_EXP==1024
60	T(0x1.ffffp1023L, FP_NORMAL)
61	T(-0x1.ffffp1023L, FP_NORMAL)
62	T(0x1p-1023L, FP_SUBNORMAL)
63	T(-0x1p-1023L, FP_SUBNORMAL)
64#endif
65	T(0.0, FP_ZERO)
66	T(-0.0, FP_ZERO)
67	T(3.14, FP_NORMAL)
68	T(-42, FP_NORMAL)
69};
70
71static char *strclass(int c)
72{
73#define C(n) case n: return #n;
74	switch (c) {
75	C(FP_NAN)
76	C(FP_INFINITE)
77	C(FP_ZERO)
78	C(FP_SUBNORMAL)
79	C(FP_NORMAL)
80	}
81	return "invalid";
82}
83
84#define error(t,c) err++, printf("%s:%d: (at line %d) %La has class %d (%s), but %s returns %d\n", \
85	__FILE__, __LINE__, t.line, (long double)t.f, t.class, strclass(t.class), #c, c(t.f))
86
87int main()
88{
89	int i;
90	int err = 0;
91
92	for (i = 0; i < length(tf); i++) {
93		if (fpclassify(tf[i].f) != tf[i].class)
94			error(tf[i], fpclassify);
95		if (!!isinf(tf[i].f) != (tf[i].class == FP_INFINITE))
96			error(tf[i], isinf);
97		if (!!isnan(tf[i].f) != (tf[i].class == FP_NAN))
98			error(tf[i], isnan);
99		if (!!isnormal(tf[i].f) != (tf[i].class == FP_NORMAL))
100			error(tf[i], isnormal);
101		if (!!isfinite(tf[i].f) != (tf[i].class > FP_INFINITE))
102			error(tf[i], isfinite);
103	}
104
105	for (i = 0; i < length(td); i++) {
106		if (fpclassify(td[i].f) != td[i].class)
107			error(td[i], fpclassify);
108		if (!!isinf(td[i].f) != (td[i].class == FP_INFINITE))
109			error(td[i], isinf);
110		if (!!isnan(td[i].f) != (td[i].class == FP_NAN))
111			error(td[i], isnan);
112		if (!!isnormal(td[i].f) != (td[i].class == FP_NORMAL))
113			error(td[i], isnormal);
114		if (!!isfinite(td[i].f) != (td[i].class > FP_INFINITE))
115			error(td[i], isfinite);
116	}
117
118	for (i = 0; i < length(tl); i++) {
119		if (fpclassify(tl[i].f) != tl[i].class)
120			error(tl[i], fpclassify);
121		if (!!isinf(tl[i].f) != (tl[i].class == FP_INFINITE))
122			error(tl[i], isinf);
123		if (!!isnan(tl[i].f) != (tl[i].class == FP_NAN))
124			error(tl[i], isnan);
125		if (!!isnormal(tl[i].f) != (tl[i].class == FP_NORMAL))
126			error(tl[i], isnormal);
127		if (!!isfinite(tl[i].f) != (tl[i].class > FP_INFINITE))
128			error(tl[i], isfinite);
129	}
130
131	return !!err;
132}
133