]> www.ginac.de Git - cln.git/blob - src/float/sfloat/elem/cl_SF_from_I.cc
* */*: Remove cl_boolean, cl_true, and cl_false in favor of built-in
[cln.git] / src / float / sfloat / elem / cl_SF_from_I.cc
1 // cl_I_to_SF().
2
3 // General includes.
4 #include "cl_sysdep.h"
5
6 // Specification.
7 #include "cl_SF.h"
8
9
10 // Implementation.
11
12 #include "cln/integer.h"
13 #include "cl_I.h"
14 #include "cl_DS.h"
15
16 namespace cln {
17
18 const cl_SF cl_I_to_SF (const cl_I& x)
19 {
20 // Methode:
21 // x=0 -> Ergebnis 0.0
22 // Merke Vorzeichen von x.
23 // x:=(abs x)
24 // Exponent:=(integer-length x)
25 //   Greife die 18 höchstwertigen Bits heraus (angeführt von einer 1).
26 //   Runde das letzte Bit weg:
27 //     Bit 0 = 0 -> abrunden,
28 //     Bit 0 = 1 und Rest =0 -> round-to-even,
29 //     Bit 0 = 1 und Rest >0 -> aufrunden.
30 //   Dabei um ein Bit nach rechts schieben.
31 //   Bei Aufrundung auf 2^17 (rounding overflow) Mantisse um 1 Bit nach rechts
32 //     schieben und Exponent incrementieren.
33       if (eq(x,0)) { return SF_0; }
34       var cl_signean sign = -(cl_signean)minusp(x); // Vorzeichen
35       var cl_I abs_x = (sign==0 ? x : -x);
36       var uintC exp = integer_length(abs_x); // (integer-length x)
37       // NDS zu |x|>0 bilden:
38       var const uintD* MSDptr;
39       var uintC len;
40       I_to_NDS_nocopy(abs_x, MSDptr=,len=,,false,);
41       // MSDptr/len/LSDptr ist die NDS zu x, len>0.
42       // Führende Digits holen: Brauche SF_mant_len+1 Bits, dazu intDsize
43       // Bits (die NDS kann mit bis zu intDsize Nullbits anfangen).
44       // Dann werden diese Bits um (exp mod intDsize) nach rechts geschoben.
45       var uintD msd = msprefnext(MSDptr); // erstes Digit
46       #if (intDsize==64)
47       var uintD msdd = 0; // weiteres Digit
48       if (--len == 0) goto ok;
49       msdd = msprefnext(MSDptr);
50       #else // (intDsize<=32)
51       var uint32 msdd = 0; // weitere min(len-1,32/intDsize) Digits
52       #define NEXT_DIGIT(i)  \
53         { if (--len == 0) goto ok;                                   \
54           msdd |= (uint32)msprefnext(MSDptr) << (32-(i+1)*intDsize); \
55         }
56       DOCONSTTIMES(32/intDsize,NEXT_DIGIT);
57       #undef NEXT_DIGIT
58       #endif
59       --len; ok:
60       #if (intDsize==64)
61       // Die NDS besteht aus msd, msdd, und len weiteren Digits.
62       // Das höchste in 2^intDsize*msd+msdd gesetzte Bit ist Bit Nummer
63       // intDsize-1 + (exp mod intDsize).
64       var uintL shiftcount = exp % intDsize;
65       var uint64 mant = // führende 64 Bits
66         (shiftcount==0
67          ? msdd
68          : ((msd << (64-shiftcount)) | (msdd >> shiftcount))
69         );
70       // Das höchste in mant gesetzte Bit ist Bit Nummer 63.
71       if ( ((mant & bit(62-SF_mant_len)) ==0) // Bit 46 =0 -> abrunden
72            || ( ((mant & (bit(62-SF_mant_len)-1)) ==0) // Bit 46 =1 und Bits 45..0 =0
73                 && ((msdd & (bit(shiftcount)-1)) ==0) // und weitere Bits aus msdd =0
74                 && (!test_loop_msp(MSDptr,len)) // und alle weiteren Digits =0
75                 // round-to-even, je nach Bit 47 :
76                 && ((mant & bit(63-SF_mant_len)) ==0)
77          )    )
78         // abrunden
79         { mant = mant >> (63-SF_mant_len); }
80         else
81         // aufrunden
82         { mant = mant >> (63-SF_mant_len);
83           mant += 1;
84           if (mant >= bit(SF_mant_len+1)) // rounding overflow?
85             { mant = mant>>1; exp = exp+1; }
86         }
87       #else
88       // Die NDS besteht aus msd, msdd, und len weiteren Digits.
89       // Das höchste in 2^32*msd+msdd gesetzte Bit ist Bit Nummer
90       // 31 + (exp mod intDsize).
91       var uintL shiftcount = exp % intDsize;
92       var uint32 mant = // führende 32 Bits
93         (shiftcount==0
94          ? msdd
95          : (((uint32)msd << (32-shiftcount)) | (msdd >> shiftcount))
96         );
97       // Das höchste in mant gesetzte Bit ist Bit Nummer 31.
98       if ( ((mant & bit(30-SF_mant_len)) ==0) // Bit 14 =0 -> abrunden
99            || ( ((mant & (bit(30-SF_mant_len)-1)) ==0) // Bit 14 =1 und Bits 13..0 =0
100                 && ((msdd & (bit(shiftcount)-1)) ==0) // und weitere Bits aus msdd =0
101                 && (!test_loop_msp(MSDptr,len)) // und alle weiteren Digits =0
102                 // round-to-even, je nach Bit 15 :
103                 && ((mant & bit(31-SF_mant_len)) ==0)
104          )    )
105         // abrunden
106         { mant = mant >> (31-SF_mant_len); }
107         else
108         // aufrunden
109         { mant = mant >> (31-SF_mant_len);
110           mant += 1;
111           if (mant >= bit(SF_mant_len+1)) // rounding overflow?
112             { mant = mant>>1; exp = exp+1; }
113         }
114       #endif
115       return encode_SF(sign,(sintL)exp,mant);
116 }
117
118 }  // namespace cln