]> www.ginac.de Git - cln.git/blob - src/integer/conv/cl_I_from_NDS.cc
* Cumulative patch including Bruno's work on large fixnums on 64 bit machines.
[cln.git] / src / integer / conv / cl_I_from_NDS.cc
1 // NDS_to_I().
2
3 // General includes.
4 #include "cl_sysdep.h"
5
6 // Specification.
7 #include "cl_I.h"
8
9
10 // Implementation.
11
12 #include "cln/number.h"
13 #include "cl_DS.h"
14
15 namespace cln {
16
17 MAYBE_INLINE
18 const cl_I NDS_to_I (const uintD* MSDptr, uintC len)
19 {
20       // Mehr als bn_minlength Digits -> Bignum.
21       // Weniger als bn_minlength Digits -> Fixnum.
22       // Genau bn_minlength Digits -> Bignum oder Fixnum.
23       if (len < bn_minlength)
24         { // 0..bn_minlength-1 Digits, paßt in ein Fixnum:
25           if (bn_minlength>1 ? (len==0) : TRUE)
26             // 0 Digits
27             { return 0; }
28           #if (cl_word_size <= 32)
29           var sint32 wert;
30           if (bn_minlength>2 ? (len==1) : TRUE)
31             // 1 Digit
32             len_1:
33             { wert = get_sint1D_Dptr(MSDptr mspop 1); }
34           elif (bn_minlength>3 ? (len==2) : TRUE)
35             // 2 Digits
36             len_2:
37             { wert = get_sint2D_Dptr(MSDptr mspop 2); }
38           elif (bn_minlength>4 ? (len==3) : TRUE)
39             // 3 Digits
40             len_3:
41             { wert = get_sint3D_Dptr(MSDptr mspop 3); }
42           elif (TRUE)
43             // 4 Digits
44             len_4:
45             { wert = get_sint4D_Dptr(MSDptr mspop 4); }
46           elif (FALSE)
47             // 5 Digits
48             len_5:
49             { wert = get_sint4D_Dptr(MSDptr mspop 5); }
50           return L_to_FN(wert);
51           #else // (cl_word_size==64)
52           var sint64 wert;
53           #if (intDsize==32)
54           if (TRUE)
55             // 1 Digit
56             len_1:
57             { wert = (sint64)(sintD)mspref(MSDptr,0); }
58           elif (FALSE)
59             // 2 Digits
60             len_2:
61             { wert = ((sint64)(sintD)mspref(MSDptr,0) << intDsize) | (uint64)(uintD)mspref(MSDptr,1); }
62           #endif
63           #if (intDsize==64)
64           if (FALSE)
65             // 1 Digit
66             len_1:
67             { wert = (sintD)mspref(MSDptr,0); }
68           #endif
69           return cl_I_from_word(cl_combine(cl_FN_tag,wert));
70           #endif
71         }
72       #if (cl_value_len > (bn_minlength-1)*intDsize)
73       if (len == bn_minlength)
74         // bn_minlength Digits, also (incl. Vorzeichen) zwischen
75         // (bn_minlength-1)*intDsize+1 und bn_minlength*intDsize Bits.
76         // Höchstens cl_value_len Bits -> paßt in ein Fixnum:
77         { if (  (mspref(MSDptr,0) <= (uintD)(bit(cl_value_len-1-(bn_minlength-1)*intDsize)-1)) // Fixnum >=0 ?
78               ||(mspref(MSDptr,0) >= (uintD)(-bit(cl_value_len-1-(bn_minlength-1)*intDsize))) // Fixnum <0 ?
79              )
80             #if (bn_minlength==1)
81             goto len_1;
82             #endif
83             #if (bn_minlength==2)
84             goto len_2;
85             #endif
86             #if (bn_minlength==3)
87             goto len_3;
88             #endif
89             #if (bn_minlength==4)
90             goto len_4;
91             #endif
92             #if (bn_minlength==5)
93             goto len_5;
94             #endif
95         }
96       #endif
97       // mindestens bn_minlength Digits, mache ein Bignum
98       { var Bignum result = allocate_bignum(len);
99         // neues Bignum mit dem Inhalt der NDS füllen:
100         copy_loop_msp(MSDptr,arrayMSDptr(result->data,len),len);
101         return result;
102       }
103 }
104
105 }  // namespace cln