]> www.ginac.de Git - cln.git/blob - src/float/lfloat/elem/cl_LF_futrunc.cc
01eb27e0ae6c0f5bfb3428fcf85df1d82bedb389
[cln.git] / src / float / lfloat / elem / cl_LF_futrunc.cc
1 // futruncate().
2
3 // General includes.
4 #include "cl_sysdep.h"
5
6 // Specification.
7 #include "cl_LF.h"
8
9
10 // Implementation.
11
12 #include "cl_LF_impl.h"
13 #include "cl_DS.h"
14
15 const cl_LF futruncate (const cl_LF& x)
16 {
17 // Methode:
18 // x = 0.0 -> Ergebnis 0.0
19 // e<=0 -> Ergebnis 1.0 oder -1.0, je nach Vorzeichen von x.
20 // 1<=e<16n -> Greife die letzten (16n-e) Bits von x heraus.
21 //             Sind sie alle =0 -> Ergebnis x.
22 //             Sonst setze sie alle auf 0 und erhöhe dann die vorderen e Bits
23 //             um 1.
24 //             Kein Überlauf -> fertig.
25 //             Sonst (Ergebnis eine Zweierpotenz): Mantisse := .1000...000,
26 //               e:=e+1. (Test auf Überlauf wegen e<=16n überflüssig)
27 // e>=16n -> Ergebnis x.
28 #if 0
29       var cl_signean sign;
30       var sintL exp;
31       var const uintD* mantMSDptr;
32       var uintC mantlen;
33       LF_decode(x, { return x; }, sign=,exp=,mantMSDptr=,mantlen=,);
34       if (exp<=0) { return encode_LF1s(sign,mantlen); } // e<=0 -> Ergebnis +-1.0
35       if ((uintL)exp >= intDsize*(uintL)mantlen) // e>=16n -> x als Ergebnis
36         { return x; }
37         else
38         // 0 < e < 16n
39         { // Testen, ob alle hinteren 16n-e Bits =0 sind:
40           var uintC count = floor((uintL)exp,intDsize); // zu kopierende Digits, < mantlen
41           var uintC bitcount = ((uintL)exp) % intDsize; // zu kopierende Bits danach, >=0, <intDsize
42           var uintD mask = minus_bitm(intDsize-bitcount); // Maske mit bitcount Bits
43           var uintD* mantptr = mantMSDptr mspop count;
44           if (   ((mspref(mantptr,0) & ~mask) ==0)
45               && !test_loop_msp(mantptr mspop 1,mantlen-count-1)
46              )
47             { return x; }
48           // neue NUDS erzeugen mit e Bits aus mant mit Increment
49           // und 16n-e Nullbits:
50           CL_ALLOCA_STACK;
51           var uintD* MSDptr;
52           num_stack_alloc(mantlen, MSDptr=,);
53           { var uintD* ptr =
54               copy_loop_msp(mantMSDptr,MSDptr,count); // count ganze Digits kopieren
55             if ((mspref(ptr,0) = ((mspref(mantptr,0) & mask) - mask)) == 0) // dann bitcount Bits kopieren und incrementieren
56               { if (!( inc_loop_lsp(ptr,count) ==0)) // evtl. weiterincrementieren
57                   { mspref(MSDptr,0) = bit(intDsize-1); exp = exp+1; } // evtl. Exponenten erhöhen
58               }
59             clear_loop_msp(ptr mspop 1,mantlen-count-1); // Rest mit Nullen füllen
60           }
61           return encode_LF(sign,exp,MSDptr,mantlen);
62         }
63 #else
64       var uintC len = TheLfloat(x)->len;
65       var uintL uexp = TheLfloat(x)->expo;
66       if (uexp <= LF_exp_mid)
67         { if (uexp == 0) { return x; } // x=0.0 -> Ergebnis 0.0
68           return encode_LF1s(TheLfloat(x)->sign,len); // e<=0 -> Ergebnis +-1.0
69         }
70       var uintL exp = uexp - LF_exp_mid;
71       if (exp >= intDsize*(uintL)len) // e>=16n -> x als Ergebnis
72         { return x; }
73       // 0 < e < 16n
74       // Testen, ob alle hinteren 16n-e Bits =0 sind:
75       var uintC count = floor(exp,intDsize); // zu kopierende Digits, < mantlen
76       var uintC bitcount = exp % intDsize; // zu kopierende Bits danach, >=0, <intDsize
77       var uintD mask = minus_bitm(intDsize-bitcount); // Maske mit bitcount Bits
78       {var const uintD* mantptr = LF_MSDptr(x) mspop count;
79        if (   ((mspref(mantptr,0) & ~mask) ==0)
80            && !test_loop_msp(mantptr mspop 1,len-count-1)
81           )
82          { return x; }
83       }
84       // Nein -> neues Long-Float produzieren:
85       var Lfloat y = allocate_lfloat(len,uexp,TheLfloat(x)->sign); // neues Long-Float
86       // y_mant := NUDS mit e Bits aus x_mant mit Increment und 16n-e Nullbits:
87       {var const uintD* x_mantMSDptr = LF_MSDptr(x);
88        var uintD* y_mantMSDptr = arrayMSDptr(TheLfloat(y)->data,len);
89        var uintD* ptr =
90          copy_loop_msp(x_mantMSDptr,y_mantMSDptr,count); // count ganze Digits kopieren
91        if ((mspref(ptr,0) = ((mspref(x_mantMSDptr,count) & mask) - mask)) == 0) // dann bitcount Bits kopieren und incrementieren
92          { if (!( inc_loop_lsp(ptr,count) ==0)) // evtl. weiterincrementieren
93              { mspref(y_mantMSDptr,0) = bit(intDsize-1); (TheLfloat(y)->expo)++; } // evtl. Exponenten erhöhen
94          }
95        clear_loop_msp(ptr mspop 1,len-count-1); // Rest mit Nullen füllen
96       }
97       return y;
98 #endif
99 }