]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/sreal.c
c++: Handle multiple aggregate overloads [PR95319].
[thirdparty/gcc.git] / gcc / sreal.c
CommitLineData
fd27ffab 1/* Simple data type for real numbers for the GNU compiler.
8d9254fc 2 Copyright (C) 2002-2020 Free Software Foundation, Inc.
ac5e69da
JZ
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
9dcd6f09 8Software Foundation; either version 3, or (at your option) any later
ac5e69da
JZ
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
9dcd6f09
NC
17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
ac5e69da 19
fd27ffab 20/* This library supports real numbers;
ac5e69da
JZ
21 inf and nan are NOT supported.
22 It is written to be simple and fast.
23
24 Value of sreal is
25 x = sig * 2 ^ exp
46c5ad27 26 where
ac5e69da
JZ
27 sig = significant
28 (for < 64-bit machines sig = sig_lo + sig_hi * 2 ^ SREAL_PART_BITS)
29 exp = exponent
30
618b7f29 31 One uint64_t is used for the significant.
ac5e69da
JZ
32 Only a half of significant bits is used (in normalized sreals) so that we do
33 not have problems with overflow, for example when c->sig = a->sig * b->sig.
618b7f29 34 So the precision is 32-bit.
46c5ad27 35
ac5e69da
JZ
36 Invariant: The numbers are normalized before and after each call of sreal_*.
37
38 Normalized sreals:
39 All numbers (except zero) meet following conditions:
40 SREAL_MIN_SIG <= sig && sig <= SREAL_MAX_SIG
46c5ad27 41 -SREAL_MAX_EXP <= exp && exp <= SREAL_MAX_EXP
ac5e69da
JZ
42
43 If the number would be too large, it is set to upper bounds of these
44 conditions.
45
46 If the number is zero or would be too small it meets following conditions:
47 sig == 0 && exp == -SREAL_MAX_EXP
48*/
49
50#include "config.h"
51#include "system.h"
bc1c9c22 52#include <math.h>
ac5e69da 53#include "coretypes.h"
ac5e69da 54#include "sreal.h"
dcbdb17a 55#include "selftest.h"
8a267096
JH
56#include "backend.h"
57#include "tree.h"
58#include "gimple.h"
59#include "cgraph.h"
60#include "data-streamer.h"
ac5e69da 61
ac5e69da
JZ
62/* Print the content of struct sreal. */
63
64void
618b7f29 65sreal::dump (FILE *file) const
ac5e69da 66{
a5f4d3d6 67 fprintf (file, "(%" PRIi64 " * 2^%d)", (int64_t)m_sig, m_exp);
ac5e69da
JZ
68}
69
7b3b6ae4 70DEBUG_FUNCTION void
d1704358 71debug (const sreal &ref)
7b3b6ae4 72{
618b7f29 73 ref.dump (stderr);
7b3b6ae4
LC
74}
75
76DEBUG_FUNCTION void
d1704358 77debug (const sreal *ptr)
7b3b6ae4
LC
78{
79 if (ptr)
80 debug (*ptr);
81 else
82 fprintf (stderr, "<nil>\n");
83}
84
618b7f29
TS
85/* Shift this right by S bits. Needed: 0 < S <= SREAL_BITS.
86 When the most significant bit shifted out is 1, add 1 to this (rounding).
87 */
7b3b6ae4 88
618b7f29
TS
89void
90sreal::shift_right (int s)
ac5e69da 91{
fd27ffab
ML
92 gcc_checking_assert (s > 0);
93 gcc_checking_assert (s <= SREAL_BITS);
41374e13
NS
94 /* Exponent should never be so large because shift_right is used only by
95 sreal_add and sreal_sub ant thus the number cannot be shifted out from
96 exponent range. */
fd27ffab 97 gcc_checking_assert (m_exp + s <= SREAL_MAX_EXP);
ac5e69da 98
618b7f29 99 m_exp += s;
ac5e69da 100
d1704358 101 m_sig += (int64_t) 1 << (s - 1);
618b7f29 102 m_sig >>= s;
ac5e69da
JZ
103}
104
618b7f29 105/* Return integer value of *this. */
ac5e69da 106
618b7f29
TS
107int64_t
108sreal::to_int () const
ac5e69da 109{
a4f28954 110 int64_t sign = SREAL_SIGN (m_sig);
fd27ffab 111
618b7f29 112 if (m_exp <= -SREAL_BITS)
ac5e69da 113 return 0;
618b7f29 114 if (m_exp >= SREAL_PART_BITS)
fd27ffab 115 return sign * INTTYPE_MAXIMUM (int64_t);
618b7f29 116 if (m_exp > 0)
a5f4d3d6 117 return sign * (SREAL_ABS ((int64_t)m_sig) << m_exp);
618b7f29 118 if (m_exp < 0)
d1704358
ML
119 return m_sig >> -m_exp;
120 return m_sig;
ac5e69da
JZ
121}
122
2bef63e1
JH
123/* Return value of *this as double.
124 This should be used for debug output only. */
125
126double
127sreal::to_double () const
128{
129 double val = m_sig;
130 if (m_exp)
aadb701b 131 val = ldexp (val, m_exp);
2bef63e1
JH
132 return val;
133}
134
618b7f29 135/* Return *this + other. */
ac5e69da 136
618b7f29
TS
137sreal
138sreal::operator+ (const sreal &other) const
ac5e69da 139{
fd27ffab 140 int dexp;
7a1ce632
JH
141 sreal tmp;
142 int64_t r_sig, r_exp;
d1704358
ML
143
144 const sreal *a_p = this, *b_p = &other, *bb;
fd27ffab 145
8301b194 146 if (a_p->m_exp < b_p->m_exp)
fd27ffab
ML
147 std::swap (a_p, b_p);
148
618b7f29 149 dexp = a_p->m_exp - b_p->m_exp;
7a1ce632 150 r_exp = a_p->m_exp;
ac5e69da
JZ
151 if (dexp > SREAL_BITS)
152 {
7a1ce632
JH
153 r_sig = a_p->m_sig;
154
155 sreal r;
156 r.m_sig = r_sig;
157 r.m_exp = r_exp;
ac5e69da
JZ
158 return r;
159 }
160
161 if (dexp == 0)
618b7f29 162 bb = b_p;
ac5e69da
JZ
163 else
164 {
618b7f29
TS
165 tmp = *b_p;
166 tmp.shift_right (dexp);
ac5e69da
JZ
167 bb = &tmp;
168 }
169
a5f4d3d6 170 r_sig = a_p->m_sig + (int64_t)bb->m_sig;
7a1ce632 171 sreal r (r_sig, r_exp);
ac5e69da
JZ
172 return r;
173}
174
d1704358 175
618b7f29 176/* Return *this - other. */
ac5e69da 177
618b7f29
TS
178sreal
179sreal::operator- (const sreal &other) const
ac5e69da
JZ
180{
181 int dexp;
7a1ce632
JH
182 sreal tmp;
183 int64_t r_sig, r_exp;
618b7f29 184 const sreal *bb;
d1704358 185 const sreal *a_p = this, *b_p = &other;
ac5e69da 186
d1704358
ML
187 int64_t sign = 1;
188 if (a_p->m_exp < b_p->m_exp)
189 {
190 sign = -1;
191 std::swap (a_p, b_p);
192 }
ac5e69da 193
d1704358 194 dexp = a_p->m_exp - b_p->m_exp;
7a1ce632 195 r_exp = a_p->m_exp;
ac5e69da
JZ
196 if (dexp > SREAL_BITS)
197 {
7a1ce632
JH
198 r_sig = sign * a_p->m_sig;
199
200 sreal r;
201 r.m_sig = r_sig;
202 r.m_exp = r_exp;
ac5e69da
JZ
203 return r;
204 }
205 if (dexp == 0)
fd27ffab 206 bb = b_p;
ac5e69da
JZ
207 else
208 {
fd27ffab 209 tmp = *b_p;
618b7f29 210 tmp.shift_right (dexp);
ac5e69da
JZ
211 bb = &tmp;
212 }
213
a5f4d3d6 214 r_sig = sign * ((int64_t) a_p->m_sig - (int64_t)bb->m_sig);
7a1ce632 215 sreal r (r_sig, r_exp);
ac5e69da
JZ
216 return r;
217}
218
618b7f29 219/* Return *this * other. */
ac5e69da 220
618b7f29
TS
221sreal
222sreal::operator* (const sreal &other) const
ac5e69da 223{
fd27ffab 224 sreal r;
7a1ce632
JH
225 if (absu_hwi (m_sig) < SREAL_MIN_SIG
226 || absu_hwi (other.m_sig) < SREAL_MIN_SIG)
ac5e69da 227 {
618b7f29
TS
228 r.m_sig = 0;
229 r.m_exp = -SREAL_MAX_EXP;
ac5e69da
JZ
230 }
231 else
7a1ce632 232 r.normalize (m_sig * (int64_t) other.m_sig, m_exp + other.m_exp);
fd27ffab 233
ac5e69da
JZ
234 return r;
235}
236
618b7f29 237/* Return *this / other. */
ac5e69da 238
618b7f29
TS
239sreal
240sreal::operator/ (const sreal &other) const
ac5e69da 241{
fd27ffab 242 gcc_checking_assert (other.m_sig != 0);
7a1ce632
JH
243 sreal r (SREAL_SIGN (m_sig)
244 * ((int64_t)SREAL_ABS (m_sig) << SREAL_PART_BITS) / other.m_sig,
245 m_exp - other.m_exp - SREAL_PART_BITS);
ac5e69da
JZ
246 return r;
247}
dcbdb17a 248
8a267096
JH
249/* Stream sreal value to OB. */
250
251void
252sreal::stream_out (struct output_block *ob)
253{
254 streamer_write_hwi (ob, m_sig);
255 streamer_write_hwi (ob, m_exp);
256}
257
258/* Read sreal value from IB. */
259
260sreal
99b1c316 261sreal::stream_in (class lto_input_block *ib)
8a267096
JH
262{
263 sreal val;
264 val.m_sig = streamer_read_hwi (ib);
265 val.m_exp = streamer_read_hwi (ib);
266 return val;
267}
268
dcbdb17a
ML
269#if CHECKING_P
270
271namespace selftest {
272
273/* Selftests for sreals. */
274
275/* Verify basic sreal operations. */
276
277static void
278sreal_verify_basics (void)
279{
a5f4d3d6
JH
280 sreal minimum = INT_MIN/2;
281 sreal maximum = INT_MAX/2;
dcbdb17a
ML
282
283 sreal seven = 7;
284 sreal minus_two = -2;
285 sreal minus_nine = -9;
286
a5f4d3d6
JH
287 ASSERT_EQ (INT_MIN/2, minimum.to_int ());
288 ASSERT_EQ (INT_MAX/2, maximum.to_int ());
dcbdb17a
ML
289
290 ASSERT_FALSE (minus_two < minus_two);
291 ASSERT_FALSE (seven < seven);
292 ASSERT_TRUE (seven > minus_two);
293 ASSERT_TRUE (minus_two < seven);
294 ASSERT_TRUE (minus_two != seven);
295 ASSERT_EQ (minus_two, -2);
296 ASSERT_EQ (seven, 7);
297 ASSERT_EQ ((seven << 10) >> 10, 7);
298 ASSERT_EQ (seven + minus_nine, -2);
299}
300
301/* Helper function that performs basic arithmetics and comparison
302 of given arguments A and B. */
303
304static void
305verify_aritmetics (int64_t a, int64_t b)
306{
307 ASSERT_EQ (a, -(-(sreal (a))).to_int ());
308 ASSERT_EQ (a < b, sreal (a) < sreal (b));
309 ASSERT_EQ (a <= b, sreal (a) <= sreal (b));
310 ASSERT_EQ (a == b, sreal (a) == sreal (b));
311 ASSERT_EQ (a != b, sreal (a) != sreal (b));
312 ASSERT_EQ (a > b, sreal (a) > sreal (b));
313 ASSERT_EQ (a >= b, sreal (a) >= sreal (b));
314 ASSERT_EQ (a + b, (sreal (a) + sreal (b)).to_int ());
315 ASSERT_EQ (a - b, (sreal (a) - sreal (b)).to_int ());
316 ASSERT_EQ (b + a, (sreal (b) + sreal (a)).to_int ());
317 ASSERT_EQ (b - a, (sreal (b) - sreal (a)).to_int ());
318}
319
320/* Verify arithmetics for interesting numbers. */
321
322static void
323sreal_verify_arithmetics (void)
324{
325 int values[] = {-14123413, -7777, -17, -10, -2, 0, 17, 139, 1234123};
326 unsigned c = sizeof (values) / sizeof (int);
327
328 for (unsigned i = 0; i < c; i++)
329 for (unsigned j = 0; j < c; j++)
330 {
331 int a = values[i];
332 int b = values[j];
333
334 verify_aritmetics (a, b);
335 }
336}
337
338/* Helper function that performs various shifting test of a given
339 argument A. */
340
341static void
342verify_shifting (int64_t a)
343{
344 sreal v = a;
345
346 for (unsigned i = 0; i < 16; i++)
347 ASSERT_EQ (a << i, (v << i).to_int());
348
349 a = a << 16;
350 v = v << 16;
351
352 for (unsigned i = 0; i < 16; i++)
353 ASSERT_EQ (a >> i, (v >> i).to_int());
354}
355
356/* Verify shifting for interesting numbers. */
357
358static void
359sreal_verify_shifting (void)
360{
361 int values[] = {0, 17, 32, 139, 1024, 55555, 1234123};
362 unsigned c = sizeof (values) / sizeof (int);
363
364 for (unsigned i = 0; i < c; i++)
365 verify_shifting (values[i]);
366}
367
a4f28954
ML
368/* Verify division by (of) a negative value. */
369
370static void
371sreal_verify_negative_division (void)
372{
373 ASSERT_EQ (sreal (1) / sreal (1), sreal (1));
374 ASSERT_EQ (sreal (-1) / sreal (-1), sreal (1));
375 ASSERT_EQ (sreal (-1234567) / sreal (-1234567), sreal (1));
376 ASSERT_EQ (sreal (-1234567) / sreal (1234567), sreal (-1));
377 ASSERT_EQ (sreal (1234567) / sreal (-1234567), sreal (-1));
378}
379
dcbdb17a
ML
380/* Run all of the selftests within this file. */
381
382void sreal_c_tests ()
383{
384 sreal_verify_basics ();
385 sreal_verify_arithmetics ();
386 sreal_verify_shifting ();
a4f28954 387 sreal_verify_negative_division ();
dcbdb17a
ML
388}
389
390} // namespace selftest
391#endif /* CHECKING_P */