4 #include "base/cl_sysdep.h"
7 #include "float/lfloat/cl_LF.h"
12 #include "float/lfloat/cl_LF_impl.h"
13 #include "cln/integer.h"
14 #include "integer/cl_I.h"
15 #include "base/digitseq/cl_DS.h"
16 #include "float/cl_F.h"
20 const cl_LF cl_I_to_LF (const cl_I& x, uintC len)
23 // x=0 -> Ergebnis 0.0
24 // Merke Vorzeichen von x.
26 // Exponent:=(integer-length x)
27 // Mantisse enthalte die höchstwertigen 16n Bits des Integers x (wobei die
28 // führenden 16-(e mod 16) Nullbits zu streichen sind).
29 // Runde die weiteren Bits weg:
30 // Kommen keine mehr -> abrunden,
31 // nächstes Bit = 0 -> abrunden,
32 // nächstes Bit = 1 und Rest =0 -> round-to-even,
33 // nächstes Bit = 1 und Rest >0 -> aufrunden.
34 // Bei Aufrundung: rounding overflow -> Mantisse um 1 Bit nach rechts schieben
35 // und Exponent incrementieren.
36 if (eq(x,0)) { return encode_LF0(len); } // x=0 -> Ergebnis 0.0
37 var cl_signean sign = -(cl_signean)minusp(x); // Vorzeichen von x
38 var cl_I abs_x = (sign==0 ? x : -x);
39 var uintC exp = integer_length(abs_x); // (integer-length x) < intDsize*2^intCsize
40 // Teste, ob exp <= LF_exp_high-LF_exp_mid :
41 if ( (log2_intDsize+intCsize < 32)
42 && ((uintE)(intDsize*bitc(intCsize)-1) <= (uintE)(LF_exp_high-LF_exp_mid))
44 {} // garantiert exp <= intDsize*2^intCsize-1 <= LF_exp_high-LF_exp_mid
46 { if (!(exp <= (uintE)(LF_exp_high-LF_exp_mid))) { throw floating_point_overflow_exception(); } }
48 var Lfloat y = allocate_lfloat(len,exp+LF_exp_mid,sign);
49 var uintD* y_mantMSDptr = arrayMSDptr(TheLfloat(y)->data,len);
50 var const uintD* x_MSDptr;
52 I_to_NDS_nocopy(abs_x, x_MSDptr=,x_len=,,false,); // NDS zu x bilden, x_len>0
53 // x_MSDptr/x_len/.. um (exp mod 16) Bits nach rechts shiften und in
54 // y einfüllen (genauer: nur maximal len Digits davon):
55 {var uintL shiftcount = exp % intDsize;
56 // Die NDS fängt mit intDsize-shiftcount Nullbits an, dann kommt eine 1.
60 { var uintD carry_rechts =
61 shiftrightcopy_loop_msp(x_MSDptr mspop 1,y_mantMSDptr,len,shiftcount,mspref(x_MSDptr,0));
62 // Mantisse ist gefüllt. Runden:
63 if ( ((sintD)carry_rechts >= 0) // nächstes Bit =0 -> abrunden
64 || ( ((carry_rechts & ((uintD)bit(intDsize-1)-1)) ==0) // =1, Rest >0 -> aufrunden
65 && !test_loop_msp(x_MSDptr mspop 1 mspop len,x_len)
67 && ((mspref(y_mantMSDptr,len-1) & bit(0)) ==0)
71 goto auf; // aufrunden
74 { copy_loop_msp(x_MSDptr mspop 1,y_mantMSDptr,len);
75 // Mantisse ist gefüllt. Runden:
76 var const uintD* ptr = x_MSDptr mspop 1 mspop len;
77 if ( (x_len==0) // keine Bits mehr -> abrunden
78 || ((sintD)mspref(ptr,0) >= 0) // nächstes Bit =0 -> abrunden
79 || ( ((mspref(ptr,0) & ((uintD)bit(intDsize-1)-1)) ==0) // =1, Rest >0 -> aufrunden
80 && !test_loop_msp(ptr mspop 1,x_len-1)
82 && ((lspref(ptr,0) & bit(0)) ==0)
86 goto auf; // aufrunden
89 if ( inc_loop_lsp(y_mantMSDptr mspop len,len) )
90 // Übertrag durchs Aufrunden
91 { mspref(y_mantMSDptr,0) = bit(intDsize-1); // Mantisse := 10...0
92 // Exponenten incrementieren:
93 if ( (log2_intDsize+intCsize < 32)
94 && ((uintE)(intDsize*bitc(intCsize)-1) < (uintE)(LF_exp_high-LF_exp_mid))
96 // garantiert exp < intDsize*2^intCsize-1 <= LF_exp_high-LF_exp_mid
97 { (TheLfloat(y)->expo)++; } // jetzt exp <= LF_exp_high-LF_exp_mid
99 { if (++(TheLfloat(y)->expo) == LF_exp_high+1) { throw floating_point_overflow_exception(); } }
105 { var uintD carry_rechts;
109 { carry_rechts = shiftrightcopy_loop_msp(x_MSDptr mspop 1,y_mantMSDptr,x_len,shiftcount,mspref(x_MSDptr,0)); }
111 { copy_loop_msp(x_MSDptr mspop 1,y_mantMSDptr,x_len); carry_rechts = 0; }
112 {var uintD* y_ptr = y_mantMSDptr mspop x_len;
113 msprefnext(y_ptr) = carry_rechts; // Carry als nächstes Digit
114 clear_loop_msp(y_ptr,len); // dann len-x_len Nulldigits