1 /* Copyright (C) 2007  Free Software Foundation.
2 
3    Verify that built-in folding of logb, ilogb and significand is
4    correctly performed by the compiler.
5 
6    Origin: Kaveh R. Ghazi,  February 22, 2007.  */
7 
8 /* { dg-do link } */
9 /* { dg-options "-fno-finite-math-only" { target sh*-*-* } } */
10 /* In order to fold algebraic exprs below, targets with "composite"
11    floating point formats need -funsafe-math-optimizations.  */
12 /* { dg-require-effective-target inf } */
13 /* { dg-options "-funsafe-math-optimizations" { target powerpc*-*-* } } */
14 
15 extern void link_error(int);
16 
17 /* Return TRUE if the sign of X != sign of Y.  This is important when
18    comparing signed zeros.  */
19 #define CKSGN_F(X,Y) \
20   (__builtin_copysignf(1.0F,(X)) != __builtin_copysignf(1.0F,(Y)))
21 #define CKSGN(X,Y) \
22   (__builtin_copysign(1.0,(X)) != __builtin_copysign(1.0,(Y)))
23 #define CKSGN_L(X,Y) \
24   (__builtin_copysignl(1.0L,(X)) != __builtin_copysignl(1.0L,(Y)))
25 
26 /* Test that FUNC(ARG) == RES.  Check the sign in case we get -0.0.  */
27 #define TESTIT(FUNC,ARG,RES) do { \
28   if (__builtin_##FUNC##f(ARG##f) != RES##f \
29       || CKSGN_F(__builtin_##FUNC##f(ARG##f),RES##f)) \
30     link_error(__LINE__); \
31   if (__builtin_##FUNC(ARG) != RES \
32       || CKSGN(__builtin_##FUNC(ARG),RES)) \
33     link_error(__LINE__); \
34   if (__builtin_##FUNC##l(ARG##l) != RES##l \
35       || CKSGN_L(__builtin_##FUNC##l(ARG##l),RES##l)) \
36     link_error(__LINE__); \
37   } while (0)
38 
39 /* Test that FUNC(ARG) == RES.  RES is an int so it can't be -0.0.  */
40 #define TESTIT2(FUNC,ARG,RES) do { \
41   if (__builtin_##FUNC##f(ARG##f) != RES) \
42     link_error(__LINE__); \
43   if (__builtin_##FUNC(ARG) != RES) \
44     link_error(__LINE__); \
45   if (__builtin_##FUNC##l(ARG##l) != RES) \
46     link_error(__LINE__); \
47   } while (0)
48 
49 /* Test if FUNCRES(FUNC(NEG FUNCARG(ARGARG))) is false.  Check the
50    sign as well.  */
51 #define TESTIT3(FUNC,NEG,FUNCARG,ARGARG,FUNCRES,NEG2) do { \
52   if (!__builtin_##FUNCRES##f(__builtin_##FUNC(NEG __builtin_##FUNCARG##f(ARGARG))) \
53       || CKSGN_F(__builtin_##FUNC##f(NEG __builtin_##FUNCARG##f(ARGARG)), NEG2 __builtin_##FUNCARG##f(ARGARG))) \
54     link_error(__LINE__); \
55   if (!__builtin_##FUNCRES(__builtin_##FUNC(NEG __builtin_##FUNCARG(ARGARG))) \
56       || CKSGN(__builtin_##FUNC(NEG __builtin_##FUNCARG(ARGARG)), NEG2 __builtin_##FUNCARG(ARGARG))) \
57     link_error(__LINE__); \
58   if (!__builtin_##FUNCRES##l(__builtin_##FUNC##l(NEG __builtin_##FUNCARG##l(ARGARG))) \
59       || CKSGN_L(__builtin_##FUNC##l(NEG __builtin_##FUNCARG##l(ARGARG)), NEG2 __builtin_##FUNCARG##l(ARGARG))) \
60     link_error(__LINE__); \
61   } while (0)
62 
63 void __attribute__ ((__noinline__))
foo(void)64 foo(void)
65 {
66   /* If radix == 2, test that logb(ARG2) -> ARG3.  */
67 #if __FLT_RADIX__ == 2
68   TESTIT (logb, -0x1p40, 40.0);
69   TESTIT (logb, -0x1p30, 30.0);
70   TESTIT (logb, -0x1p20, 20.0);
71   TESTIT (logb, -0x1p10, 10.0);
72   TESTIT (logb, -0x1p5, 5.0);
73   TESTIT (logb, -100/3.0, 5.0);
74   TESTIT (logb, -2.0, 1.0);
75   TESTIT (logb, -1.5, 0.0);
76   TESTIT (logb, -1.0, 0.0);
77   TESTIT (logb, -1/3.0, -2.0);
78   TESTIT (logb, -1/9.0, -4.0);
79   TESTIT (logb, -0x1p-5, -5.0);
80   TESTIT (logb, -0x1p-10, -10.0);
81   TESTIT (logb, -0x1p-20, -20.0);
82   TESTIT (logb, -0x1p-30, -30.0);
83   TESTIT (logb, -0x1p-40, -40.0);
84 
85   TESTIT (logb, 0x1p-40, -40.0);
86   TESTIT (logb, 0x1p-30, -30.0);
87   TESTIT (logb, 0x1p-20, -20.0);
88   TESTIT (logb, 0x1p-10, -10.0);
89   TESTIT (logb, 0x1p-5, -5.0);
90   TESTIT (logb, 1/9.0, -4.0);
91   TESTIT (logb, 1/3.0, -2.0);
92   TESTIT (logb, 1.0, 0.0);
93   TESTIT (logb, 1.5, 0.0);
94   TESTIT (logb, 2.0, 1.0);
95   TESTIT (logb, 100/3.0, 5.0);
96   TESTIT (logb, 0x1p5, 5.0);
97   TESTIT (logb, 0x1p10, 10.0);
98   TESTIT (logb, 0x1p20, 20.0);
99   TESTIT (logb, 0x1p30, 30.0);
100   TESTIT (logb, 0x1p40, 40.0);
101 #endif
102 
103   /* If radix == 2, test that ilogb(ARG2) -> ARG3.  */
104 #if __FLT_RADIX__ == 2
105   TESTIT2 (ilogb, -0x1p40, 40);
106   TESTIT2 (ilogb, -0x1p30, 30);
107   TESTIT2 (ilogb, -0x1p20, 20);
108   TESTIT2 (ilogb, -0x1p10, 10);
109   TESTIT2 (ilogb, -0x1p5, 5);
110   TESTIT2 (ilogb, -100/3.0, 5);
111   TESTIT2 (ilogb, -2.0, 1);
112   TESTIT2 (ilogb, -1.5, 0);
113   TESTIT2 (ilogb, -1.0, 0);
114   TESTIT2 (ilogb, -1/3.0, -2);
115   TESTIT2 (ilogb, -1/9.0, -4);
116   TESTIT2 (ilogb, -0x1p-5, -5);
117   TESTIT2 (ilogb, -0x1p-10, -10);
118   TESTIT2 (ilogb, -0x1p-20, -20);
119   TESTIT2 (ilogb, -0x1p-30, -30);
120   TESTIT2 (ilogb, -0x1p-40, -40);
121 
122   TESTIT2 (ilogb, 0x1p-40, -40);
123   TESTIT2 (ilogb, 0x1p-30, -30);
124   TESTIT2 (ilogb, 0x1p-20, -20);
125   TESTIT2 (ilogb, 0x1p-10, -10);
126   TESTIT2 (ilogb, 0x1p-5, -5);
127   TESTIT2 (ilogb, 1/9.0, -4);
128   TESTIT2 (ilogb, 1/3.0, -2);
129   TESTIT2 (ilogb, 1.0, 0);
130   TESTIT2 (ilogb, 1.5, 0);
131   TESTIT2 (ilogb, 2.0, 1);
132   TESTIT2 (ilogb, 100/3.0, 5);
133   TESTIT2 (ilogb, 0x1p5, 5);
134   TESTIT2 (ilogb, 0x1p10, 10);
135   TESTIT2 (ilogb, 0x1p20, 20);
136   TESTIT2 (ilogb, 0x1p30, 30);
137   TESTIT2 (ilogb, 0x1p40, 40);
138 #endif
139 
140   /* If radix == 2, test that significand(ARG2) -> ARG3.  Zero always
141      folds regardless of the radix.  */
142   TESTIT (significand, -0.0, -0.0);
143   TESTIT (significand, 0.0, 0.0);
144 
145 #if __FLT_RADIX__ == 2
146   TESTIT (significand, -0x1p5, -1.0);
147   TESTIT (significand, -100/3.0, -100/96.0);
148   TESTIT (significand, -1.5, -1.5);
149   TESTIT (significand, -1.0, -1.0);
150   TESTIT (significand, -1/3.0, -4/3.0);
151   TESTIT (significand, -1/9.0, -16/9.0);
152   TESTIT (significand, -0x1p-5, -1.0);
153 
154   TESTIT (significand, 0x1p-5, 1.0);
155   TESTIT (significand, 1/9.0, 16/9.0);
156   TESTIT (significand, 1/3.0, 4/3.0);
157   TESTIT (significand, 1.0, 1.0);
158   TESTIT (significand, 1.5, 1.5);
159   TESTIT (significand, 100/3.0, 100/96.0);
160   TESTIT (significand, 0x1p5, 1.0);
161 #endif
162 
163   /* Test for f(+-Inf) -> +-Inf and f(+-NaN) -> +-NaN, regardless of
164      the radix.  */
165   TESTIT3 (logb, ,inf, , isinf, );
166   TESTIT3 (logb, - ,inf, , isinf, );
167   TESTIT3 (logb,  ,nan, "", isnan, );
168   TESTIT3 (logb, - ,nan, "", isnan, -);
169 
170   TESTIT3 (significand, ,inf, , isinf, );
171   TESTIT3 (significand, - ,inf, , isinf, -);
172   TESTIT3 (significand,  ,nan, "", isnan, );
173   TESTIT3 (significand, - ,nan, "", isnan, -);
174 }
175 
main()176 int main()
177 {
178   foo ();
179 
180   return 0;
181 }
182