xref: /dflybsd-src/contrib/gcc-4.7/gcc/sreal.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
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