]> www.ginac.de Git - cln.git/blob - src/float/lfloat/elem/cl_LF_from_I.cc
* All Files have been modified for inclusion of namespace cln;
[cln.git] / src / float / lfloat / elem / cl_LF_from_I.cc
1 // cl_I_to_LF().
2
3 // General includes.
4 #include "cl_sysdep.h"
5
6 // Specification.
7 #include "cl_LF.h"
8
9
10 // Implementation.
11
12 #include "cl_LF_impl.h"
13 #include "cln/integer.h"
14 #include "cl_I.h"
15 #include "cl_DS.h"
16 #include "cl_F.h"
17
18 namespace cln {
19
20 const cl_LF cl_I_to_LF (const cl_I& x, uintC len)
21 {
22 // Methode:
23 // x=0 -> Ergebnis 0.0
24 // Merke Vorzeichen von x.
25 // x:=(abs 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 uintL 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           && ((uintL)(intDsize*bitc(intCsize)-1) <= (uintL)(LF_exp_high-LF_exp_mid))
43          )
44         {} // garantiert exp <= intDsize*2^intCsize-1 <= LF_exp_high-LF_exp_mid
45         else
46         { if (!(exp <= (uintL)(LF_exp_high-LF_exp_mid))) { cl_error_floating_point_overflow(); } }
47       // Long-Float bauen:
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;
51       var uintC x_len;
52       I_to_NDS_nocopy(abs_x, x_MSDptr=,x_len=,,cl_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.
57        if (x_len > len)
58          { x_len -= 1+len;
59            if (shiftcount>0)
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)
66                          // round-to-even
67                          && ((mspref(y_mantMSDptr,len-1) & bit(0)) ==0)
68                   )    )
69                  goto ab; // aufrunden
70                  else
71                  goto auf; // aufrunden
72              }
73              else
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)
81                          // round-to-even
82                          && ((lspref(ptr,0) & bit(0)) ==0)
83                   )    )
84                  goto ab; // aufrunden
85                  else
86                  goto auf; // aufrunden
87              }
88            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                      && ((uintL)(intDsize*bitc(intCsize)-1) < (uintL)(LF_exp_high-LF_exp_mid))
95                     )
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
98                    else
99                    { if (++(TheLfloat(y)->expo) == LF_exp_high+1) { cl_error_floating_point_overflow(); } }
100                }
101            ab: // abrunden
102              ;
103          }
104          else // x_len <= len
105          { var uintD carry_rechts;
106            len -= x_len;
107            x_len -= 1;
108            if (shiftcount>0)
109              { carry_rechts = shiftrightcopy_loop_msp(x_MSDptr mspop 1,y_mantMSDptr,x_len,shiftcount,mspref(x_MSDptr,0)); }
110              else
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
115          }}
116       }
117       return y;
118 }
119
120 }  // namespace cln