1 /* Simple data type for real numbers for the GNU compiler.
2 Copyright (C) 2002-2023 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
20 /* This library supports real numbers;
21 inf and nan are NOT supported.
22 It is written to be simple and fast.
28 (for < 64-bit machines sig = sig_lo + sig_hi * 2 ^ SREAL_PART_BITS)
31 One uint64_t is used for the significant.
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.
34 So the precision is 32-bit.
36 Invariant: The numbers are normalized before and after each call of sreal_*.
39 All numbers (except zero) meet following conditions:
40 SREAL_MIN_SIG <= sig && sig <= SREAL_MAX_SIG
41 -SREAL_MAX_EXP <= exp && exp <= SREAL_MAX_EXP
43 If the number would be too large, it is set to upper bounds of these
46 If the number is zero or would be too small it meets following conditions:
47 sig == 0 && exp == -SREAL_MAX_EXP
53 #include "coretypes.h"
60 #include "data-streamer.h"
62 /* Print the content of struct sreal. */
65 sreal::dump (FILE *file
) const
67 fprintf (file
, "(%" PRIi64
" * 2^%d)", (int64_t)m_sig
, m_exp
);
71 debug (const sreal
&ref
)
77 debug (const sreal
*ptr
)
82 fprintf (stderr
, "<nil>\n");
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).
90 sreal::shift_right (int s
)
92 gcc_checking_assert (s
> 0);
93 gcc_checking_assert (s
<= SREAL_BITS
);
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
97 gcc_checking_assert (m_exp
+ s
<= SREAL_MAX_EXP
);
101 m_sig
+= (int64_t) 1 << (s
- 1);
105 /* Return integer value of *this. */
108 sreal::to_int () const
110 int64_t sign
= SREAL_SIGN (m_sig
);
112 if (m_exp
<= -SREAL_BITS
)
114 if (m_exp
>= SREAL_PART_BITS
)
115 return sign
* INTTYPE_MAXIMUM (int64_t);
117 return sign
* (SREAL_ABS ((int64_t)m_sig
) << m_exp
);
119 return sign
* (SREAL_ABS ((int64_t)m_sig
) >> -m_exp
);
123 /* Return nearest integer value of *this. */
126 sreal::to_nearest_int () const
128 int64_t sign
= SREAL_SIGN (m_sig
);
130 if (m_exp
<= -SREAL_BITS
)
132 if (m_exp
>= SREAL_PART_BITS
)
133 return sign
* INTTYPE_MAXIMUM (int64_t);
135 return sign
* (SREAL_ABS ((int64_t)m_sig
) << m_exp
);
137 return sign
* ((SREAL_ABS ((int64_t)m_sig
) >> -m_exp
)
138 + ((SREAL_ABS (m_sig
) >> (-m_exp
- 1)) & 1));
142 /* Return value of *this as double.
143 This should be used for debug output only. */
146 sreal::to_double () const
150 val
= ldexp (val
, m_exp
);
154 /* Return *this + other. */
157 sreal::operator+ (const sreal
&other
) const
161 int64_t r_sig
, r_exp
;
163 const sreal
*a_p
= this, *b_p
= &other
, *bb
;
165 if (a_p
->m_exp
< b_p
->m_exp
)
166 std::swap (a_p
, b_p
);
168 dexp
= a_p
->m_exp
- b_p
->m_exp
;
170 if (dexp
> SREAL_BITS
)
185 tmp
.shift_right (dexp
);
189 r_sig
= a_p
->m_sig
+ (int64_t)bb
->m_sig
;
190 sreal
r (r_sig
, r_exp
);
195 /* Return *this - other. */
198 sreal::operator- (const sreal
&other
) const
202 int64_t r_sig
, r_exp
;
204 const sreal
*a_p
= this, *b_p
= &other
;
207 if (a_p
->m_exp
< b_p
->m_exp
)
210 std::swap (a_p
, b_p
);
213 dexp
= a_p
->m_exp
- b_p
->m_exp
;
215 if (dexp
> SREAL_BITS
)
217 r_sig
= sign
* a_p
->m_sig
;
229 tmp
.shift_right (dexp
);
233 r_sig
= sign
* ((int64_t) a_p
->m_sig
- (int64_t)bb
->m_sig
);
234 sreal
r (r_sig
, r_exp
);
238 /* Return *this * other. */
241 sreal::operator* (const sreal
&other
) const
244 if (absu_hwi (m_sig
) < SREAL_MIN_SIG
245 || absu_hwi (other
.m_sig
) < SREAL_MIN_SIG
)
248 r
.m_exp
= -SREAL_MAX_EXP
;
251 r
.normalize (m_sig
* (int64_t) other
.m_sig
, m_exp
+ other
.m_exp
);
256 /* Return *this / other. */
259 sreal::operator/ (const sreal
&other
) const
261 gcc_checking_assert (other
.m_sig
!= 0);
262 sreal
r (SREAL_SIGN (m_sig
)
263 * ((int64_t)SREAL_ABS (m_sig
) << SREAL_PART_BITS
) / other
.m_sig
,
264 m_exp
- other
.m_exp
- SREAL_PART_BITS
);
268 /* Stream sreal value to OB. */
271 sreal::stream_out (struct output_block
*ob
)
273 streamer_write_hwi (ob
, m_sig
);
274 streamer_write_hwi (ob
, m_exp
);
277 /* Read sreal value from IB. */
280 sreal::stream_in (class lto_input_block
*ib
)
283 val
.m_sig
= streamer_read_hwi (ib
);
284 val
.m_exp
= streamer_read_hwi (ib
);
292 /* Selftests for sreals. */
294 /* Verify basic sreal operations. */
297 sreal_verify_basics (void)
299 sreal minimum
= INT_MIN
/2;
300 sreal maximum
= INT_MAX
/2;
303 sreal minus_two
= -2;
304 sreal minus_nine
= -9;
306 ASSERT_EQ (INT_MIN
/2, minimum
.to_int ());
307 ASSERT_EQ (INT_MAX
/2, maximum
.to_int ());
308 ASSERT_EQ (INT_MIN
/2, minimum
.to_nearest_int ());
309 ASSERT_EQ (INT_MAX
/2, maximum
.to_nearest_int ());
311 ASSERT_FALSE (minus_two
< minus_two
);
312 ASSERT_FALSE (seven
< seven
);
313 ASSERT_TRUE (seven
> minus_two
);
314 ASSERT_TRUE (minus_two
< seven
);
315 ASSERT_TRUE (minus_two
!= seven
);
316 ASSERT_EQ (minus_two
, -2);
317 ASSERT_EQ (seven
, 7);
318 ASSERT_EQ ((seven
<< 10) >> 10, 7);
319 ASSERT_EQ (seven
+ minus_nine
, -2);
322 /* Helper function that performs basic arithmetics and comparison
323 of given arguments A and B. */
326 verify_arithmetics (int64_t a
, int64_t b
)
328 ASSERT_EQ (a
, -(-(sreal (a
))).to_int ());
329 ASSERT_EQ (a
< b
, sreal (a
) < sreal (b
));
330 ASSERT_EQ (a
<= b
, sreal (a
) <= sreal (b
));
331 ASSERT_EQ (a
== b
, sreal (a
) == sreal (b
));
332 ASSERT_EQ (a
!= b
, sreal (a
) != sreal (b
));
333 ASSERT_EQ (a
> b
, sreal (a
) > sreal (b
));
334 ASSERT_EQ (a
>= b
, sreal (a
) >= sreal (b
));
335 ASSERT_EQ (a
+ b
, (sreal (a
) + sreal (b
)).to_int ());
336 ASSERT_EQ (a
- b
, (sreal (a
) - sreal (b
)).to_int ());
337 ASSERT_EQ (b
+ a
, (sreal (b
) + sreal (a
)).to_int ());
338 ASSERT_EQ (b
- a
, (sreal (b
) - sreal (a
)).to_int ());
339 ASSERT_EQ (a
+ b
, (sreal (a
) + sreal (b
)).to_nearest_int ());
340 ASSERT_EQ (a
- b
, (sreal (a
) - sreal (b
)).to_nearest_int ());
341 ASSERT_EQ (b
+ a
, (sreal (b
) + sreal (a
)).to_nearest_int ());
342 ASSERT_EQ (b
- a
, (sreal (b
) - sreal (a
)).to_nearest_int ());
345 /* Verify arithmetics for interesting numbers. */
348 sreal_verify_arithmetics (void)
350 int values
[] = {-14123413, -7777, -17, -10, -2, 0, 17, 139, 1234123};
351 unsigned c
= sizeof (values
) / sizeof (int);
353 for (unsigned i
= 0; i
< c
; i
++)
354 for (unsigned j
= 0; j
< c
; j
++)
359 verify_arithmetics (a
, b
);
363 /* Helper function that performs various shifting test of a given
367 verify_shifting (int64_t a
)
371 for (unsigned i
= 0; i
< 16; i
++)
372 ASSERT_EQ (a
<< i
, (v
<< i
).to_int());
377 for (unsigned i
= 0; i
< 16; i
++)
378 ASSERT_EQ (a
>> i
, (v
>> i
).to_int());
381 /* Verify shifting for interesting numbers. */
384 sreal_verify_shifting (void)
386 int values
[] = {0, 17, 32, 139, 1024, 55555, 1234123};
387 unsigned c
= sizeof (values
) / sizeof (int);
389 for (unsigned i
= 0; i
< c
; i
++)
390 verify_shifting (values
[i
]);
393 /* Verify division by (of) a negative value. */
396 sreal_verify_negative_division (void)
398 ASSERT_EQ (sreal (1) / sreal (1), sreal (1));
399 ASSERT_EQ (sreal (-1) / sreal (-1), sreal (1));
400 ASSERT_EQ (sreal (-1234567) / sreal (-1234567), sreal (1));
401 ASSERT_EQ (sreal (-1234567) / sreal (1234567), sreal (-1));
402 ASSERT_EQ (sreal (1234567) / sreal (-1234567), sreal (-1));
406 sreal_verify_conversions (void)
408 ASSERT_EQ ((sreal (11) / sreal (3)).to_int (), 3);
409 ASSERT_EQ ((sreal (11) / sreal (3)).to_nearest_int (), 4);
410 ASSERT_EQ ((sreal (10) / sreal (3)).to_int (), 3);
411 ASSERT_EQ ((sreal (10) / sreal (3)).to_nearest_int (), 3);
412 ASSERT_EQ ((sreal (9) / sreal (3)).to_int (), 3);
413 ASSERT_EQ ((sreal (9) / sreal (3)).to_nearest_int (), 3);
414 ASSERT_EQ ((sreal (-11) / sreal (3)).to_int (), -3);
415 ASSERT_EQ ((sreal (-11) / sreal (3)).to_nearest_int (), -4);
416 ASSERT_EQ ((sreal (-10) / sreal (3)).to_int (), -3);
417 ASSERT_EQ ((sreal (-10) / sreal (3)).to_nearest_int (), -3);
418 ASSERT_EQ ((sreal (-3)).to_int (), -3);
419 ASSERT_EQ ((sreal (-3)).to_nearest_int (), -3);
420 for (int i
= -100000 ; i
< 100000; i
+= 123)
421 for (int j
= -10000 ; j
< 100000; j
+= 71)
424 sreal sval
= ((sreal
)i
) / (sreal
)j
;
425 double val
= (double)i
/ (double)j
;
426 ASSERT_EQ ((fabs (sval
.to_double () - val
) < 0.00001), true);
427 ASSERT_EQ (sval
.to_int (), (int)val
);
428 ASSERT_EQ (sval
.to_nearest_int (), lround (val
));
432 /* Run all of the selftests within this file. */
434 void sreal_cc_tests ()
436 sreal_verify_basics ();
437 sreal_verify_arithmetics ();
438 sreal_verify_shifting ();
439 sreal_verify_negative_division ();
440 sreal_verify_conversions ();
443 } // namespace selftest
444 #endif /* CHECKING_P */