7 #include "cl_rational.h"
14 #include "cl_integer.h"
18 float cl_float_approx (const cl_RA& x)
20 // Method: same as cl_RA_to_FF().
23 return cl_float_approx(x);
27 union { ffloat eksplicit; float machine_float; } u;
28 var cl_I a = numerator(x); // +/- a
29 var const cl_I& b = denominator(x); // b
30 var cl_signean sign = -(cl_signean)minusp(a); // Vorzeichen
31 if (!(sign==0)) { a = -a; } // Betrag nehmen, liefert a
32 var sintL lendiff = (sintL)integer_length(a) // (integer-length a)
33 - (sintL)integer_length(b); // (integer-length b)
34 if (lendiff > FF_exp_high-FF_exp_mid) // Exponent >= n-m > Obergrenze ?
35 { u.eksplicit = make_FF_word(sign,bit(FF_exp_len)-1,0); // Infinity
36 return u.machine_float;
38 if (lendiff < FF_exp_low-FF_exp_mid-2) // Exponent <= n-m+2 < Untergrenze ?
39 { u.eksplicit = make_FF_word(sign,0,0); // 0.0
40 return u.machine_float;
44 if (lendiff >= FF_mant_len+2)
46 { nenner = ash(b,lendiff - (FF_mant_len+2)); // (ash b n-m-25)
50 { zaehler = ash(a,(FF_mant_len+2) - lendiff); // (ash a -n+m+25)
53 // Division zaehler/nenner durchführen:
54 var cl_I_div_t q_r = cl_divide(zaehler,nenner);
55 var cl_I& q = q_r.quotient;
56 var cl_I& r = q_r.remainder;
57 // 2^24 <= q < 2^26, also ist q Fixnum oder Bignum mit bn_minlength Digits.
58 var uint32 mant = ((FF_mant_len+3 < cl_value_len)
62 if (mant >= bit(FF_mant_len+2))
63 // 2^25 <= q < 2^26, schiebe um 2 Bits nach rechts
64 { var uintL rounding_bits = mant & (bit(2)-1);
65 lendiff = lendiff+1; // Exponent := n-m+1
67 if ( (rounding_bits < bit(1)) // 00,01 werden abgerundet
68 || ( (rounding_bits == bit(1)) // 10
69 && (eq(r,0)) // und genau halbzahlig (r=0)
70 && ((mant & bit(0)) ==0) // -> round-to-even
79 { var uintL rounding_bit = mant & bit(0);
81 if ( (rounding_bit == 0) // 0 wird abgerundet
82 || ( (eq(r,0)) // genau halbzahlig (r=0)
83 && ((mant & bit(0)) ==0) // -> round-to-even
93 if (mant >= bit(FF_mant_len+1)) // rounding overflow?
94 { mant = mant>>1; lendiff = lendiff+1; }
97 if (lendiff < (sintL)(FF_exp_low-FF_exp_mid))
98 { u.eksplicit = make_FF_word(sign,0,0); }
99 else if (lendiff > (sintL)(FF_exp_high-FF_exp_mid))
100 { u.eksplicit = make_FF_word(sign,bit(FF_exp_len)-1,0); } // Infinity
102 { u.eksplicit = make_FF_word(sign,lendiff+FF_exp_mid,mant); }
103 return u.machine_float;