]> www.ginac.de Git - cln.git/blob - src/float/dfloat/elem/cl_DF_fround.cc
* All Files have been modified for inclusion of namespace cln;
[cln.git] / src / float / dfloat / elem / cl_DF_fround.cc
1 // fround().
2
3 // General includes.
4 #include "cl_sysdep.h"
5
6 // Specification.
7 #include "cln/dfloat.h"
8
9
10 // Implementation.
11
12 #include "cl_DF.h"
13
14 namespace cln {
15
16 const cl_DF fround (const cl_DF& x)
17 {
18 // Methode:
19 // x = 0.0 oder e<0 -> Ergebnis 0.0
20 // 0<=e<=52 -> letzte (53-e) Bits der Mantisse wegrunden,
21 //             Exponent und Vorzeichen beibehalten.
22 // e>52 -> Ergebnis x
23 #if (cl_word_size==64)
24       var dfloat x_ = TheDfloat(x)->dfloat_value;
25       var uintL uexp = DF_uexp(x_); // e + DF_exp_mid
26       if (uexp < DF_exp_mid) // x = 0.0 oder e<0 ?
27         { return cl_DF_0; }
28         else
29         { if (uexp > DF_exp_mid+DF_mant_len) // e > 52 ?
30             { return x; }
31             else
32             if (uexp > DF_exp_mid+1) // e>1 ?
33               { var uint64 bitmask = // Bitmaske: Bit 52-e gesetzt, alle anderen gelöscht
34                   bit(DF_mant_len+DF_exp_mid-uexp);
35                 var uint64 mask = // Bitmaske: Bits 51-e..0 gesetzt, alle anderen gelöscht
36                   bitmask-1;
37                 if ( ((x_ & bitmask) ==0) // Bit 52-e =0 -> abrunden
38                      || ( ((x_ & mask) ==0) // Bit 52-e =1 und Bits 51-e..0 >0 -> aufrunden
39                           // round-to-even, je nach Bit 53-e :
40                           && ((x_ & (bitmask<<1)) ==0)
41                    )    )
42                   // abrunden
43                   { mask |= bitmask; // Bitmaske: Bits 52-e..0 gesetzt, alle anderen gelöscht
44                     return allocate_dfloat( x_ & ~mask );
45                   }
46                   else
47                   // aufrunden
48                   { return allocate_dfloat
49                       ((x_ | mask) // alle diese Bits 51-e..0 setzen (Bit 52-e schon gesetzt)
50                        + 1 // letzte Stelle erhöhen, dabei evtl. Exponenten incrementieren
51                       );
52                   }
53               }
54             elif (uexp == DF_exp_mid+1) // e=1 ?
55               // Wie bei 1 < e <= 52, nur daß Bit 53-e stets gesetzt ist.
56               { if ((x_ & bit(DF_mant_len-1)) ==0) // Bit 52-e =0 -> abrunden
57                   // abrunden
58                   { return allocate_dfloat( x_ & ~(bit(DF_mant_len)-1) ); }
59                   else
60                   // aufrunden
61                   { return allocate_dfloat
62                       ((x_ | (bit(DF_mant_len)-1)) // alle diese Bits 52-e..0 setzen
63                        + 1 // letzte Stelle erhöhen, dabei evtl. Exponenten incrementieren
64                       );
65                   }
66               }
67             else // e=0 ?
68               // Wie bei 1 < e <= 52, nur daß Bit 52-e stets gesetzt
69               // und Bit 53-e stets gelöscht ist.
70               { if ((x_ & (bit(DF_mant_len)-1)) ==0)
71                   // abrunden von +-0.5 zu 0.0
72                   { return cl_DF_0; }
73                   else
74                   // aufrunden
75                   { return allocate_dfloat
76                       ((x_ | (bit(DF_mant_len)-1)) // alle Bits 51-e..0 setzen
77                        + 1 // letzte Stelle erhöhen, dabei Exponenten incrementieren
78                       );
79               }   }
80         }
81 #else
82       var uint32 semhi = TheDfloat(x)->dfloat_value.semhi;
83       var uint32 mlo = TheDfloat(x)->dfloat_value.mlo;
84       var uintL uexp = DF_uexp(semhi); // e + DF_exp_mid
85       if (uexp < DF_exp_mid) // x = 0.0 oder e<0 ?
86         { return cl_DF_0; }
87         else
88         { if (uexp > DF_exp_mid+DF_mant_len) // e > 52 ?
89             { return x; }
90             else
91             if (uexp > DF_exp_mid+1) // e>1 ?
92               { if (uexp > DF_exp_mid+DF_mant_len-32) // e > 20 ?
93                   { var uint32 bitmask = // Bitmaske: Bit 52-e gesetzt, alle anderen gelöscht
94                       bit(DF_mant_len+DF_exp_mid-uexp);
95                     var uint32 mask = // Bitmaske: Bits 51-e..0 gesetzt, alle anderen gelöscht
96                       bitmask-1;
97                     if ( ((mlo & bitmask) ==0) // Bit 52-e =0 -> abrunden
98                          || ( ((mlo & mask) ==0) // Bit 52-e =1 und Bits 51-e..0 >0 -> aufrunden
99                               // round-to-even, je nach Bit 53-e :
100                               && ( ((bitmask<<1) == 0) // e=21 ?
101                                     ? ((semhi & bit(0)) ==0)
102                                     : ((mlo & (bitmask<<1)) ==0)
103                        )    )    )
104                       // abrunden
105                       { mask |= bitmask; // Bitmaske: Bits 52-e..0 gesetzt, alle anderen gelöscht
106                         return allocate_dfloat(semhi, mlo & ~mask );
107                       }
108                       else
109                       // aufrunden
110                       { mlo = (mlo | mask) // alle diese Bits 51-e..0 setzen (Bit 52-e schon gesetzt)
111                               + 1; // letzte Stelle erhöhen,
112                         if (mlo==0) { semhi += 1; } // dabei evtl. Exponenten incrementieren
113                         return allocate_dfloat(semhi,mlo);
114                       }
115                   }
116                   else
117                   { var uint32 bitmask = // Bitmaske: Bit 20-e gesetzt, alle anderen gelöscht
118                       bit(DF_mant_len+DF_exp_mid-32-uexp);
119                     var uint32 mask = // Bitmaske: Bits 19-e..0 gesetzt, alle anderen gelöscht
120                       bitmask-1;
121                     if ( ((semhi & bitmask) ==0) // Bit 52-e =0 -> abrunden
122                          || ( (mlo==0) && ((semhi & mask) ==0) // Bit 52-e =1 und Bits 51-e..0 >0 -> aufrunden
123                               // round-to-even, je nach Bit 53-e :
124                               && ((semhi & (bitmask<<1)) ==0)
125                        )    )
126                       // abrunden
127                       { mask |= bitmask; // Bitmaske: Bits 20-e..0 gesetzt, alle anderen gelöscht
128                         return allocate_dfloat( semhi & ~mask, 0 );
129                       }
130                       else
131                       // aufrunden
132                       { return allocate_dfloat
133                           ((semhi | mask) // alle diese Bits 19-e..0 setzen (Bit 20-e schon gesetzt)
134                            + 1, // letzte Stelle erhöhen, dabei evtl. Exponenten incrementieren
135                            0
136                           );
137                       }
138                   }
139               }
140             elif (uexp == DF_exp_mid+1) // e=1 ?
141               // Wie bei 1 < e <= 20, nur daß Bit 53-e stets gesetzt ist.
142               { if ((semhi & bit(DF_mant_len-32-1)) ==0) // Bit 52-e =0 -> abrunden
143                   // abrunden
144                   { return allocate_dfloat( semhi & ~(bit(DF_mant_len-32)-1) , 0 ); }
145                   else
146                   // aufrunden
147                   { return allocate_dfloat
148                       ((semhi | (bit(DF_mant_len-32)-1)) // alle diese Bits 52-e..0 setzen
149                        + 1, // letzte Stelle erhöhen, dabei evtl. Exponenten incrementieren
150                        0
151                       );
152                   }
153               }
154             else // e=0 ?
155               // Wie bei 1 < e <= 20, nur daß Bit 52-e stets gesetzt
156               // und Bit 53-e stets gelöscht ist.
157               { if ((mlo==0) && ((semhi & (bit(DF_mant_len-32)-1)) ==0))
158                   // abrunden von +-0.5 zu 0.0
159                   { return cl_DF_0; }
160                   else
161                   // aufrunden
162                   { return allocate_dfloat
163                       ((semhi | (bit(DF_mant_len-32)-1)) // alle Bits 51-e..0 setzen
164                        + 1, // letzte Stelle erhöhen, dabei Exponenten incrementieren
165                        0
166                       );
167               }   }
168         }
169 #endif
170 }
171
172 }  // namespace cln