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