1 /* Simple data type for real numbers for the GNU compiler.
2 Copyright (C) 2002-2014 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"
56 /* Print the content of struct sreal. */
59 sreal::dump (FILE *file
) const
61 fprintf (file
, "(%" PRIu64
" * 2^%d)", m_sig
, m_exp
);
65 debug (const sreal
&ref
)
71 debug (const sreal
*ptr
)
76 fprintf (stderr
, "<nil>\n");
79 /* Shift this right by S bits. Needed: 0 < S <= SREAL_BITS.
80 When the most significant bit shifted out is 1, add 1 to this (rounding).
84 sreal::shift_right (int s
)
86 gcc_checking_assert (s
> 0);
87 gcc_checking_assert (s
<= SREAL_BITS
);
88 /* Exponent should never be so large because shift_right is used only by
89 sreal_add and sreal_sub ant thus the number cannot be shifted out from
91 gcc_checking_assert (m_exp
+ s
<= SREAL_MAX_EXP
);
95 m_sig
+= (int64_t) 1 << (s
- 1);
99 /* Normalize *this. */
104 int64_t s
= m_sig
< 0 ? -1 : 1;
105 unsigned HOST_WIDE_INT sig
= absu_hwi (m_sig
);
109 m_exp
= -SREAL_MAX_EXP
;
111 else if (sig
< SREAL_MIN_SIG
)
118 while (sig
< SREAL_MIN_SIG
);
120 /* Check underflow. */
121 if (m_exp
< -SREAL_MAX_EXP
)
123 m_exp
= -SREAL_MAX_EXP
;
127 else if (sig
> SREAL_MAX_SIG
)
136 while (sig
> SREAL_MAX_SIG
);
138 /* Round the number. */
140 if (sig
> SREAL_MAX_SIG
)
146 /* Check overflow. */
147 if (m_exp
> SREAL_MAX_EXP
)
149 m_exp
= SREAL_MAX_EXP
;
157 /* Return integer value of *this. */
160 sreal::to_int () const
162 int64_t sign
= m_sig
< 0 ? -1 : 1;
164 if (m_exp
<= -SREAL_BITS
)
166 if (m_exp
>= SREAL_PART_BITS
)
167 return sign
* INTTYPE_MAXIMUM (int64_t);
169 return m_sig
<< m_exp
;
171 return m_sig
>> -m_exp
;
175 /* Return value of *this as double.
176 This should be used for debug output only. */
179 sreal::to_double () const
187 /* Return *this + other. */
190 sreal::operator+ (const sreal
&other
) const
195 const sreal
*a_p
= this, *b_p
= &other
, *bb
;
197 if (a_p
->m_exp
< b_p
->m_exp
)
198 std::swap (a_p
, b_p
);
200 dexp
= a_p
->m_exp
- b_p
->m_exp
;
201 r
.m_exp
= a_p
->m_exp
;
202 if (dexp
> SREAL_BITS
)
204 r
.m_sig
= a_p
->m_sig
;
213 tmp
.shift_right (dexp
);
217 r
.m_sig
= a_p
->m_sig
+ bb
->m_sig
;
223 /* Return *this - other. */
226 sreal::operator- (const sreal
&other
) const
231 const sreal
*a_p
= this, *b_p
= &other
;
234 if (a_p
->m_exp
< b_p
->m_exp
)
237 std::swap (a_p
, b_p
);
240 dexp
= a_p
->m_exp
- b_p
->m_exp
;
241 r
.m_exp
= a_p
->m_exp
;
242 if (dexp
> SREAL_BITS
)
244 r
.m_sig
= sign
* a_p
->m_sig
;
252 tmp
.shift_right (dexp
);
256 r
.m_sig
= sign
* (a_p
->m_sig
- bb
->m_sig
);
261 /* Return *this * other. */
264 sreal::operator* (const sreal
&other
) const
267 if (absu_hwi (m_sig
) < SREAL_MIN_SIG
|| absu_hwi (other
.m_sig
) < SREAL_MIN_SIG
)
270 r
.m_exp
= -SREAL_MAX_EXP
;
274 r
.m_sig
= m_sig
* other
.m_sig
;
275 r
.m_exp
= m_exp
+ other
.m_exp
;
282 /* Return *this / other. */
285 sreal::operator/ (const sreal
&other
) const
287 gcc_checking_assert (other
.m_sig
!= 0);
289 r
.m_sig
= (m_sig
<< SREAL_PART_BITS
) / other
.m_sig
;
290 r
.m_exp
= m_exp
- other
.m_exp
- SREAL_PART_BITS
;