7 #include "cln/lfloat.h"
13 #include "cl_LF_impl.h"
18 const cl_LF fround (const cl_LF& x)
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
28 var const uintD* mantMSDptr;
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 ((uintL)exp >= intDsize*(uintL)mantlen) // e>=16n -> x als Ergebnis
36 { // alle hinteren 16n-e Bits wegrunden:
37 var uintC count = floor((uintL)exp,intDsize); // zu kopierende Digits, < mantlen
38 var uintC bitcount = ((uintL)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 :
46 { if ((mspref(mantptr,0) & (-2*mask)) ==0) goto ab; else goto auf; }
48 { if ((lspref(mantptr,0) & bit(0)) ==0) goto ab; else goto auf; }
50 // bitcount=0, count=0, also exp=0: Abrunden von +-0.5 zu 0.0
51 { return encode_LF0(mantlen); }
55 num_stack_alloc(mantlen, MSDptr=,);
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);
65 num_stack_alloc(mantlen, MSDptr=,);
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
72 clear_loop_msp(ptr mspop 1,mantlen-count-1); // Rest mit Nullen füllen
73 return encode_LF(sign,exp,MSDptr,mantlen);
77 var uintC len = TheLfloat(x)->len;
78 var uintL 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
83 var uintL exp = uexp - LF_exp_mid;
84 if (exp >= intDsize*(uintL)len) // e>=16n -> x als Ergebnis
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
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
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 :
102 { if ((mspref(mantptr,0) & (-2*mask)) ==0) goto ab; else goto auf; }
104 { if ((lspref(mantptr,0) & bit(0)) ==0) goto ab; else goto auf; }
106 // bitcount=0, count=0, also exp=0: Abrunden von +-0.5 zu 0.0
107 { return encode_LF0(len); }
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);
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
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);
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
131 clear_loop_msp(ptr mspop 1,len-count-1); // Rest mit Nullen füllen