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