4 #include "base/cl_sysdep.h"
7 #include "float/dfloat/cl_DF.h"
12 #include "rational/cl_RA.h"
13 #include "cln/integer.h"
14 #include "integer/cl_I.h"
15 #include "float/cl_F.h"
19 const cl_DF cl_RA_to_DF (const cl_RA& x)
23 // x = +/- a/b mit Integers a,b>0:
24 // Seien n,m so gewählt, daß
25 // 2^(n-1) <= a < 2^n, 2^(m-1) <= b < 2^m.
26 // Dann ist 2^(n-m-1) < a/b < 2^(n-m+1).
27 // Berechne n=(integer-length a) und m=(integer-length b) und
28 // floor(2^(-n+m+54)*a/b) :
29 // Bei n-m>=54 dividiere a durch (ash b (n-m-54)),
30 // bei n-m<54 dividiere (ash a (-n+m+54)) durch b.
31 // Der erste Wert ist >=2^53, <2^55.
32 // Falls er >=2^54 ist, runde 2 Bits weg,
33 // falls er <2^54 ist, runde 1 Bit weg.
40 var cl_I a = numerator(x); // +/- a
41 var const cl_I& b = denominator(x); // b
42 var cl_signean sign = -(cl_signean)minusp(a); // Vorzeichen
43 if (!(sign==0)) { a = -a; } // Betrag nehmen, liefert a
44 var sintC lendiff = (sintC)integer_length(a) // (integer-length a)
45 - (sintC)integer_length(b); // (integer-length b)
46 if (lendiff > DF_exp_high-DF_exp_mid) // Exponent >= n-m > Obergrenze ?
47 { throw floating_point_overflow_exception(); } // -> Overflow
48 if (lendiff < DF_exp_low-DF_exp_mid-2) // Exponent <= n-m+2 < Untergrenze ?
49 { if (underflow_allowed())
50 { throw floating_point_underflow_exception(); } // -> Underflow
56 if (lendiff >= DF_mant_len+2)
58 { nenner = ash(b,lendiff - (DF_mant_len+2)); // (ash b n-m-54)
62 { zaehler = ash(a,(DF_mant_len+2) - lendiff); // (ash a -n+m+54)
65 // Division zaehler/nenner durchführen:
66 var cl_I_div_t q_r = cl_divide(zaehler,nenner);
67 var cl_I& q = q_r.quotient;
68 var cl_I& r = q_r.remainder;
69 #if (cl_word_size==64)
70 #if (cl_value_len>=55)
71 // 2^53 <= q < 2^55: q is fixnum.
72 var uint64 mant = FN_to_UV(q);
74 // 2^53 <= q < 2^55: q is bignum with one Digit.
75 var const uintD* ptr = BN_MSDptr(q);
76 var uint64 mant = get_max64_Dptr(55,ptr);
78 if (mant >= bit(DF_mant_len+2))
79 // 2^54 <= q < 2^55, schiebe um 2 Bits nach rechts
80 { var uint64 rounding_bits = mant & (bit(2)-1);
81 lendiff = lendiff+1; // Exponent := n-m+1
83 if ( (rounding_bits < bit(1)) // 00,01 werden abgerundet
84 || ( (rounding_bits == bit(1)) // 10
85 && (eq(r,0)) // und genau halbzahlig (r=0)
86 && ((mant & bit(0)) ==0) // -> round-to-even
95 { var uint64 rounding_bit = mant & bit(0);
97 if ( (rounding_bit == 0) // 0 wird abgerundet
98 || ( (eq(r,0)) // genau halbzahlig (r=0)
99 && ((mant & bit(0)) ==0) // -> round-to-even
109 if (mant >= bit(DF_mant_len+1)) // rounding overflow?
110 { mant = mant>>1; lendiff = lendiff+1; }
113 return encode_DF(sign,lendiff,mant);
114 #else // (cl_word_size<64)
115 // 2^53 <= q < 2^55: q is bignum with two Digits.
116 var const uintD* ptr = BN_MSDptr(q);
117 var uint32 manthi = get_max32_Dptr(23,ptr);
118 var uint32 mantlo = get_32_Dptr(ptr mspop ceiling(23,intDsize));
119 if (manthi >= bit(DF_mant_len-32+2))
120 // 2^54 <= q < 2^55, schiebe um 2 Bits nach rechts
121 { var uintL rounding_bits = mantlo & (bit(2)-1);
122 lendiff = lendiff+1; // Exponent := n-m+1
123 mantlo = (mantlo >> 2) | (manthi << 30); manthi = manthi >> 2;
124 if ( (rounding_bits < bit(1)) // 00,01 werden abgerundet
125 || ( (rounding_bits == bit(1)) // 10
126 && (eq(r,0)) // und genau halbzahlig (r=0)
127 && ((mantlo & bit(0)) ==0) // -> round-to-even
136 { var uintL rounding_bit = mantlo & bit(0);
137 mantlo = (mantlo >> 1) | (manthi << 31); manthi = manthi >> 1;
138 if ( (rounding_bit == 0) // 0 wird abgerundet
139 || ( (eq(r,0)) // genau halbzahlig (r=0)
140 && ((mantlo & bit(0)) ==0) // -> round-to-even
152 if (manthi >= bit(DF_mant_len-32+1)) // rounding overflow?
153 { manthi = manthi>>1; lendiff = lendiff+1; }
157 return encode_DF(sign,lendiff,manthi,mantlo);