12 #include "cl_LF_impl.h"
13 #include "cl_integer.h"
18 const cl_LF cl_I_to_LF (const cl_I& x, uintC len)
21 // x=0 -> Ergebnis 0.0
22 // Merke Vorzeichen von x.
24 // Exponent:=(integer-length x)
25 // Mantisse enthalte die höchstwertigen 16n Bits des Integers x (wobei die
26 // führenden 16-(e mod 16) Nullbits zu streichen sind).
27 // Runde die weiteren Bits weg:
28 // Kommen keine mehr -> abrunden,
29 // nächstes Bit = 0 -> abrunden,
30 // nächstes Bit = 1 und Rest =0 -> round-to-even,
31 // nächstes Bit = 1 und Rest >0 -> aufrunden.
32 // Bei Aufrundung: rounding overflow -> Mantisse um 1 Bit nach rechts schieben
33 // und Exponent incrementieren.
34 if (eq(x,0)) { return encode_LF0(len); } // x=0 -> Ergebnis 0.0
35 var cl_signean sign = -(cl_signean)minusp(x); // Vorzeichen von x
36 var cl_I abs_x = (sign==0 ? x : -x);
37 var uintL exp = integer_length(abs_x); // (integer-length x) < intDsize*2^intCsize
38 // Teste, ob exp <= LF_exp_high-LF_exp_mid :
39 if ( (log2_intDsize+intCsize < 32)
40 && ((uintL)(intDsize*bitc(intCsize)-1) <= (uintL)(LF_exp_high-LF_exp_mid))
42 {} // garantiert exp <= intDsize*2^intCsize-1 <= LF_exp_high-LF_exp_mid
44 { if (!(exp <= (uintL)(LF_exp_high-LF_exp_mid))) { cl_error_floating_point_overflow(); } }
46 var Lfloat y = allocate_lfloat(len,exp+LF_exp_mid,sign);
47 var uintD* y_mantMSDptr = arrayMSDptr(TheLfloat(y)->data,len);
48 var const uintD* x_MSDptr;
50 I_to_NDS_nocopy(abs_x, x_MSDptr=,x_len=,,cl_false,); // NDS zu x bilden, x_len>0
51 // x_MSDptr/x_len/.. um (exp mod 16) Bits nach rechts shiften und in
52 // y einfüllen (genauer: nur maximal len Digits davon):
53 {var uintL shiftcount = exp % intDsize;
54 // Die NDS fängt mit intDsize-shiftcount Nullbits an, dann kommt eine 1.
58 { var uintD carry_rechts =
59 shiftrightcopy_loop_msp(x_MSDptr mspop 1,y_mantMSDptr,len,shiftcount,mspref(x_MSDptr,0));
60 // Mantisse ist gefüllt. Runden:
61 if ( ((sintD)carry_rechts >= 0) // nächstes Bit =0 -> abrunden
62 || ( ((carry_rechts & ((uintD)bit(intDsize-1)-1)) ==0) // =1, Rest >0 -> aufrunden
63 && !test_loop_msp(x_MSDptr mspop 1 mspop len,x_len)
65 && ((mspref(y_mantMSDptr,len-1) & bit(0)) ==0)
69 goto auf; // aufrunden
72 { copy_loop_msp(x_MSDptr mspop 1,y_mantMSDptr,len);
73 // Mantisse ist gefüllt. Runden:
74 var const uintD* ptr = x_MSDptr mspop 1 mspop len;
75 if ( (x_len==0) // keine Bits mehr -> abrunden
76 || ((sintD)mspref(ptr,0) >= 0) // nächstes Bit =0 -> abrunden
77 || ( ((mspref(ptr,0) & ((uintD)bit(intDsize-1)-1)) ==0) // =1, Rest >0 -> aufrunden
78 && !test_loop_msp(ptr mspop 1,x_len-1)
80 && ((lspref(ptr,0) & bit(0)) ==0)
84 goto auf; // aufrunden
87 if ( inc_loop_lsp(y_mantMSDptr mspop len,len) )
88 // Übertrag durchs Aufrunden
89 { mspref(y_mantMSDptr,0) = bit(intDsize-1); // Mantisse := 10...0
90 // Exponenten incrementieren:
91 if ( (log2_intDsize+intCsize < 32)
92 && ((uintL)(intDsize*bitc(intCsize)-1) < (uintL)(LF_exp_high-LF_exp_mid))
94 // garantiert exp < intDsize*2^intCsize-1 <= LF_exp_high-LF_exp_mid
95 { (TheLfloat(y)->expo)++; } // jetzt exp <= LF_exp_high-LF_exp_mid
97 { if (++(TheLfloat(y)->expo) == LF_exp_high+1) { cl_error_floating_point_overflow(); } }
103 { var uintD carry_rechts;
107 { carry_rechts = shiftrightcopy_loop_msp(x_MSDptr mspop 1,y_mantMSDptr,x_len,shiftcount,mspref(x_MSDptr,0)); }
109 { copy_loop_msp(x_MSDptr mspop 1,y_mantMSDptr,x_len); carry_rechts = 0; }
110 {var uintD* y_ptr = y_mantMSDptr mspop x_len;
111 msprefnext(y_ptr) = carry_rechts; // Carry als nächstes Digit
112 clear_loop_msp(y_ptr,len); // dann len-x_len Nulldigits