1*e4b17023SJohn Marino /* Simple data type for positive real numbers for the GNU compiler.
2*e4b17023SJohn Marino Copyright (C) 2002, 2003, 2004, 2007, 2010 Free Software Foundation, Inc.
3*e4b17023SJohn Marino
4*e4b17023SJohn Marino This file is part of GCC.
5*e4b17023SJohn Marino
6*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
7*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
8*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
9*e4b17023SJohn Marino version.
10*e4b17023SJohn Marino
11*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
13*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14*e4b17023SJohn Marino for more details.
15*e4b17023SJohn Marino
16*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
17*e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see
18*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
19*e4b17023SJohn Marino
20*e4b17023SJohn Marino /* This library supports positive real numbers and 0;
21*e4b17023SJohn Marino inf and nan are NOT supported.
22*e4b17023SJohn Marino It is written to be simple and fast.
23*e4b17023SJohn Marino
24*e4b17023SJohn Marino Value of sreal is
25*e4b17023SJohn Marino x = sig * 2 ^ exp
26*e4b17023SJohn Marino where
27*e4b17023SJohn Marino sig = significant
28*e4b17023SJohn Marino (for < 64-bit machines sig = sig_lo + sig_hi * 2 ^ SREAL_PART_BITS)
29*e4b17023SJohn Marino exp = exponent
30*e4b17023SJohn Marino
31*e4b17023SJohn Marino One HOST_WIDE_INT is used for the significant on 64-bit (and more than
32*e4b17023SJohn Marino 64-bit) machines,
33*e4b17023SJohn Marino otherwise two HOST_WIDE_INTs are used for the significant.
34*e4b17023SJohn Marino Only a half of significant bits is used (in normalized sreals) so that we do
35*e4b17023SJohn Marino not have problems with overflow, for example when c->sig = a->sig * b->sig.
36*e4b17023SJohn Marino So the precision for 64-bit and 32-bit machines is 32-bit.
37*e4b17023SJohn Marino
38*e4b17023SJohn Marino Invariant: The numbers are normalized before and after each call of sreal_*.
39*e4b17023SJohn Marino
40*e4b17023SJohn Marino Normalized sreals:
41*e4b17023SJohn Marino All numbers (except zero) meet following conditions:
42*e4b17023SJohn Marino SREAL_MIN_SIG <= sig && sig <= SREAL_MAX_SIG
43*e4b17023SJohn Marino -SREAL_MAX_EXP <= exp && exp <= SREAL_MAX_EXP
44*e4b17023SJohn Marino
45*e4b17023SJohn Marino If the number would be too large, it is set to upper bounds of these
46*e4b17023SJohn Marino conditions.
47*e4b17023SJohn Marino
48*e4b17023SJohn Marino If the number is zero or would be too small it meets following conditions:
49*e4b17023SJohn Marino sig == 0 && exp == -SREAL_MAX_EXP
50*e4b17023SJohn Marino */
51*e4b17023SJohn Marino
52*e4b17023SJohn Marino #include "config.h"
53*e4b17023SJohn Marino #include "system.h"
54*e4b17023SJohn Marino #include "coretypes.h"
55*e4b17023SJohn Marino #include "sreal.h"
56*e4b17023SJohn Marino
57*e4b17023SJohn Marino static inline void copy (sreal *, sreal *);
58*e4b17023SJohn Marino static inline void shift_right (sreal *, int);
59*e4b17023SJohn Marino static void normalize (sreal *);
60*e4b17023SJohn Marino
61*e4b17023SJohn Marino /* Print the content of struct sreal. */
62*e4b17023SJohn Marino
63*e4b17023SJohn Marino void
dump_sreal(FILE * file,sreal * x)64*e4b17023SJohn Marino dump_sreal (FILE *file, sreal *x)
65*e4b17023SJohn Marino {
66*e4b17023SJohn Marino #if SREAL_PART_BITS < 32
67*e4b17023SJohn Marino fprintf (file, "((" HOST_WIDE_INT_PRINT_UNSIGNED " * 2^16 + "
68*e4b17023SJohn Marino HOST_WIDE_INT_PRINT_UNSIGNED ") * 2^%d)",
69*e4b17023SJohn Marino x->sig_hi, x->sig_lo, x->exp);
70*e4b17023SJohn Marino #else
71*e4b17023SJohn Marino fprintf (file, "(" HOST_WIDE_INT_PRINT_UNSIGNED " * 2^%d)", x->sig, x->exp);
72*e4b17023SJohn Marino #endif
73*e4b17023SJohn Marino }
74*e4b17023SJohn Marino
75*e4b17023SJohn Marino /* Copy the sreal number. */
76*e4b17023SJohn Marino
77*e4b17023SJohn Marino static inline void
copy(sreal * r,sreal * a)78*e4b17023SJohn Marino copy (sreal *r, sreal *a)
79*e4b17023SJohn Marino {
80*e4b17023SJohn Marino #if SREAL_PART_BITS < 32
81*e4b17023SJohn Marino r->sig_lo = a->sig_lo;
82*e4b17023SJohn Marino r->sig_hi = a->sig_hi;
83*e4b17023SJohn Marino #else
84*e4b17023SJohn Marino r->sig = a->sig;
85*e4b17023SJohn Marino #endif
86*e4b17023SJohn Marino r->exp = a->exp;
87*e4b17023SJohn Marino }
88*e4b17023SJohn Marino
89*e4b17023SJohn Marino /* Shift X right by S bits. Needed: 0 < S <= SREAL_BITS.
90*e4b17023SJohn Marino When the most significant bit shifted out is 1, add 1 to X (rounding). */
91*e4b17023SJohn Marino
92*e4b17023SJohn Marino static inline void
shift_right(sreal * x,int s)93*e4b17023SJohn Marino shift_right (sreal *x, int s)
94*e4b17023SJohn Marino {
95*e4b17023SJohn Marino gcc_assert (s > 0);
96*e4b17023SJohn Marino gcc_assert (s <= SREAL_BITS);
97*e4b17023SJohn Marino /* Exponent should never be so large because shift_right is used only by
98*e4b17023SJohn Marino sreal_add and sreal_sub ant thus the number cannot be shifted out from
99*e4b17023SJohn Marino exponent range. */
100*e4b17023SJohn Marino gcc_assert (x->exp + s <= SREAL_MAX_EXP);
101*e4b17023SJohn Marino
102*e4b17023SJohn Marino x->exp += s;
103*e4b17023SJohn Marino
104*e4b17023SJohn Marino #if SREAL_PART_BITS < 32
105*e4b17023SJohn Marino if (s > SREAL_PART_BITS)
106*e4b17023SJohn Marino {
107*e4b17023SJohn Marino s -= SREAL_PART_BITS;
108*e4b17023SJohn Marino x->sig_hi += (uhwi) 1 << (s - 1);
109*e4b17023SJohn Marino x->sig_lo = x->sig_hi >> s;
110*e4b17023SJohn Marino x->sig_hi = 0;
111*e4b17023SJohn Marino }
112*e4b17023SJohn Marino else
113*e4b17023SJohn Marino {
114*e4b17023SJohn Marino x->sig_lo += (uhwi) 1 << (s - 1);
115*e4b17023SJohn Marino if (x->sig_lo & ((uhwi) 1 << SREAL_PART_BITS))
116*e4b17023SJohn Marino {
117*e4b17023SJohn Marino x->sig_hi++;
118*e4b17023SJohn Marino x->sig_lo -= (uhwi) 1 << SREAL_PART_BITS;
119*e4b17023SJohn Marino }
120*e4b17023SJohn Marino x->sig_lo >>= s;
121*e4b17023SJohn Marino x->sig_lo |= (x->sig_hi & (((uhwi) 1 << s) - 1)) << (SREAL_PART_BITS - s);
122*e4b17023SJohn Marino x->sig_hi >>= s;
123*e4b17023SJohn Marino }
124*e4b17023SJohn Marino #else
125*e4b17023SJohn Marino x->sig += (uhwi) 1 << (s - 1);
126*e4b17023SJohn Marino x->sig >>= s;
127*e4b17023SJohn Marino #endif
128*e4b17023SJohn Marino }
129*e4b17023SJohn Marino
130*e4b17023SJohn Marino /* Normalize *X. */
131*e4b17023SJohn Marino
132*e4b17023SJohn Marino static void
normalize(sreal * x)133*e4b17023SJohn Marino normalize (sreal *x)
134*e4b17023SJohn Marino {
135*e4b17023SJohn Marino #if SREAL_PART_BITS < 32
136*e4b17023SJohn Marino int shift;
137*e4b17023SJohn Marino HOST_WIDE_INT mask;
138*e4b17023SJohn Marino
139*e4b17023SJohn Marino if (x->sig_lo == 0 && x->sig_hi == 0)
140*e4b17023SJohn Marino {
141*e4b17023SJohn Marino x->exp = -SREAL_MAX_EXP;
142*e4b17023SJohn Marino }
143*e4b17023SJohn Marino else if (x->sig_hi < SREAL_MIN_SIG)
144*e4b17023SJohn Marino {
145*e4b17023SJohn Marino if (x->sig_hi == 0)
146*e4b17023SJohn Marino {
147*e4b17023SJohn Marino /* Move lower part of significant to higher part. */
148*e4b17023SJohn Marino x->sig_hi = x->sig_lo;
149*e4b17023SJohn Marino x->sig_lo = 0;
150*e4b17023SJohn Marino x->exp -= SREAL_PART_BITS;
151*e4b17023SJohn Marino }
152*e4b17023SJohn Marino shift = 0;
153*e4b17023SJohn Marino while (x->sig_hi < SREAL_MIN_SIG)
154*e4b17023SJohn Marino {
155*e4b17023SJohn Marino x->sig_hi <<= 1;
156*e4b17023SJohn Marino x->exp--;
157*e4b17023SJohn Marino shift++;
158*e4b17023SJohn Marino }
159*e4b17023SJohn Marino /* Check underflow. */
160*e4b17023SJohn Marino if (x->exp < -SREAL_MAX_EXP)
161*e4b17023SJohn Marino {
162*e4b17023SJohn Marino x->exp = -SREAL_MAX_EXP;
163*e4b17023SJohn Marino x->sig_hi = 0;
164*e4b17023SJohn Marino x->sig_lo = 0;
165*e4b17023SJohn Marino }
166*e4b17023SJohn Marino else if (shift)
167*e4b17023SJohn Marino {
168*e4b17023SJohn Marino mask = (1 << SREAL_PART_BITS) - (1 << (SREAL_PART_BITS - shift));
169*e4b17023SJohn Marino x->sig_hi |= (x->sig_lo & mask) >> (SREAL_PART_BITS - shift);
170*e4b17023SJohn Marino x->sig_lo = (x->sig_lo << shift) & (((uhwi) 1 << SREAL_PART_BITS) - 1);
171*e4b17023SJohn Marino }
172*e4b17023SJohn Marino }
173*e4b17023SJohn Marino else if (x->sig_hi > SREAL_MAX_SIG)
174*e4b17023SJohn Marino {
175*e4b17023SJohn Marino unsigned HOST_WIDE_INT tmp = x->sig_hi;
176*e4b17023SJohn Marino
177*e4b17023SJohn Marino /* Find out how many bits will be shifted. */
178*e4b17023SJohn Marino shift = 0;
179*e4b17023SJohn Marino do
180*e4b17023SJohn Marino {
181*e4b17023SJohn Marino tmp >>= 1;
182*e4b17023SJohn Marino shift++;
183*e4b17023SJohn Marino }
184*e4b17023SJohn Marino while (tmp > SREAL_MAX_SIG);
185*e4b17023SJohn Marino
186*e4b17023SJohn Marino /* Round the number. */
187*e4b17023SJohn Marino x->sig_lo += (uhwi) 1 << (shift - 1);
188*e4b17023SJohn Marino
189*e4b17023SJohn Marino x->sig_lo >>= shift;
190*e4b17023SJohn Marino x->sig_lo += ((x->sig_hi & (((uhwi) 1 << shift) - 1))
191*e4b17023SJohn Marino << (SREAL_PART_BITS - shift));
192*e4b17023SJohn Marino x->sig_hi >>= shift;
193*e4b17023SJohn Marino x->exp += shift;
194*e4b17023SJohn Marino if (x->sig_lo & ((uhwi) 1 << SREAL_PART_BITS))
195*e4b17023SJohn Marino {
196*e4b17023SJohn Marino x->sig_lo -= (uhwi) 1 << SREAL_PART_BITS;
197*e4b17023SJohn Marino x->sig_hi++;
198*e4b17023SJohn Marino if (x->sig_hi > SREAL_MAX_SIG)
199*e4b17023SJohn Marino {
200*e4b17023SJohn Marino /* x->sig_hi was SREAL_MAX_SIG before increment
201*e4b17023SJohn Marino so now last bit is zero. */
202*e4b17023SJohn Marino x->sig_hi >>= 1;
203*e4b17023SJohn Marino x->sig_lo >>= 1;
204*e4b17023SJohn Marino x->exp++;
205*e4b17023SJohn Marino }
206*e4b17023SJohn Marino }
207*e4b17023SJohn Marino
208*e4b17023SJohn Marino /* Check overflow. */
209*e4b17023SJohn Marino if (x->exp > SREAL_MAX_EXP)
210*e4b17023SJohn Marino {
211*e4b17023SJohn Marino x->exp = SREAL_MAX_EXP;
212*e4b17023SJohn Marino x->sig_hi = SREAL_MAX_SIG;
213*e4b17023SJohn Marino x->sig_lo = SREAL_MAX_SIG;
214*e4b17023SJohn Marino }
215*e4b17023SJohn Marino }
216*e4b17023SJohn Marino #else
217*e4b17023SJohn Marino if (x->sig == 0)
218*e4b17023SJohn Marino {
219*e4b17023SJohn Marino x->exp = -SREAL_MAX_EXP;
220*e4b17023SJohn Marino }
221*e4b17023SJohn Marino else if (x->sig < SREAL_MIN_SIG)
222*e4b17023SJohn Marino {
223*e4b17023SJohn Marino do
224*e4b17023SJohn Marino {
225*e4b17023SJohn Marino x->sig <<= 1;
226*e4b17023SJohn Marino x->exp--;
227*e4b17023SJohn Marino }
228*e4b17023SJohn Marino while (x->sig < SREAL_MIN_SIG);
229*e4b17023SJohn Marino
230*e4b17023SJohn Marino /* Check underflow. */
231*e4b17023SJohn Marino if (x->exp < -SREAL_MAX_EXP)
232*e4b17023SJohn Marino {
233*e4b17023SJohn Marino x->exp = -SREAL_MAX_EXP;
234*e4b17023SJohn Marino x->sig = 0;
235*e4b17023SJohn Marino }
236*e4b17023SJohn Marino }
237*e4b17023SJohn Marino else if (x->sig > SREAL_MAX_SIG)
238*e4b17023SJohn Marino {
239*e4b17023SJohn Marino int last_bit;
240*e4b17023SJohn Marino do
241*e4b17023SJohn Marino {
242*e4b17023SJohn Marino last_bit = x->sig & 1;
243*e4b17023SJohn Marino x->sig >>= 1;
244*e4b17023SJohn Marino x->exp++;
245*e4b17023SJohn Marino }
246*e4b17023SJohn Marino while (x->sig > SREAL_MAX_SIG);
247*e4b17023SJohn Marino
248*e4b17023SJohn Marino /* Round the number. */
249*e4b17023SJohn Marino x->sig += last_bit;
250*e4b17023SJohn Marino if (x->sig > SREAL_MAX_SIG)
251*e4b17023SJohn Marino {
252*e4b17023SJohn Marino x->sig >>= 1;
253*e4b17023SJohn Marino x->exp++;
254*e4b17023SJohn Marino }
255*e4b17023SJohn Marino
256*e4b17023SJohn Marino /* Check overflow. */
257*e4b17023SJohn Marino if (x->exp > SREAL_MAX_EXP)
258*e4b17023SJohn Marino {
259*e4b17023SJohn Marino x->exp = SREAL_MAX_EXP;
260*e4b17023SJohn Marino x->sig = SREAL_MAX_SIG;
261*e4b17023SJohn Marino }
262*e4b17023SJohn Marino }
263*e4b17023SJohn Marino #endif
264*e4b17023SJohn Marino }
265*e4b17023SJohn Marino
266*e4b17023SJohn Marino /* Set *R to SIG * 2 ^ EXP. Return R. */
267*e4b17023SJohn Marino
268*e4b17023SJohn Marino sreal *
sreal_init(sreal * r,unsigned HOST_WIDE_INT sig,signed int exp)269*e4b17023SJohn Marino sreal_init (sreal *r, unsigned HOST_WIDE_INT sig, signed int exp)
270*e4b17023SJohn Marino {
271*e4b17023SJohn Marino #if SREAL_PART_BITS < 32
272*e4b17023SJohn Marino r->sig_lo = 0;
273*e4b17023SJohn Marino r->sig_hi = sig;
274*e4b17023SJohn Marino r->exp = exp - 16;
275*e4b17023SJohn Marino #else
276*e4b17023SJohn Marino r->sig = sig;
277*e4b17023SJohn Marino r->exp = exp;
278*e4b17023SJohn Marino #endif
279*e4b17023SJohn Marino normalize (r);
280*e4b17023SJohn Marino return r;
281*e4b17023SJohn Marino }
282*e4b17023SJohn Marino
283*e4b17023SJohn Marino /* Return integer value of *R. */
284*e4b17023SJohn Marino
285*e4b17023SJohn Marino HOST_WIDE_INT
sreal_to_int(sreal * r)286*e4b17023SJohn Marino sreal_to_int (sreal *r)
287*e4b17023SJohn Marino {
288*e4b17023SJohn Marino #if SREAL_PART_BITS < 32
289*e4b17023SJohn Marino if (r->exp <= -SREAL_BITS)
290*e4b17023SJohn Marino return 0;
291*e4b17023SJohn Marino if (r->exp >= 0)
292*e4b17023SJohn Marino return MAX_HOST_WIDE_INT;
293*e4b17023SJohn Marino return ((r->sig_hi << SREAL_PART_BITS) + r->sig_lo) >> -r->exp;
294*e4b17023SJohn Marino #else
295*e4b17023SJohn Marino if (r->exp <= -SREAL_BITS)
296*e4b17023SJohn Marino return 0;
297*e4b17023SJohn Marino if (r->exp >= SREAL_PART_BITS)
298*e4b17023SJohn Marino return MAX_HOST_WIDE_INT;
299*e4b17023SJohn Marino if (r->exp > 0)
300*e4b17023SJohn Marino return r->sig << r->exp;
301*e4b17023SJohn Marino if (r->exp < 0)
302*e4b17023SJohn Marino return r->sig >> -r->exp;
303*e4b17023SJohn Marino return r->sig;
304*e4b17023SJohn Marino #endif
305*e4b17023SJohn Marino }
306*e4b17023SJohn Marino
307*e4b17023SJohn Marino /* Compare *A and *B. Return -1 if *A < *B, 1 if *A > *B and 0 if *A == *B. */
308*e4b17023SJohn Marino
309*e4b17023SJohn Marino int
sreal_compare(sreal * a,sreal * b)310*e4b17023SJohn Marino sreal_compare (sreal *a, sreal *b)
311*e4b17023SJohn Marino {
312*e4b17023SJohn Marino if (a->exp > b->exp)
313*e4b17023SJohn Marino return 1;
314*e4b17023SJohn Marino if (a->exp < b->exp)
315*e4b17023SJohn Marino return -1;
316*e4b17023SJohn Marino #if SREAL_PART_BITS < 32
317*e4b17023SJohn Marino if (a->sig_hi > b->sig_hi)
318*e4b17023SJohn Marino return 1;
319*e4b17023SJohn Marino if (a->sig_hi < b->sig_hi)
320*e4b17023SJohn Marino return -1;
321*e4b17023SJohn Marino if (a->sig_lo > b->sig_lo)
322*e4b17023SJohn Marino return 1;
323*e4b17023SJohn Marino if (a->sig_lo < b->sig_lo)
324*e4b17023SJohn Marino return -1;
325*e4b17023SJohn Marino #else
326*e4b17023SJohn Marino if (a->sig > b->sig)
327*e4b17023SJohn Marino return 1;
328*e4b17023SJohn Marino if (a->sig < b->sig)
329*e4b17023SJohn Marino return -1;
330*e4b17023SJohn Marino #endif
331*e4b17023SJohn Marino return 0;
332*e4b17023SJohn Marino }
333*e4b17023SJohn Marino
334*e4b17023SJohn Marino /* *R = *A + *B. Return R. */
335*e4b17023SJohn Marino
336*e4b17023SJohn Marino sreal *
sreal_add(sreal * r,sreal * a,sreal * b)337*e4b17023SJohn Marino sreal_add (sreal *r, sreal *a, sreal *b)
338*e4b17023SJohn Marino {
339*e4b17023SJohn Marino int dexp;
340*e4b17023SJohn Marino sreal tmp;
341*e4b17023SJohn Marino sreal *bb;
342*e4b17023SJohn Marino
343*e4b17023SJohn Marino if (sreal_compare (a, b) < 0)
344*e4b17023SJohn Marino {
345*e4b17023SJohn Marino sreal *swap;
346*e4b17023SJohn Marino swap = a;
347*e4b17023SJohn Marino a = b;
348*e4b17023SJohn Marino b = swap;
349*e4b17023SJohn Marino }
350*e4b17023SJohn Marino
351*e4b17023SJohn Marino dexp = a->exp - b->exp;
352*e4b17023SJohn Marino r->exp = a->exp;
353*e4b17023SJohn Marino if (dexp > SREAL_BITS)
354*e4b17023SJohn Marino {
355*e4b17023SJohn Marino #if SREAL_PART_BITS < 32
356*e4b17023SJohn Marino r->sig_hi = a->sig_hi;
357*e4b17023SJohn Marino r->sig_lo = a->sig_lo;
358*e4b17023SJohn Marino #else
359*e4b17023SJohn Marino r->sig = a->sig;
360*e4b17023SJohn Marino #endif
361*e4b17023SJohn Marino return r;
362*e4b17023SJohn Marino }
363*e4b17023SJohn Marino
364*e4b17023SJohn Marino if (dexp == 0)
365*e4b17023SJohn Marino bb = b;
366*e4b17023SJohn Marino else
367*e4b17023SJohn Marino {
368*e4b17023SJohn Marino copy (&tmp, b);
369*e4b17023SJohn Marino shift_right (&tmp, dexp);
370*e4b17023SJohn Marino bb = &tmp;
371*e4b17023SJohn Marino }
372*e4b17023SJohn Marino
373*e4b17023SJohn Marino #if SREAL_PART_BITS < 32
374*e4b17023SJohn Marino r->sig_hi = a->sig_hi + bb->sig_hi;
375*e4b17023SJohn Marino r->sig_lo = a->sig_lo + bb->sig_lo;
376*e4b17023SJohn Marino if (r->sig_lo & ((uhwi) 1 << SREAL_PART_BITS))
377*e4b17023SJohn Marino {
378*e4b17023SJohn Marino r->sig_hi++;
379*e4b17023SJohn Marino r->sig_lo -= (uhwi) 1 << SREAL_PART_BITS;
380*e4b17023SJohn Marino }
381*e4b17023SJohn Marino #else
382*e4b17023SJohn Marino r->sig = a->sig + bb->sig;
383*e4b17023SJohn Marino #endif
384*e4b17023SJohn Marino normalize (r);
385*e4b17023SJohn Marino return r;
386*e4b17023SJohn Marino }
387*e4b17023SJohn Marino
388*e4b17023SJohn Marino /* *R = *A - *B. Return R. */
389*e4b17023SJohn Marino
390*e4b17023SJohn Marino sreal *
sreal_sub(sreal * r,sreal * a,sreal * b)391*e4b17023SJohn Marino sreal_sub (sreal *r, sreal *a, sreal *b)
392*e4b17023SJohn Marino {
393*e4b17023SJohn Marino int dexp;
394*e4b17023SJohn Marino sreal tmp;
395*e4b17023SJohn Marino sreal *bb;
396*e4b17023SJohn Marino
397*e4b17023SJohn Marino gcc_assert (sreal_compare (a, b) >= 0);
398*e4b17023SJohn Marino
399*e4b17023SJohn Marino dexp = a->exp - b->exp;
400*e4b17023SJohn Marino r->exp = a->exp;
401*e4b17023SJohn Marino if (dexp > SREAL_BITS)
402*e4b17023SJohn Marino {
403*e4b17023SJohn Marino #if SREAL_PART_BITS < 32
404*e4b17023SJohn Marino r->sig_hi = a->sig_hi;
405*e4b17023SJohn Marino r->sig_lo = a->sig_lo;
406*e4b17023SJohn Marino #else
407*e4b17023SJohn Marino r->sig = a->sig;
408*e4b17023SJohn Marino #endif
409*e4b17023SJohn Marino return r;
410*e4b17023SJohn Marino }
411*e4b17023SJohn Marino if (dexp == 0)
412*e4b17023SJohn Marino bb = b;
413*e4b17023SJohn Marino else
414*e4b17023SJohn Marino {
415*e4b17023SJohn Marino copy (&tmp, b);
416*e4b17023SJohn Marino shift_right (&tmp, dexp);
417*e4b17023SJohn Marino bb = &tmp;
418*e4b17023SJohn Marino }
419*e4b17023SJohn Marino
420*e4b17023SJohn Marino #if SREAL_PART_BITS < 32
421*e4b17023SJohn Marino if (a->sig_lo < bb->sig_lo)
422*e4b17023SJohn Marino {
423*e4b17023SJohn Marino r->sig_hi = a->sig_hi - bb->sig_hi - 1;
424*e4b17023SJohn Marino r->sig_lo = a->sig_lo + ((uhwi) 1 << SREAL_PART_BITS) - bb->sig_lo;
425*e4b17023SJohn Marino }
426*e4b17023SJohn Marino else
427*e4b17023SJohn Marino {
428*e4b17023SJohn Marino r->sig_hi = a->sig_hi - bb->sig_hi;
429*e4b17023SJohn Marino r->sig_lo = a->sig_lo - bb->sig_lo;
430*e4b17023SJohn Marino }
431*e4b17023SJohn Marino #else
432*e4b17023SJohn Marino r->sig = a->sig - bb->sig;
433*e4b17023SJohn Marino #endif
434*e4b17023SJohn Marino normalize (r);
435*e4b17023SJohn Marino return r;
436*e4b17023SJohn Marino }
437*e4b17023SJohn Marino
438*e4b17023SJohn Marino /* *R = *A * *B. Return R. */
439*e4b17023SJohn Marino
440*e4b17023SJohn Marino sreal *
sreal_mul(sreal * r,sreal * a,sreal * b)441*e4b17023SJohn Marino sreal_mul (sreal *r, sreal *a, sreal *b)
442*e4b17023SJohn Marino {
443*e4b17023SJohn Marino #if SREAL_PART_BITS < 32
444*e4b17023SJohn Marino if (a->sig_hi < SREAL_MIN_SIG || b->sig_hi < SREAL_MIN_SIG)
445*e4b17023SJohn Marino {
446*e4b17023SJohn Marino r->sig_lo = 0;
447*e4b17023SJohn Marino r->sig_hi = 0;
448*e4b17023SJohn Marino r->exp = -SREAL_MAX_EXP;
449*e4b17023SJohn Marino }
450*e4b17023SJohn Marino else
451*e4b17023SJohn Marino {
452*e4b17023SJohn Marino unsigned HOST_WIDE_INT tmp1, tmp2, tmp3;
453*e4b17023SJohn Marino if (sreal_compare (a, b) < 0)
454*e4b17023SJohn Marino {
455*e4b17023SJohn Marino sreal *swap;
456*e4b17023SJohn Marino swap = a;
457*e4b17023SJohn Marino a = b;
458*e4b17023SJohn Marino b = swap;
459*e4b17023SJohn Marino }
460*e4b17023SJohn Marino
461*e4b17023SJohn Marino r->exp = a->exp + b->exp + SREAL_PART_BITS;
462*e4b17023SJohn Marino
463*e4b17023SJohn Marino tmp1 = a->sig_lo * b->sig_lo;
464*e4b17023SJohn Marino tmp2 = a->sig_lo * b->sig_hi;
465*e4b17023SJohn Marino tmp3 = a->sig_hi * b->sig_lo + (tmp1 >> SREAL_PART_BITS);
466*e4b17023SJohn Marino
467*e4b17023SJohn Marino r->sig_hi = a->sig_hi * b->sig_hi;
468*e4b17023SJohn Marino r->sig_hi += (tmp2 >> SREAL_PART_BITS) + (tmp3 >> SREAL_PART_BITS);
469*e4b17023SJohn Marino tmp2 &= ((uhwi) 1 << SREAL_PART_BITS) - 1;
470*e4b17023SJohn Marino tmp3 &= ((uhwi) 1 << SREAL_PART_BITS) - 1;
471*e4b17023SJohn Marino tmp1 = tmp2 + tmp3;
472*e4b17023SJohn Marino
473*e4b17023SJohn Marino r->sig_lo = tmp1 & (((uhwi) 1 << SREAL_PART_BITS) - 1);
474*e4b17023SJohn Marino r->sig_hi += tmp1 >> SREAL_PART_BITS;
475*e4b17023SJohn Marino
476*e4b17023SJohn Marino normalize (r);
477*e4b17023SJohn Marino }
478*e4b17023SJohn Marino #else
479*e4b17023SJohn Marino if (a->sig < SREAL_MIN_SIG || b->sig < SREAL_MIN_SIG)
480*e4b17023SJohn Marino {
481*e4b17023SJohn Marino r->sig = 0;
482*e4b17023SJohn Marino r->exp = -SREAL_MAX_EXP;
483*e4b17023SJohn Marino }
484*e4b17023SJohn Marino else
485*e4b17023SJohn Marino {
486*e4b17023SJohn Marino r->sig = a->sig * b->sig;
487*e4b17023SJohn Marino r->exp = a->exp + b->exp;
488*e4b17023SJohn Marino normalize (r);
489*e4b17023SJohn Marino }
490*e4b17023SJohn Marino #endif
491*e4b17023SJohn Marino return r;
492*e4b17023SJohn Marino }
493*e4b17023SJohn Marino
494*e4b17023SJohn Marino /* *R = *A / *B. Return R. */
495*e4b17023SJohn Marino
496*e4b17023SJohn Marino sreal *
sreal_div(sreal * r,sreal * a,sreal * b)497*e4b17023SJohn Marino sreal_div (sreal *r, sreal *a, sreal *b)
498*e4b17023SJohn Marino {
499*e4b17023SJohn Marino #if SREAL_PART_BITS < 32
500*e4b17023SJohn Marino unsigned HOST_WIDE_INT tmp, tmp1, tmp2;
501*e4b17023SJohn Marino
502*e4b17023SJohn Marino gcc_assert (b->sig_hi >= SREAL_MIN_SIG);
503*e4b17023SJohn Marino if (a->sig_hi < SREAL_MIN_SIG)
504*e4b17023SJohn Marino {
505*e4b17023SJohn Marino r->sig_hi = 0;
506*e4b17023SJohn Marino r->sig_lo = 0;
507*e4b17023SJohn Marino r->exp = -SREAL_MAX_EXP;
508*e4b17023SJohn Marino }
509*e4b17023SJohn Marino else
510*e4b17023SJohn Marino {
511*e4b17023SJohn Marino /* Since division by the whole number is pretty ugly to write
512*e4b17023SJohn Marino we are dividing by first 3/4 of bits of number. */
513*e4b17023SJohn Marino
514*e4b17023SJohn Marino tmp1 = (a->sig_hi << SREAL_PART_BITS) + a->sig_lo;
515*e4b17023SJohn Marino tmp2 = ((b->sig_hi << (SREAL_PART_BITS / 2))
516*e4b17023SJohn Marino + (b->sig_lo >> (SREAL_PART_BITS / 2)));
517*e4b17023SJohn Marino if (b->sig_lo & ((uhwi) 1 << ((SREAL_PART_BITS / 2) - 1)))
518*e4b17023SJohn Marino tmp2++;
519*e4b17023SJohn Marino
520*e4b17023SJohn Marino r->sig_lo = 0;
521*e4b17023SJohn Marino tmp = tmp1 / tmp2;
522*e4b17023SJohn Marino tmp1 = (tmp1 % tmp2) << (SREAL_PART_BITS / 2);
523*e4b17023SJohn Marino r->sig_hi = tmp << SREAL_PART_BITS;
524*e4b17023SJohn Marino
525*e4b17023SJohn Marino tmp = tmp1 / tmp2;
526*e4b17023SJohn Marino tmp1 = (tmp1 % tmp2) << (SREAL_PART_BITS / 2);
527*e4b17023SJohn Marino r->sig_hi += tmp << (SREAL_PART_BITS / 2);
528*e4b17023SJohn Marino
529*e4b17023SJohn Marino tmp = tmp1 / tmp2;
530*e4b17023SJohn Marino r->sig_hi += tmp;
531*e4b17023SJohn Marino
532*e4b17023SJohn Marino r->exp = a->exp - b->exp - SREAL_BITS - SREAL_PART_BITS / 2;
533*e4b17023SJohn Marino normalize (r);
534*e4b17023SJohn Marino }
535*e4b17023SJohn Marino #else
536*e4b17023SJohn Marino gcc_assert (b->sig != 0);
537*e4b17023SJohn Marino r->sig = (a->sig << SREAL_PART_BITS) / b->sig;
538*e4b17023SJohn Marino r->exp = a->exp - b->exp - SREAL_PART_BITS;
539*e4b17023SJohn Marino normalize (r);
540*e4b17023SJohn Marino #endif
541*e4b17023SJohn Marino return r;
542*e4b17023SJohn Marino }
543