1 /* Simple data type for real numbers for the GNU compiler.
2 Copyright (C) 2002-2018 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)", 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 (m_sig
) << m_exp
);
119 return m_sig
>> -m_exp
;
123 /* Return value of *this as double.
124 This should be used for debug output only. */
127 sreal::to_double () const
131 val
= ldexp (val
, m_exp
);
135 /* Return *this + other. */
138 sreal::operator+ (const sreal
&other
) const
143 const sreal
*a_p
= this, *b_p
= &other
, *bb
;
145 if (a_p
->m_exp
< b_p
->m_exp
)
146 std::swap (a_p
, b_p
);
148 dexp
= a_p
->m_exp
- b_p
->m_exp
;
149 r
.m_exp
= a_p
->m_exp
;
150 if (dexp
> SREAL_BITS
)
152 r
.m_sig
= a_p
->m_sig
;
161 tmp
.shift_right (dexp
);
165 r
.m_sig
= a_p
->m_sig
+ bb
->m_sig
;
171 /* Return *this - other. */
174 sreal::operator- (const sreal
&other
) const
179 const sreal
*a_p
= this, *b_p
= &other
;
182 if (a_p
->m_exp
< b_p
->m_exp
)
185 std::swap (a_p
, b_p
);
188 dexp
= a_p
->m_exp
- b_p
->m_exp
;
189 r
.m_exp
= a_p
->m_exp
;
190 if (dexp
> SREAL_BITS
)
192 r
.m_sig
= sign
* a_p
->m_sig
;
200 tmp
.shift_right (dexp
);
204 r
.m_sig
= sign
* (a_p
->m_sig
- bb
->m_sig
);
209 /* Return *this * other. */
212 sreal::operator* (const sreal
&other
) const
215 if (absu_hwi (m_sig
) < SREAL_MIN_SIG
|| absu_hwi (other
.m_sig
) < SREAL_MIN_SIG
)
218 r
.m_exp
= -SREAL_MAX_EXP
;
222 r
.m_sig
= m_sig
* other
.m_sig
;
223 r
.m_exp
= m_exp
+ other
.m_exp
;
230 /* Return *this / other. */
233 sreal::operator/ (const sreal
&other
) const
235 gcc_checking_assert (other
.m_sig
!= 0);
238 = SREAL_SIGN (m_sig
) * (SREAL_ABS (m_sig
) << SREAL_PART_BITS
) / other
.m_sig
;
239 r
.m_exp
= m_exp
- other
.m_exp
- SREAL_PART_BITS
;
244 /* Stream sreal value to OB. */
247 sreal::stream_out (struct output_block
*ob
)
249 streamer_write_hwi (ob
, m_sig
);
250 streamer_write_hwi (ob
, m_exp
);
253 /* Read sreal value from IB. */
256 sreal::stream_in (struct lto_input_block
*ib
)
259 val
.m_sig
= streamer_read_hwi (ib
);
260 val
.m_exp
= streamer_read_hwi (ib
);
268 /* Selftests for sreals. */
270 /* Verify basic sreal operations. */
273 sreal_verify_basics (void)
275 sreal minimum
= INT_MIN
;
276 sreal maximum
= INT_MAX
;
279 sreal minus_two
= -2;
280 sreal minus_nine
= -9;
282 ASSERT_EQ (INT_MIN
, minimum
.to_int ());
283 ASSERT_EQ (INT_MAX
, maximum
.to_int ());
285 ASSERT_FALSE (minus_two
< minus_two
);
286 ASSERT_FALSE (seven
< seven
);
287 ASSERT_TRUE (seven
> minus_two
);
288 ASSERT_TRUE (minus_two
< seven
);
289 ASSERT_TRUE (minus_two
!= seven
);
290 ASSERT_EQ (minus_two
, -2);
291 ASSERT_EQ (seven
, 7);
292 ASSERT_EQ ((seven
<< 10) >> 10, 7);
293 ASSERT_EQ (seven
+ minus_nine
, -2);
296 /* Helper function that performs basic arithmetics and comparison
297 of given arguments A and B. */
300 verify_aritmetics (int64_t a
, int64_t b
)
302 ASSERT_EQ (a
, -(-(sreal (a
))).to_int ());
303 ASSERT_EQ (a
< b
, sreal (a
) < sreal (b
));
304 ASSERT_EQ (a
<= b
, sreal (a
) <= sreal (b
));
305 ASSERT_EQ (a
== b
, sreal (a
) == sreal (b
));
306 ASSERT_EQ (a
!= b
, sreal (a
) != sreal (b
));
307 ASSERT_EQ (a
> b
, sreal (a
) > sreal (b
));
308 ASSERT_EQ (a
>= b
, sreal (a
) >= sreal (b
));
309 ASSERT_EQ (a
+ b
, (sreal (a
) + sreal (b
)).to_int ());
310 ASSERT_EQ (a
- b
, (sreal (a
) - sreal (b
)).to_int ());
311 ASSERT_EQ (b
+ a
, (sreal (b
) + sreal (a
)).to_int ());
312 ASSERT_EQ (b
- a
, (sreal (b
) - sreal (a
)).to_int ());
315 /* Verify arithmetics for interesting numbers. */
318 sreal_verify_arithmetics (void)
320 int values
[] = {-14123413, -7777, -17, -10, -2, 0, 17, 139, 1234123};
321 unsigned c
= sizeof (values
) / sizeof (int);
323 for (unsigned i
= 0; i
< c
; i
++)
324 for (unsigned j
= 0; j
< c
; j
++)
329 verify_aritmetics (a
, b
);
333 /* Helper function that performs various shifting test of a given
337 verify_shifting (int64_t a
)
341 for (unsigned i
= 0; i
< 16; i
++)
342 ASSERT_EQ (a
<< i
, (v
<< i
).to_int());
347 for (unsigned i
= 0; i
< 16; i
++)
348 ASSERT_EQ (a
>> i
, (v
>> i
).to_int());
351 /* Verify shifting for interesting numbers. */
354 sreal_verify_shifting (void)
356 int values
[] = {0, 17, 32, 139, 1024, 55555, 1234123};
357 unsigned c
= sizeof (values
) / sizeof (int);
359 for (unsigned i
= 0; i
< c
; i
++)
360 verify_shifting (values
[i
]);
363 /* Verify division by (of) a negative value. */
366 sreal_verify_negative_division (void)
368 ASSERT_EQ (sreal (1) / sreal (1), sreal (1));
369 ASSERT_EQ (sreal (-1) / sreal (-1), sreal (1));
370 ASSERT_EQ (sreal (-1234567) / sreal (-1234567), sreal (1));
371 ASSERT_EQ (sreal (-1234567) / sreal (1234567), sreal (-1));
372 ASSERT_EQ (sreal (1234567) / sreal (-1234567), sreal (-1));
375 /* Run all of the selftests within this file. */
377 void sreal_c_tests ()
379 sreal_verify_basics ();
380 sreal_verify_arithmetics ();
381 sreal_verify_shifting ();
382 sreal_verify_negative_division ();
385 } // namespace selftest
386 #endif /* CHECKING_P */