1 /* Copyright (C) 2007  Free Software Foundation.
2 
3    Verify that built-in folding of modf is correctly performed by the
4    compiler.
5 
6    Origin: Kaveh R. Ghazi,  February 23, 2007.  */
7 
8 /* { dg-do link } */
9 /* { dg-require-effective-target inf } */
10 /* { dg-options "-fno-finite-math-only" { target sh*-*-* } } */
11 /* { dg-options "-funsafe-math-optimizations -fsigned-zeros -fno-associative-math" { target powerpc-*-darwin* powerpc*-*-linux* } } */
12 
13 extern void link_error(int);
14 
15 /* Return TRUE if the sign of X != sign of Y.  This is important when
16    comparing signed zeros.  */
17 #define CKSGN_F(X,Y) \
18   (__builtin_copysignf(1.0F,(X)) != __builtin_copysignf(1.0F,(Y)))
19 #define CKSGN(X,Y) \
20   (__builtin_copysign(1.0,(X)) != __builtin_copysign(1.0,(Y)))
21 #define CKSGN_L(X,Y) \
22   (__builtin_copysignl(1.0L,(X)) != __builtin_copysignl(1.0L,(Y)))
23 
24 /* We use these macros if we can only check these when optimizing.  In
25    some cases we rely on other optimizations to propagate the value
26    and fold away certain constructs.  Likewise for the sign testing.
27    TRUE means an error occurred.  */
28 #ifdef __OPTIMIZE__
29 #define CKRES(X) (X)
30 #define CKIPTR(X,Y) X != Y
31 #define CKSGN_IPTR_F(X,Y) CKSGN_F(X,Y)
32 #define CKSGN_IPTR(X,Y) CKSGN(X,Y)
33 #define CKSGN_IPTR_L(X,Y) CKSGN_L(X,Y)
34 #else
35 #define CKRES(X) 0
36 #define CKIPTR(X,Y) 0
37 #define CKSGN_IPTR_F(X,Y) 0
38 #define CKSGN_IPTR(X,Y) 0
39 #define CKSGN_IPTR_L(X,Y) 0
40 #endif
41 
42 /* Test that modf(ARG1,&iptr) == FRACRES && iptr == INTRES.  Check the
43    sign in case we get -0.0.  */
44 #define TESTIT_MODF(ARG,INTRES,FRACRES) do { \
45   float iptrf = 0.5; double iptr = 0.5; long double iptrl = 0.5; \
46   if (__builtin_modff(ARG##f,&iptrf) != FRACRES##f \
47       || CKIPTR(iptrf,INTRES##f) \
48       || CKSGN_F(__builtin_modff(ARG##f,&iptrf),FRACRES##f) \
49       || CKSGN_IPTR_F(iptrf,INTRES##f)) \
50     link_error(__LINE__); \
51   if (__builtin_modf(ARG,&iptr) != FRACRES \
52       || CKIPTR(iptr,INTRES) \
53       || CKSGN(__builtin_modf(ARG,&iptr),FRACRES) \
54       || CKSGN_IPTR(iptr,INTRES)) \
55     link_error(__LINE__); \
56   if (__builtin_modfl(ARG##l,&iptrl) != FRACRES##l \
57       || CKIPTR(iptrl,INTRES##l) \
58       || CKSGN_L(__builtin_modfl(ARG##l,&iptrl),FRACRES##l) \
59       || CKSGN_IPTR_L(iptrl,INTRES##l)) \
60     link_error(__LINE__); \
61   } while (0)
62 
63 /* Test that modf(NEG FUNCARG(ARGARG, &iptr)) == FRACRES &&
64    FUNCRES(iptr) is true.  Check the sign of both as well.  This is
65    for checking an argument of Inf.  */
66 #define TESTIT_MODF2(NEG,FUNCARG,ARGARG,FUNCRES,FRACRES) do { \
67   float iptrf = 0.5; double iptr = 0.5; long double iptrl = 0.5; \
68   if (__builtin_modff(NEG __builtin_##FUNCARG##f(ARGARG),&iptrf) != FRACRES##f \
69       || CKSGN_F(__builtin_modff(NEG __builtin_##FUNCARG##f(ARGARG),&iptrf), FRACRES##f) \
70       || CKIPTR(!__builtin_##FUNCRES##f(iptrf),0) \
71       || CKSGN_IPTR_F(iptrf,FRACRES##f)) \
72     link_error(__LINE__); \
73   if (__builtin_modf(NEG __builtin_##FUNCARG(ARGARG),&iptr) != FRACRES \
74       || CKSGN(__builtin_modf(NEG __builtin_##FUNCARG(ARGARG),&iptr), FRACRES) \
75       || CKIPTR(!__builtin_##FUNCRES(iptr),0) \
76       || CKSGN_IPTR(iptr,FRACRES)) \
77     link_error(__LINE__); \
78   if (__builtin_modfl(NEG __builtin_##FUNCARG##l(ARGARG),&iptrl) != FRACRES##l \
79       || CKSGN_L(__builtin_modfl(NEG __builtin_##FUNCARG##l(ARGARG),&iptrl), FRACRES##l) \
80       || CKIPTR(!__builtin_##FUNCRES##l(iptrl),0) \
81       || CKSGN_IPTR_L(iptrl,FRACRES##l)) \
82     link_error(__LINE__); \
83   } while (0)
84 
85 /* Test that FUNCRES(modf(NEG FUNCARG(ARGARG, &iptr))) is true &&
86    FUNCRES(iptr) is true.  Check the sign of both as well.  This is
87    for checking an argument of NaN.  */
88 #define TESTIT_MODF3(NEG,FUNCARG,ARGARG,FUNCRES) do { \
89   float iptrf = 0.5; double iptr = 0.5; long double iptrl = 0.5; \
90   if (CKRES(!__builtin_##FUNCRES##f(__builtin_modff(NEG __builtin_##FUNCARG##f(ARGARG),&iptrf))) \
91       || CKSGN_F(__builtin_modff(NEG __builtin_##FUNCARG##f(ARGARG),&iptrf), NEG 1) \
92       || CKIPTR(!__builtin_##FUNCRES##f(iptrf),0) \
93       || CKSGN_IPTR_F(iptrf,NEG 1)) \
94     link_error(__LINE__); \
95   if (CKRES(!__builtin_##FUNCRES(__builtin_modf(NEG __builtin_##FUNCARG(ARGARG),&iptr))) \
96       || CKSGN(__builtin_modf(NEG __builtin_##FUNCARG(ARGARG),&iptr), NEG 1) \
97       || CKIPTR(!__builtin_##FUNCRES(iptr),0) \
98       || CKSGN_IPTR(iptr,NEG 1)) \
99     link_error(__LINE__); \
100   if (CKRES(!__builtin_##FUNCRES##l(__builtin_modfl(NEG __builtin_##FUNCARG##l(ARGARG),&iptrl))) \
101       || CKSGN_L(__builtin_modfl(NEG __builtin_##FUNCARG##l(ARGARG),&iptrl), NEG 1) \
102       || CKIPTR(!__builtin_##FUNCRES##l(iptrl),0) \
103       || CKSGN_IPTR_L(iptrl,NEG 1)) \
104     link_error(__LINE__); \
105   } while (0)
106 
107 void __attribute__ ((__noinline__))
foo(void)108 foo(void)
109 {
110   /* Test that modf(ARG1,&iptr) -> ARG3 && iptr == ARG2.  */
111   TESTIT_MODF (0x1p10F+0.5, 0x1p10, 0.5);
112   TESTIT_MODF (0x1p10F+0x1p-10, 0x1p10, 0x1p-10);
113   TESTIT_MODF (12345678L/17.0, 726216.0, -726216L+12345678L/17.0);
114   TESTIT_MODF (555.555, 555.0, -555+555.555);
115   TESTIT_MODF (5000/11.0, 454.0, -454+5000/11.0);
116   TESTIT_MODF (1000/7.0, 142.0, -142+1000/7.0);
117   TESTIT_MODF (123/7.0, 17.0, -17+123/7.0);
118   TESTIT_MODF (117/7.0, 16.0, -16+117/7.0);
119   TESTIT_MODF (5.5, 5.0, 0.5);
120   TESTIT_MODF (1.5, 1.0, 0.5);
121   TESTIT_MODF (4/3.0, 1.0, -1+4/3.0);
122   TESTIT_MODF (1.0, 1.0, 0.0);
123   TESTIT_MODF (0.5, 0.0, 0.5);
124   TESTIT_MODF (4/9.0, 0.0, 4/9.0);
125   TESTIT_MODF (1/3.0, 0.0, 1/3.0);
126   TESTIT_MODF (1/9.0, 0.0, 1/9.0);
127   TESTIT_MODF (0.0, 0.0, 0.0);
128 
129   TESTIT_MODF (-0.0, -0.0, -0.0);
130   TESTIT_MODF (-1/9.0, -0.0, -1/9.0);
131   TESTIT_MODF (-1/3.0, -0.0, -1/3.0);
132   TESTIT_MODF (-4/9.0, -0.0, -4/9.0);
133   TESTIT_MODF (-0.5, -0.0, -0.5);
134   TESTIT_MODF (-1.0, -1.0, -0.0);
135   TESTIT_MODF (-4/3.0, -1.0, 1-4/3.0);
136   TESTIT_MODF (-1.5, -1.0, -0.5);
137   TESTIT_MODF (-5.5, -5.0, -0.5);
138   TESTIT_MODF (-117/7.0, -16.0, 16-117/7.0);
139   TESTIT_MODF (-123/7.0, -17.0, 17-123/7.0);
140   TESTIT_MODF (-1000/7.0, -142.0, 142-1000/7.0);
141   TESTIT_MODF (-5000/11.0, -454.0, 454-5000/11.0);
142   TESTIT_MODF (-555.555, -555.0, 555-555.555);
143   TESTIT_MODF (-12345678L/17.0, -726216.0, 726216L-12345678L/17.0);
144   TESTIT_MODF (-0x1p10F-0x1p-10, -0x1p10, -0x1p-10);
145   TESTIT_MODF (-0x1p10F-0.5, -0x1p10, -0.5);
146 
147 
148   /* Test for modf(+-Inf,&i) -> (i=+-0.0, +-Inf).  */
149   TESTIT_MODF2 ( ,inf, , isinf, 0.0);
150   TESTIT_MODF2 (- ,inf, , isinf, -0.0);
151 
152   /* Test for and modf(+-NaN,&i) -> (i=+-NaN, +-NaN).  */
153   TESTIT_MODF3 ( ,nan, "", isnan);
154   TESTIT_MODF3 (- ,nan, "", isnan);
155 }
156 
main()157 int main()
158 {
159   foo();
160 
161   return 0;
162 }
163