]> www.ginac.de Git - cln.git/blob - src/float/lfloat/elem/cl_LF_fround.cc
bump library version, since CLN doesn't export global object ctors any more.
[cln.git] / src / float / lfloat / elem / cl_LF_fround.cc
1 // fround().
2
3 // General includes.
4 #include "cl_sysdep.h"
5
6 // Specification.
7 #include "cln/lfloat.h"
8
9
10 // Implementation.
11
12 #include "cl_LF.h"
13 #include "cl_LF_impl.h"
14 #include "cl_DS.h"
15
16 namespace cln {
17
18 const cl_LF fround (const cl_LF& x)
19 {
20 // Methode:
21 // x = 0.0 oder e<0 -> Ergebnis 0.0
22 // 0<=e<16n -> letzte (16n-e) Bits der Mantisse wegrunden,
23 //             Exponent und Vorzeichen beibehalten.
24 // e>=16n -> Ergebnis x
25 #if 0
26       var cl_signean sign;
27       var sintE exp;
28       var const uintD* mantMSDptr;
29       var uintC mantlen;
30       LF_decode(x, { return x; }, sign=,exp=,mantMSDptr=,mantlen=,);
31       if (exp<0) { return encode_LF0(mantlen); } // e<0 -> Ergebnis 0.0
32       if ((uintE)exp >= intDsize*mantlen) // e>=16n -> x als Ergebnis
33         { return x; }
34         else
35         // 0 <= e < 16n
36         { // alle hinteren 16n-e Bits wegrunden:
37           var uintC count = floor((uintE)exp,intDsize); // zu kopierende Digits, < mantlen
38           var uintC bitcount = ((uintE)exp) % intDsize; // zu kopierende Bits danach, >=0, <intDsize
39           var uintD mask = minus_bit(intDsize-bitcount-1); // Maske mit bitcount+1 Bits
40           var const uintD* mantptr = mantMSDptr mspop count;
41           if ((mspref(mantptr,0) & -mask) ==0) goto ab; // Bit 16n-e-1 =0 -> abrunden
42           if (!((mspref(mantptr,0) & ~mask) ==0)) goto auf; // Bit 16n-e-1 =1 und Bits 16n-e-2..0 >0 -> aufrunden
43           if (test_loop_msp(mantptr mspop 1,mantlen-count-1)) goto auf;
44           // round-to-even, je nach Bit 16n-e :
45           if (bitcount>0)
46             { if ((mspref(mantptr,0) & (-2*mask)) ==0) goto ab; else goto auf; }
47             elif (count>0)
48               { if ((lspref(mantptr,0) & bit(0)) ==0) goto ab; else goto auf; }
49               else
50               // bitcount=0, count=0, also exp=0: Abrunden von +-0.5 zu 0.0
51               { return encode_LF0(mantlen); }
52           ab: // abrunden
53           { CL_ALLOCA_STACK;
54             var uintD* MSDptr;
55             num_stack_alloc(mantlen, MSDptr=,);
56            {var uintD* ptr =
57               copy_loop_msp(mantMSDptr,MSDptr,count); // count ganze Digits kopieren
58             msprefnext(ptr) = mspref(mantptr,0) & mask; // dann bitcount Bits kopieren
59             clear_loop_msp(ptr,mantlen-count-1); // Rest mit Nullen füllen
60             return encode_LF(sign,exp,MSDptr,mantlen);
61           }}
62           auf: // aufrunden
63           { CL_ALLOCA_STACK;
64             var uintD* MSDptr;
65             num_stack_alloc(mantlen, MSDptr=,);
66            {var uintD* ptr =
67               copy_loop_msp(mantMSDptr,MSDptr,count); // count ganze Digits kopieren
68             if ((mspref(ptr,0) = ((mspref(mantptr,0) & mask) - mask)) == 0) // dann bitcount Bits kopieren und incrementieren
69               { if (!( inc_loop_lsp(ptr,count) ==0)) // evtl. weiterincrementieren
70                   { mspref(MSDptr,0) = bit(intDsize-1); exp = exp+1; } // evtl. Exponenten erhöhen
71               }
72             clear_loop_msp(ptr mspop 1,mantlen-count-1); // Rest mit Nullen füllen
73             return encode_LF(sign,exp,MSDptr,mantlen);
74           }}
75         }
76 #else
77       var uintC len = TheLfloat(x)->len;
78       var uintE uexp = TheLfloat(x)->expo;
79       if (uexp < LF_exp_mid)
80         { if (uexp == 0) { return x; } // x=0.0 -> Ergebnis 0.0
81           return encode_LF0(len); // e<0 -> Ergebnis 0.0
82         }
83       var uintE exp = uexp - LF_exp_mid;
84       if (exp >= intDsize*len) // e>=16n -> x als Ergebnis
85         { return x; }
86       // 0 <= e < 16n
87       // alle hinteren 16n-e Bits wegrunden:
88       var uintC count = floor(exp,intDsize); // zu kopierende Digits, < mantlen
89       var uintC bitcount = exp % intDsize; // zu kopierende Bits danach, >=0, <intDsize
90       var uintD mask = minus_bit(intDsize-bitcount-1); // Maske mit bitcount+1 Bits
91       {var const uintD* mantptr = LF_MSDptr(x) mspop count;
92        #if !(defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ == 7))
93        if ((mspref(mantptr,0) & -mask) ==0) goto ab; // Bit 16n-e-1 =0 -> abrunden
94        #else
95        // Work around gcc-2.7.x bug on i386/ELF
96        if ((mspref(mantptr,0) & ((~mask)+1)) ==0) goto ab; // Bit 16n-e-1 =0 -> abrunden
97        #endif
98        if (!((mspref(mantptr,0) & ~mask) ==0)) goto auf; // Bit 16n-e-1 =1 und Bits 16n-e-2..0 >0 -> aufrunden
99        if (test_loop_msp(mantptr mspop 1,len-count-1)) goto auf;
100        // round-to-even, je nach Bit 16n-e :
101        if (bitcount>0)
102          { if ((mspref(mantptr,0) & (-2*mask)) ==0) goto ab; else goto auf; }
103          elif (count>0)
104            { if ((lspref(mantptr,0) & bit(0)) ==0) goto ab; else goto auf; }
105            else
106            // bitcount=0, count=0, also exp=0: Abrunden von +-0.5 zu 0.0
107            { return encode_LF0(len); }
108       }
109       ab: // abrunden
110         {var Lfloat y = allocate_lfloat(len,uexp,TheLfloat(x)->sign); // neues Long-Float
111          // y_mant := NUDS mit e Bits aus x_mant und 16n-e Nullbits:
112          {var const uintD* x_mantMSDptr = LF_MSDptr(x);
113           var uintD* ptr =
114             copy_loop_msp(x_mantMSDptr,arrayMSDptr(TheLfloat(y)->data,len),count); // count ganze Digits kopieren
115           msprefnext(ptr) = mspref(x_mantMSDptr,count) & mask; // dann bitcount Bits kopieren
116           clear_loop_msp(ptr,len-count-1); // Rest mit Nullen füllen
117          }
118          return y;
119         }
120       auf: // aufrunden
121         {var Lfloat y = allocate_lfloat(len,uexp,TheLfloat(x)->sign); // neues Long-Float
122          // y_mant := NUDS mit e Bits aus x_mant mit Increment und 16n-e Nullbits:
123          {var const uintD* x_mantMSDptr = LF_MSDptr(x);
124           var uintD* y_mantMSDptr = arrayMSDptr(TheLfloat(y)->data,len);
125           var uintD* ptr =
126             copy_loop_msp(x_mantMSDptr,y_mantMSDptr,count); // count ganze Digits kopieren
127           if ((mspref(ptr,0) = ((mspref(x_mantMSDptr,count) & mask) - mask)) == 0) // dann bitcount Bits kopieren und incrementieren
128             { if (!( inc_loop_lsp(ptr,count) ==0)) // evtl. weiterincrementieren
129                 { mspref(y_mantMSDptr,0) = bit(intDsize-1); (TheLfloat(y)->expo)++; } // evtl. Exponenten erhöhen
130             }
131           clear_loop_msp(ptr mspop 1,len-count-1); // Rest mit Nullen füllen
132          }
133          return y;
134         }
135 #endif
136 }
137
138 }  // namespace cln