1/* { dg-do run } */
2/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
3/* { dg-options "-fsanitize=float-cast-overflow -fno-sanitize-recover=float-cast-overflow" } */
4/* FIXME: When _DecimalXX <-> {signed, unsigned} __int128 conversions are
5   supported, -DBROKEN_DECIMAL_INT128 can be removed.  */
6/* { dg-additional-options "-DUSE_DFP -DBROKEN_DECIMAL_INT128" { target dfp } } */
7
8#define USE_FLT_DBL_LDBL
9#ifdef __SIZEOF_INT128__
10#define USE_INT128
11#endif
12#ifdef __SIZEOF_FLOAT80__
13#define USE_FLOAT80
14#endif
15#ifdef __SIZEOF_FLOAT128__
16#define USE_FLOAT128
17#endif
18
19#include "float-cast-overflow-7.h"
20
21#define TEST(type1, type2) \
22  if (cvt_##type1##_##type2 (-0.5f) != 0) abort ();		\
23  if (cvt_##type1##_##type2 (0.5f) != 0) abort ();		\
24  if (cvt_##type1##_##type2 (-0.75f) != 0) abort ();		\
25  if (cvt_##type1##_##type2 (0.75f) != 0) abort ();		\
26  if (type1##_MIN)						\
27    {								\
28      /* For RADIX 2 type1##_MIN should be always */		\
29      /* exactly representable in type2.  */			\
30      if (type2##_RADIX == 2					\
31	  || type1##_MAX <= type2##_MAX)			\
32	{							\
33	  if (cvt_##type1##_##type2 (type1##_MIN)		\
34	      != type1##_MIN) abort ();				\
35	  volatile type2 tem = ((type2) -0.75f) + type1##_MIN;	\
36	  volatile type2 tem2 = ((type2) -1.0f) + type1##_MIN;	\
37	  if (tem != tem2					\
38	      && cvt_##type1##_##type2 ((type2) -0.75f		\
39					+ type1##_MIN)		\
40		 != type1##_MIN) abort ();			\
41	}							\
42      else							\
43	{							\
44	  type2 min = type1##_MIN;				\
45	  /* tem could be below minimum here due to */		\
46	  /* rounding.  */					\
47	  MAXT add = 1;						\
48	  while (add)						\
49	    {							\
50	      volatile type2 tem = type1##_MIN + (type1) add;	\
51	      if (tem != min)					\
52		break;						\
53	      MAXT newadd = add * type2##_RADIX;		\
54	      if (newadd < add || newadd > type1##_MAX)		\
55		add = 0;					\
56	      else						\
57		add = newadd;					\
58	    }							\
59	  if (add)						\
60	    {							\
61	      MAXT newadd					\
62		= (-(type1##_MIN + (type1) add)) % add;		\
63	      volatile type2 tem = type1##_MIN + (type1) newadd;\
64	      volatile type2 tem2 = type1##_MIN + (type1) add;	\
65	      if (tem == tem2)					\
66		add = newadd;					\
67	      else						\
68		{						\
69		  newadd += add;				\
70		  if (newadd < add || newadd > type1##_MAX)	\
71		    add = 0;					\
72		  else						\
73		    {						\
74		      tem = type1##_MIN + (type1) newadd;	\
75		      if (tem == tem2)				\
76			add = newadd;				\
77		      else					\
78			add = 0;				\
79		    }						\
80		}						\
81	    }							\
82	  if (add						\
83	      && cvt_##type1##_##type2 (type1##_MIN		\
84					+ (type1) add)		\
85		 != type1##_MIN + (type1) add) abort ();	\
86	}							\
87    }								\
88  if (type1##_MAX <= type2##_MAX)				\
89    {								\
90      if (cvt_##type1##_##type2 (type1##_MAX) != type1##_MAX)	\
91	abort ();						\
92      volatile type2 tem = ((type2) 0.75f) + type1##_MAX;	\
93      volatile type2 tem2 = ((type2) 1.0f) + type1##_MAX;	\
94      if (tem < tem2						\
95	  && cvt_##type1##_##type2 ((type2) 0.75f + type1##_MAX)\
96	     != type1##_MAX) abort ();				\
97    }								\
98  else								\
99    {								\
100      type2 max = type1##_MAX;					\
101      /* tem could be above maximum here due to rounding.  */	\
102      MAXT sub = 1;						\
103      while (sub)						\
104	{							\
105	  volatile type2 tem = type1##_MAX - sub;		\
106	  if (tem != max)					\
107	    break;						\
108	  MAXT newsub = sub * type2##_RADIX;			\
109	  if (newsub < sub || newsub > type1##_MAX)		\
110	    sub = 0;						\
111	  else							\
112	    sub = newsub;					\
113	}							\
114      if (sub)							\
115	{							\
116	  MAXT newsub = ((type1##_MAX - sub) % sub);		\
117	  volatile type2 tem = type1##_MAX - newsub;		\
118	  volatile type2 tem2 = type1##_MAX - sub;		\
119	  if (tem == tem2)					\
120	    sub = newsub;					\
121	  else							\
122	    {							\
123	      newsub += sub;					\
124	      if (newsub < sub || newsub > type1##_MAX)		\
125		sub = 0;					\
126	      else						\
127		{						\
128		  tem = type1##_MAX - newsub;			\
129		  if (tem == tem2)				\
130		    sub = newsub;				\
131		  else						\
132		    sub = 0;					\
133		}						\
134	    }							\
135	}							\
136      if (sub							\
137	  && cvt_##type1##_##type2 (type1##_MAX - sub)		\
138	     != type1##_MAX - sub) abort ();			\
139    }
140
141
142#ifdef si128_MAX
143# define TESTS128(type2) TEST (si128, type2) TEST (ui128, type2)
144#else
145# define TESTS128(type2)
146#endif
147
148#define TESTS(type2) \
149  TEST (sc, type2) TEST (c, type2) TEST (uc, type2)	\
150  TEST (ss, type2) TEST (us, type2)			\
151  TEST (si, type2) TEST (ui, type2)			\
152  TEST (sl, type2) TEST (ul, type2)			\
153  TEST (sll, type2) TEST (ull, type2)			\
154  TESTS128 (type2)
155
156int
157main ()
158{
159#ifdef f_MAX
160  TESTS (f)
161#endif
162#ifdef d_MAX
163  TESTS (d)
164#endif
165#ifdef ld_MAX
166  TESTS (ld)
167#endif
168#ifdef f80_MAX
169  TESTS (f80)
170#endif
171#ifdef f128_MAX
172  TESTS (f128)
173#endif
174#ifdef BROKEN_DECIMAL_INT128
175# undef TESTS128
176# define TESTS128(type2)
177# undef TWO
178# undef M1U
179# undef MAXS
180# undef MAXT
181# define TWO 2ULL
182# define M1U -1ULL
183# define MAXS (__CHAR_BIT__ * __SIZEOF_LONG_LONG__)
184# define MAXT unsigned long long
185#endif
186#ifdef d32_MAX
187  TESTS (d32)
188#endif
189#ifdef d64_MAX
190  TESTS (d64)
191#endif
192#ifdef d128_MAX
193  TESTS (d128)
194#endif
195  return 0;
196}
197