12 #include "cln/integer.h"
19 const cl_DF cl_I_to_DF (const cl_I& x)
22 // x=0 -> Ergebnis 0.0
23 // Merke Vorzeichen von x.
25 // Exponent:=(integer-length x)
26 // Greife die 54 höchstwertigen Bits heraus (angeführt von einer 1).
27 // Runde das letzte Bit weg:
28 // Bit 0 = 0 -> abrunden,
29 // Bit 0 = 1 und Rest =0 -> round-to-even,
30 // Bit 0 = 1 und Rest >0 -> aufrunden.
31 // Dabei um ein Bit nach rechts schieben.
32 // Bei Aufrundung auf 2^53 (rounding overflow) Mantisse um 1 Bit nach rechts
33 // schieben und Exponent incrementieren.
34 if (eq(x,0)) { return cl_DF_0; }
35 var cl_signean sign = -(cl_signean)minusp(x); // Vorzeichen
36 var cl_I abs_x = (sign==0 ? x : -x);
37 var uintC exp = integer_length(abs_x); // (integer-length x)
38 // NDS zu |x|>0 bilden:
39 var const uintD* MSDptr;
41 I_to_NDS_nocopy(abs_x, MSDptr=,len=,,false,);
42 // MSDptr/len/LSDptr ist die NDS zu x, len>0.
43 // Führende Digits holen: Brauche DF_mant_len+1 Bits, dazu intDsize
44 // Bits (die NDS kann mit bis zu intDsize Nullbits anfangen).
45 // Dann werden diese Bits um (exp mod intDsize) nach rechts geschoben.
46 var uintD msd = msprefnext(MSDptr); // erstes Digit
47 #if (cl_word_size==64)
48 var uint64 msdd = 0; // weitere min(len-1,64/intDsize) Digits
49 #define NEXT_DIGIT(i) \
50 { if (--len == 0) goto ok; \
51 msdd |= (uint64)msprefnext(MSDptr) << (64-(i+1)*intDsize); \
53 DOCONSTTIMES(64/intDsize,NEXT_DIGIT);
56 var uint32 msdd = 0; // weitere min(len-1,32/intDsize) Digits
57 var uint32 msddf = 0; // weitere maximal 32/intDsize Digits
58 #define NEXT_DIGIT(i) \
59 { if (--len == 0) goto ok; \
60 msdd |= (uint32)msprefnext(MSDptr) << (32-(i+1)*intDsize); \
62 DOCONSTTIMES(32/intDsize,NEXT_DIGIT);
64 #define NEXT_DIGIT(i) \
65 { if (--len == 0) goto ok; \
66 msddf |= (uint32)msprefnext(MSDptr) << (32-(i+1)*intDsize); \
68 DOCONSTTIMES(32/intDsize,NEXT_DIGIT);
72 #if (cl_word_size==64)
73 // Die NDS besteht aus msd, msdd und len weiteren Digits.
74 // Das höchste in 2^64*msd+msdd gesetzte Bit ist Bit Nummer
75 // 63 + (exp mod intDsize).
76 var uintL shiftcount = exp % intDsize;
77 var uint64 mant = // führende 64 Bits
80 : (((uint64)msd << (64-shiftcount)) | (msdd >> shiftcount))
82 // Das höchste in mant gesetzte Bit ist Bit Nummer 63.
83 if ( ((mant & bit(62-DF_mant_len)) ==0) // Bit 10 =0 -> abrunden
84 || ( ((mant & (bit(62-DF_mant_len)-1)) ==0) // Bit 10 =1 und Bits 9..0 =0
85 && ((msdd & (bit(shiftcount)-1)) ==0) // und weitere Bits aus msddf =0
86 && (!test_loop_msp(MSDptr,len)) // und alle weiteren Digits =0
87 // round-to-even, je nach Bit 11 :
88 && ((mant & bit(63-DF_mant_len)) ==0)
91 { mant = mant >> (63-DF_mant_len); }
94 { mant = mant >> (63-DF_mant_len);
96 if (mant >= bit(DF_mant_len+1)) // rounding overflow?
97 { mant = mant>>1; exp = exp+1; }
99 return encode_DF(sign,(sintL)exp,mant);
101 // Die NDS besteht aus msd, msdd, msddf und len weiteren Digits.
102 // Das höchste in 2^64*msd+2^32*msdd+msddf gesetzte Bit ist Bit Nummer
103 // 63 + (exp mod intDsize).
104 var uintL shiftcount = exp % intDsize;
105 var uint32 manthi; // führende 32 Bits
106 var uint32 mantlo; // nächste 32 Bits
108 { manthi = msdd; mantlo = msddf; }
110 { manthi = ((uint32)msd << (32-shiftcount)) | (msdd >> shiftcount);
111 mantlo = (msdd << (32-shiftcount)) | (msddf >> shiftcount);
113 // Das höchste in mant gesetzte Bit ist Bit Nummer 63.
114 if ( ((mantlo & bit(62-DF_mant_len)) ==0) // Bit 10 =0 -> abrunden
115 || ( ((mantlo & (bit(62-DF_mant_len)-1)) ==0) // Bit 10 =1 und Bits 9..0 =0
116 && ((msddf & (bit(shiftcount)-1)) ==0) // und weitere Bits aus msddf =0
117 && (!test_loop_msp(MSDptr,len)) // und alle weiteren Digits =0
118 // round-to-even, je nach Bit 11 :
119 && ((mantlo & bit(63-DF_mant_len)) ==0)
122 { mantlo = (mantlo >> (63-DF_mant_len)) | (manthi << (DF_mant_len-32+1));
123 manthi = manthi >> (63-DF_mant_len);
127 { mantlo = (mantlo >> (63-DF_mant_len)) | (manthi << (DF_mant_len-32+1));
128 manthi = manthi >> (63-DF_mant_len);
132 if (manthi >= bit(DF_mant_len-32+1)) // rounding overflow?
133 { manthi = manthi>>1; exp = exp+1; }
135 return encode_DF(sign,(sintL)exp,manthi,mantlo);