1 /*
2  * This file is part of the MicroPython project, http://micropython.org/
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2013, 2014 Damien P. George
7  * Copyright (c) 2014 Paul Sokolovsky
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a copy
10  * of this software and associated documentation files (the "Software"), to deal
11  * in the Software without restriction, including without limitation the rights
12  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13  * copies of the Software, and to permit persons to whom the Software is
14  * furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included in
17  * all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25  * THE SOFTWARE.
26  */
27 
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #include "py/smallint.h"
32 #include "py/objint.h"
33 #include "py/runtime.h"
34 
35 #if MICROPY_PY_BUILTINS_FLOAT
36 #include <math.h>
37 #endif
38 
39 #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
40 
41 #if MICROPY_PY_SYS_MAXSIZE
42 // Export value for sys.maxsize
43 const mp_obj_int_t mp_sys_maxsize_obj = {{&mp_type_int}, MP_SSIZE_MAX};
44 #endif
45 
mp_obj_int_from_bytes_impl(bool big_endian,size_t len,const byte * buf)46 mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf) {
47     int delta = 1;
48     if (!big_endian) {
49         buf += len - 1;
50         delta = -1;
51     }
52 
53     mp_longint_impl_t value = 0;
54     for (; len--; buf += delta) {
55         value = (value << 8) | *buf;
56     }
57     return mp_obj_new_int_from_ll(value);
58 }
59 
mp_obj_int_to_bytes_impl(mp_obj_t self_in,bool big_endian,size_t len,byte * buf)60 void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf) {
61     assert(mp_obj_is_type(self_in, &mp_type_int));
62     mp_obj_int_t *self = self_in;
63     long long val = self->val;
64     if (big_endian) {
65         byte *b = buf + len;
66         while (b > buf) {
67             *--b = val;
68             val >>= 8;
69         }
70     } else {
71         for (; len > 0; --len) {
72             *buf++ = val;
73             val >>= 8;
74         }
75     }
76 }
77 
mp_obj_int_sign(mp_obj_t self_in)78 int mp_obj_int_sign(mp_obj_t self_in) {
79     mp_longint_impl_t val;
80     if (mp_obj_is_small_int(self_in)) {
81         val = MP_OBJ_SMALL_INT_VALUE(self_in);
82     } else {
83         mp_obj_int_t *self = self_in;
84         val = self->val;
85     }
86     if (val < 0) {
87         return -1;
88     } else if (val > 0) {
89         return 1;
90     } else {
91         return 0;
92     }
93 }
94 
mp_obj_int_unary_op(mp_unary_op_t op,mp_obj_t o_in)95 mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) {
96     mp_obj_int_t *o = o_in;
97     switch (op) {
98         case MP_UNARY_OP_BOOL:
99             return mp_obj_new_bool(o->val != 0);
100 
101         // truncate value to fit in mp_int_t, which gives the same hash as
102         // small int if the value fits without truncation
103         case MP_UNARY_OP_HASH:
104             return MP_OBJ_NEW_SMALL_INT((mp_int_t)o->val);
105 
106         case MP_UNARY_OP_POSITIVE:
107             return o_in;
108         case MP_UNARY_OP_NEGATIVE:
109             return mp_obj_new_int_from_ll(-o->val);
110         case MP_UNARY_OP_INVERT:
111             return mp_obj_new_int_from_ll(~o->val);
112         case MP_UNARY_OP_ABS: {
113             mp_obj_int_t *self = MP_OBJ_TO_PTR(o_in);
114             if (self->val >= 0) {
115                 return o_in;
116             }
117             self = mp_obj_new_int_from_ll(self->val);
118             // TODO could overflow long long
119             self->val = -self->val;
120             return MP_OBJ_FROM_PTR(self);
121         }
122         default:
123             return MP_OBJ_NULL;      // op not supported
124     }
125 }
126 
mp_obj_int_binary_op(mp_binary_op_t op,mp_obj_t lhs_in,mp_obj_t rhs_in)127 mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
128     long long lhs_val;
129     long long rhs_val;
130 
131     if (mp_obj_is_small_int(lhs_in)) {
132         lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs_in);
133     } else {
134         assert(mp_obj_is_type(lhs_in, &mp_type_int));
135         lhs_val = ((mp_obj_int_t *)lhs_in)->val;
136     }
137 
138     if (mp_obj_is_small_int(rhs_in)) {
139         rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs_in);
140     } else if (mp_obj_is_type(rhs_in, &mp_type_int)) {
141         rhs_val = ((mp_obj_int_t *)rhs_in)->val;
142     } else {
143         // delegate to generic function to check for extra cases
144         return mp_obj_int_binary_op_extra_cases(op, lhs_in, rhs_in);
145     }
146 
147     switch (op) {
148         case MP_BINARY_OP_ADD:
149         case MP_BINARY_OP_INPLACE_ADD:
150             return mp_obj_new_int_from_ll(lhs_val + rhs_val);
151         case MP_BINARY_OP_SUBTRACT:
152         case MP_BINARY_OP_INPLACE_SUBTRACT:
153             return mp_obj_new_int_from_ll(lhs_val - rhs_val);
154         case MP_BINARY_OP_MULTIPLY:
155         case MP_BINARY_OP_INPLACE_MULTIPLY:
156             return mp_obj_new_int_from_ll(lhs_val * rhs_val);
157         case MP_BINARY_OP_FLOOR_DIVIDE:
158         case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE:
159             if (rhs_val == 0) {
160                 goto zero_division;
161             }
162             return mp_obj_new_int_from_ll(lhs_val / rhs_val);
163         case MP_BINARY_OP_MODULO:
164         case MP_BINARY_OP_INPLACE_MODULO:
165             if (rhs_val == 0) {
166                 goto zero_division;
167             }
168             return mp_obj_new_int_from_ll(lhs_val % rhs_val);
169 
170         case MP_BINARY_OP_AND:
171         case MP_BINARY_OP_INPLACE_AND:
172             return mp_obj_new_int_from_ll(lhs_val & rhs_val);
173         case MP_BINARY_OP_OR:
174         case MP_BINARY_OP_INPLACE_OR:
175             return mp_obj_new_int_from_ll(lhs_val | rhs_val);
176         case MP_BINARY_OP_XOR:
177         case MP_BINARY_OP_INPLACE_XOR:
178             return mp_obj_new_int_from_ll(lhs_val ^ rhs_val);
179 
180         case MP_BINARY_OP_LSHIFT:
181         case MP_BINARY_OP_INPLACE_LSHIFT:
182             return mp_obj_new_int_from_ll(lhs_val << (int)rhs_val);
183         case MP_BINARY_OP_RSHIFT:
184         case MP_BINARY_OP_INPLACE_RSHIFT:
185             return mp_obj_new_int_from_ll(lhs_val >> (int)rhs_val);
186 
187         case MP_BINARY_OP_POWER:
188         case MP_BINARY_OP_INPLACE_POWER: {
189             if (rhs_val < 0) {
190                 #if MICROPY_PY_BUILTINS_FLOAT
191                 return mp_obj_float_binary_op(op, lhs_val, rhs_in);
192                 #else
193                 mp_raise_ValueError(MP_ERROR_TEXT("negative power with no float support"));
194                 #endif
195             }
196             long long ans = 1;
197             while (rhs_val > 0) {
198                 if (rhs_val & 1) {
199                     ans *= lhs_val;
200                 }
201                 if (rhs_val == 1) {
202                     break;
203                 }
204                 rhs_val /= 2;
205                 lhs_val *= lhs_val;
206             }
207             return mp_obj_new_int_from_ll(ans);
208         }
209 
210         case MP_BINARY_OP_LESS:
211             return mp_obj_new_bool(lhs_val < rhs_val);
212         case MP_BINARY_OP_MORE:
213             return mp_obj_new_bool(lhs_val > rhs_val);
214         case MP_BINARY_OP_LESS_EQUAL:
215             return mp_obj_new_bool(lhs_val <= rhs_val);
216         case MP_BINARY_OP_MORE_EQUAL:
217             return mp_obj_new_bool(lhs_val >= rhs_val);
218         case MP_BINARY_OP_EQUAL:
219             return mp_obj_new_bool(lhs_val == rhs_val);
220 
221         default:
222             return MP_OBJ_NULL; // op not supported
223     }
224 
225 zero_division:
226     mp_raise_msg(&mp_type_ZeroDivisionError, MP_ERROR_TEXT("divide by zero"));
227 }
228 
mp_obj_new_int(mp_int_t value)229 mp_obj_t mp_obj_new_int(mp_int_t value) {
230     if (MP_SMALL_INT_FITS(value)) {
231         return MP_OBJ_NEW_SMALL_INT(value);
232     }
233     return mp_obj_new_int_from_ll(value);
234 }
235 
mp_obj_new_int_from_uint(mp_uint_t value)236 mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
237     // SMALL_INT accepts only signed numbers, so make sure the input
238     // value fits completely in the small-int positive range.
239     if ((value & ~MP_SMALL_INT_POSITIVE_MASK) == 0) {
240         return MP_OBJ_NEW_SMALL_INT(value);
241     }
242     return mp_obj_new_int_from_ll(value);
243 }
244 
mp_obj_new_int_from_ll(long long val)245 mp_obj_t mp_obj_new_int_from_ll(long long val) {
246     mp_obj_int_t *o = m_new_obj(mp_obj_int_t);
247     o->base.type = &mp_type_int;
248     o->val = val;
249     return o;
250 }
251 
mp_obj_new_int_from_ull(unsigned long long val)252 mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) {
253     // TODO raise an exception if the unsigned long long won't fit
254     if (val >> (sizeof(unsigned long long) * 8 - 1) != 0) {
255         mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("ulonglong too large"));
256     }
257     mp_obj_int_t *o = m_new_obj(mp_obj_int_t);
258     o->base.type = &mp_type_int;
259     o->val = val;
260     return o;
261 }
262 
mp_obj_new_int_from_str_len(const char ** str,size_t len,bool neg,unsigned int base)263 mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) {
264     // TODO this does not honor the given length of the string, but it all cases it should anyway be null terminated
265     // TODO check overflow
266     mp_obj_int_t *o = m_new_obj(mp_obj_int_t);
267     o->base.type = &mp_type_int;
268     char *endptr;
269     o->val = strtoll(*str, &endptr, base);
270     *str = endptr;
271     return o;
272 }
273 
mp_obj_int_get_truncated(mp_const_obj_t self_in)274 mp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in) {
275     if (mp_obj_is_small_int(self_in)) {
276         return MP_OBJ_SMALL_INT_VALUE(self_in);
277     } else {
278         const mp_obj_int_t *self = self_in;
279         return self->val;
280     }
281 }
282 
mp_obj_int_get_checked(mp_const_obj_t self_in)283 mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {
284     // TODO: Check overflow
285     return mp_obj_int_get_truncated(self_in);
286 }
287 
288 #if MICROPY_PY_BUILTINS_FLOAT
mp_obj_int_as_float_impl(mp_obj_t self_in)289 mp_float_t mp_obj_int_as_float_impl(mp_obj_t self_in) {
290     assert(mp_obj_is_type(self_in, &mp_type_int));
291     mp_obj_int_t *self = self_in;
292     return self->val;
293 }
294 #endif
295 
296 #endif
297