]> www.ginac.de Git - cln.git/blob - src/integer/conv/cl_I_to_Q.cc
Fix integer input with leading zeros in power-of-two base.
[cln.git] / src / integer / conv / cl_I_to_Q.cc
1 // cl_I_to_Q().
2
3 // General includes.
4 #include "base/cl_sysdep.h"
5
6 // Specification.
7 #include "integer/cl_I.h"
8
9
10 // Implementation.
11
12 #ifdef intQsize
13
14 #include "cln/number.h"
15 #include "base/digitseq/cl_DS.h"
16 #include "cln/io.h"
17 #include "cln/integer_io.h"
18 #include "cln/exception.h"
19 #include <sstream>
20
21 namespace cln {
22
23 sint64 cl_I_to_Q (const cl_I& obj)
24 {
25         if (fixnump(obj))
26                 // Fixnum
27                 return (sint64)(sintV)FN_to_V(obj);
28     {   // Bignum
29         var cl_heap_bignum* bn = TheBignum(obj);
30         var uintC len = bn->length;
31         if ((sintD)mspref(arrayMSDptr(bn->data,len),0) >= 0) {
32                 // Bignum > 0
33                 #define IF_LENGTH(i)  \
34                   if (bn_minlength <= i) /* genau i Digits überhaupt möglich? */\
35                     if (len == i) /* genau i Digits? */                         \
36                       /* 2^((i-1)*intDsize-1) <= obj < 2^(i*intDsize-1) */      \
37                       if ( (i*intDsize > 64)                                    \
38                            && ( ((i-1)*intDsize >= 64)                          \
39                                 || (mspref(arrayMSDptr(bn->data,len),0) >= (uintD)bitc(63-(i-1)*intDsize)) \
40                          )    )                                                 \
41                         goto bad;                                               \
42                         else
43                 #if (intDsize==64)
44                 IF_LENGTH(1)
45                         return (uint64)arrayLSref(bn->data,1,0);
46                 #endif
47                 #if (intDsize==32)
48                 IF_LENGTH(1)
49                         return (uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,1));
50                 IF_LENGTH(2)
51                         return ((uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,2) lspop 1) << 32) | (uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,2));
52                 #endif
53                 #if (intDsize==16)
54                 IF_LENGTH(1)
55                         return (uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,1));
56                 IF_LENGTH(2)
57                         return (uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,2));
58                 IF_LENGTH(3)
59                         return ((uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,3) lspop 2) << 32) | (uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,3));
60                 IF_LENGTH(4)
61                         return ((uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,4) lspop 2) << 32) | (uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,4));
62                 #endif
63                 #if (intDsize==8)
64                 IF_LENGTH(1)
65                         return (uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,1));
66                 IF_LENGTH(2)
67                         return (uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,2));
68                 IF_LENGTH(3)
69                         return (uint64)get_uint3D_Dptr(arrayLSDptr(bn->data,3));
70                 IF_LENGTH(4)
71                         return (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,4));
72                 IF_LENGTH(5)
73                         return ((uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,5) lspop 4) << 32) | (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,5));
74                 IF_LENGTH(6)
75                         return ((uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,6) lspop 4) << 32) | (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,6));
76                 IF_LENGTH(7)
77                         return ((uint64)get_uint3D_Dptr(arrayLSDptr(bn->data,7) lspop 4) << 32) | (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,7));
78                 IF_LENGTH(8)
79                         return ((uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,8) lspop 4) << 32) | (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,8));
80                 #endif
81                 #undef IF_LENGTH
82         } else {
83                 // Bignum < 0
84                 #define IF_LENGTH(i)  \
85                   if (bn_minlength <= i) /* genau i Digits überhaupt möglich? */\
86                     if (len == i) /* genau i Digits? */                         \
87                       /* - 2^(i*intDsize-1) <= obj < - 2^((i-1)*intDsize-1) */  \
88                       if ( (i*intDsize > 64)                                    \
89                            && ( ((i-1)*intDsize >= 64)                          \
90                                 || (mspref(arrayMSDptr(bn->data,len),0) < (uintD)(-bitc(63-(i-1)*intDsize))) \
91                          )    )                                                 \
92                         goto bad;                                               \
93                         else
94                 #if (intDsize==64)
95                 IF_LENGTH(1)
96                         return (sint64)arrayLSref(bn->data,1,0);
97                 #endif
98                 #if (intDsize==32)
99                 IF_LENGTH(1)
100                         return (sint64)get_sint1D_Dptr(arrayLSDptr(bn->data,1));
101                 IF_LENGTH(2)
102                         return ((sint64)get_sint1D_Dptr(arrayLSDptr(bn->data,2) lspop 1) << 32) | (uint64)get_uint1D_Dptr(arrayLSDptr(bn->data,2));
103                 #endif
104                 #if (intDsize==16)
105                 IF_LENGTH(1)
106                         return (sint64)get_sint1D_Dptr(arrayLSDptr(bn->data,1));
107                 IF_LENGTH(2)
108                         return (sint64)get_sint2D_Dptr(arrayLSDptr(bn->data,2));
109                 IF_LENGTH(3)
110                         return ((sint64)get_sint1D_Dptr(arrayLSDptr(bn->data,3) lspop 2) << 32) | (uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,3));
111                 IF_LENGTH(4)
112                         return ((sint64)get_sint2D_Dptr(arrayLSDptr(bn->data,4) lspop 2) << 32) | (uint64)get_uint2D_Dptr(arrayLSDptr(bn->data,4));
113                 #endif
114                 #if (intDsize==8)
115                 IF_LENGTH(1)
116                         return (sint64)get_sint1D_Dptr(arrayLSDptr(bn->data,1));
117                 IF_LENGTH(2)
118                         return (sint64)get_sint2D_Dptr(arrayLSDptr(bn->data,2));
119                 IF_LENGTH(3)
120                         return (sint64)get_sint3D_Dptr(arrayLSDptr(bn->data,3));
121                 IF_LENGTH(4)
122                         return (sint64)get_sint4D_Dptr(arrayLSDptr(bn->data,4));
123                 IF_LENGTH(5)
124                         return ((sint64)get_sint1D_Dptr(arrayLSDptr(bn->data,5) lspop 4) << 32) | (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,5));
125                 IF_LENGTH(6)
126                         return ((sint64)get_sint2D_Dptr(arrayLSDptr(bn->data,6) lspop 4) << 32) | (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,6));
127                 IF_LENGTH(7)
128                         return ((sint64)get_sint3D_Dptr(arrayLSDptr(bn->data,7) lspop 4) << 32) | (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,7));
129                 IF_LENGTH(8)
130                         return ((sint64)get_sint4D_Dptr(arrayLSDptr(bn->data,8) lspop 4) << 32) | (uint64)get_uint4D_Dptr(arrayLSDptr(bn->data,8));
131                 #endif
132                 #undef IF_LENGTH
133         }
134         bad: // unpassendes Objekt
135         std::ostringstream buf;
136         fprint(buf, "Not a 64-bit integer: ");
137         fprint(buf, obj);
138         throw runtime_exception(buf.str());
139     }
140 }
141
142 }  // namespace cln
143
144 #endif