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  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24  * THE SOFTWARE.
25  */
26 
27 #include <string.h>
28 #include <stdio.h>
29 #include <assert.h>
30 
31 #include "py/parsenumbase.h"
32 #include "py/smallint.h"
33 #include "py/objint.h"
34 #include "py/runtime.h"
35 
36 #if MICROPY_PY_BUILTINS_FLOAT
37 #include <math.h>
38 #endif
39 
40 #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ
41 
42 #if MICROPY_PY_SYS_MAXSIZE
43 // Export value for sys.maxsize
44 // *FORMAT-OFF*
45 #define DIG_MASK ((MPZ_LONG_1 << MPZ_DIG_SIZE) - 1)
46 STATIC const mpz_dig_t maxsize_dig[] = {
47     #define NUM_DIG 1
48     (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 0) & DIG_MASK,
49     #if (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 0) > DIG_MASK
50      #undef NUM_DIG
51      #define NUM_DIG 2
52      (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 1) & DIG_MASK,
53      #if (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 1) > DIG_MASK
54       #undef NUM_DIG
55       #define NUM_DIG 3
56       (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 2) & DIG_MASK,
57       #if (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 2) > DIG_MASK
58        #undef NUM_DIG
59        #define NUM_DIG 4
60        (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 3) & DIG_MASK,
61        #if (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 3) > DIG_MASK
62         #error cannot encode MP_SSIZE_MAX as mpz
63        #endif
64       #endif
65      #endif
66     #endif
67 };
68 // *FORMAT-ON*
69 const mp_obj_int_t mp_sys_maxsize_obj = {
70     {&mp_type_int},
71     {.fixed_dig = 1, .len = NUM_DIG, .alloc = NUM_DIG, .dig = (mpz_dig_t *)maxsize_dig}
72 };
73 #undef DIG_MASK
74 #undef NUM_DIG
75 #endif
76 
mp_obj_int_new_mpz(void)77 mp_obj_int_t *mp_obj_int_new_mpz(void) {
78     mp_obj_int_t *o = m_new_obj(mp_obj_int_t);
79     o->base.type = &mp_type_int;
80     mpz_init_zero(&o->mpz);
81     return o;
82 }
83 
84 // This routine expects you to pass in a buffer and size (in *buf and buf_size).
85 // If, for some reason, this buffer is too small, then it will allocate a
86 // buffer and return the allocated buffer and size in *buf and *buf_size. It
87 // is the callers responsibility to free this allocated buffer.
88 //
89 // The resulting formatted string will be returned from this function and the
90 // formatted size will be in *fmt_size.
91 //
92 // This particular routine should only be called for the mpz representation of the int.
mp_obj_int_formatted_impl(char ** buf,size_t * buf_size,size_t * fmt_size,mp_const_obj_t self_in,int base,const char * prefix,char base_char,char comma)93 char *mp_obj_int_formatted_impl(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in,
94     int base, const char *prefix, char base_char, char comma) {
95     assert(mp_obj_is_type(self_in, &mp_type_int));
96     const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
97 
98     size_t needed_size = mp_int_format_size(mpz_max_num_bits(&self->mpz), base, prefix, comma);
99     if (needed_size > *buf_size) {
100         *buf = m_new(char, needed_size);
101         *buf_size = needed_size;
102     }
103     char *str = *buf;
104 
105     *fmt_size = mpz_as_str_inpl(&self->mpz, base, prefix, base_char, comma, str);
106 
107     return str;
108 }
109 
mp_obj_int_from_bytes_impl(bool big_endian,size_t len,const byte * buf)110 mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf) {
111     mp_obj_int_t *o = mp_obj_int_new_mpz();
112     mpz_set_from_bytes(&o->mpz, big_endian, len, buf);
113     return MP_OBJ_FROM_PTR(o);
114 }
115 
mp_obj_int_to_bytes_impl(mp_obj_t self_in,bool big_endian,size_t len,byte * buf)116 void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf) {
117     assert(mp_obj_is_type(self_in, &mp_type_int));
118     mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
119     mpz_as_bytes(&self->mpz, big_endian, len, buf);
120 }
121 
mp_obj_int_sign(mp_obj_t self_in)122 int mp_obj_int_sign(mp_obj_t self_in) {
123     if (mp_obj_is_small_int(self_in)) {
124         mp_int_t val = MP_OBJ_SMALL_INT_VALUE(self_in);
125         if (val < 0) {
126             return -1;
127         } else if (val > 0) {
128             return 1;
129         } else {
130             return 0;
131         }
132     }
133     mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
134     if (self->mpz.len == 0) {
135         return 0;
136     } else if (self->mpz.neg == 0) {
137         return 1;
138     } else {
139         return -1;
140     }
141 }
142 
mp_obj_int_unary_op(mp_unary_op_t op,mp_obj_t o_in)143 mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) {
144     mp_obj_int_t *o = MP_OBJ_TO_PTR(o_in);
145     switch (op) {
146         case MP_UNARY_OP_BOOL:
147             return mp_obj_new_bool(!mpz_is_zero(&o->mpz));
148         case MP_UNARY_OP_HASH:
149             return MP_OBJ_NEW_SMALL_INT(mpz_hash(&o->mpz));
150         case MP_UNARY_OP_POSITIVE:
151             return o_in;
152         case MP_UNARY_OP_NEGATIVE: { mp_obj_int_t *o2 = mp_obj_int_new_mpz();
153                                      mpz_neg_inpl(&o2->mpz, &o->mpz);
154                                      return MP_OBJ_FROM_PTR(o2);
155         }
156         case MP_UNARY_OP_INVERT: { mp_obj_int_t *o2 = mp_obj_int_new_mpz();
157                                    mpz_not_inpl(&o2->mpz, &o->mpz);
158                                    return MP_OBJ_FROM_PTR(o2);
159         }
160         case MP_UNARY_OP_ABS: {
161             mp_obj_int_t *self = MP_OBJ_TO_PTR(o_in);
162             if (self->mpz.neg == 0) {
163                 return o_in;
164             }
165             mp_obj_int_t *self2 = mp_obj_int_new_mpz();
166             mpz_abs_inpl(&self2->mpz, &self->mpz);
167             return MP_OBJ_FROM_PTR(self2);
168         }
169         default:
170             return MP_OBJ_NULL;      // op not supported
171     }
172 }
173 
mp_obj_int_binary_op(mp_binary_op_t op,mp_obj_t lhs_in,mp_obj_t rhs_in)174 mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
175     const mpz_t *zlhs;
176     const mpz_t *zrhs;
177     mpz_t z_int;
178     mpz_dig_t z_int_dig[MPZ_NUM_DIG_FOR_INT];
179 
180     // lhs could be a small int (eg small-int + mpz)
181     if (mp_obj_is_small_int(lhs_in)) {
182         mpz_init_fixed_from_int(&z_int, z_int_dig, MPZ_NUM_DIG_FOR_INT, MP_OBJ_SMALL_INT_VALUE(lhs_in));
183         zlhs = &z_int;
184     } else {
185         assert(mp_obj_is_type(lhs_in, &mp_type_int));
186         zlhs = &((mp_obj_int_t *)MP_OBJ_TO_PTR(lhs_in))->mpz;
187     }
188 
189     // if rhs is small int, then lhs was not (otherwise mp_binary_op handles it)
190     if (mp_obj_is_small_int(rhs_in)) {
191         mpz_init_fixed_from_int(&z_int, z_int_dig, MPZ_NUM_DIG_FOR_INT, MP_OBJ_SMALL_INT_VALUE(rhs_in));
192         zrhs = &z_int;
193     } else if (mp_obj_is_type(rhs_in, &mp_type_int)) {
194         zrhs = &((mp_obj_int_t *)MP_OBJ_TO_PTR(rhs_in))->mpz;
195     #if MICROPY_PY_BUILTINS_FLOAT
196     } else if (mp_obj_is_float(rhs_in)) {
197         return mp_obj_float_binary_op(op, mpz_as_float(zlhs), rhs_in);
198     #endif
199     #if MICROPY_PY_BUILTINS_COMPLEX
200     } else if (mp_obj_is_type(rhs_in, &mp_type_complex)) {
201         return mp_obj_complex_binary_op(op, mpz_as_float(zlhs), 0, rhs_in);
202     #endif
203     } else {
204         // delegate to generic function to check for extra cases
205         return mp_obj_int_binary_op_extra_cases(op, lhs_in, rhs_in);
206     }
207 
208     #if MICROPY_PY_BUILTINS_FLOAT
209     if (op == MP_BINARY_OP_TRUE_DIVIDE || op == MP_BINARY_OP_INPLACE_TRUE_DIVIDE) {
210         if (mpz_is_zero(zrhs)) {
211             goto zero_division_error;
212         }
213         mp_float_t flhs = mpz_as_float(zlhs);
214         mp_float_t frhs = mpz_as_float(zrhs);
215         return mp_obj_new_float(flhs / frhs);
216     }
217     #endif
218 
219     if (op >= MP_BINARY_OP_INPLACE_OR && op < MP_BINARY_OP_CONTAINS) {
220         mp_obj_int_t *res = mp_obj_int_new_mpz();
221 
222         switch (op) {
223             case MP_BINARY_OP_ADD:
224             case MP_BINARY_OP_INPLACE_ADD:
225                 mpz_add_inpl(&res->mpz, zlhs, zrhs);
226                 break;
227             case MP_BINARY_OP_SUBTRACT:
228             case MP_BINARY_OP_INPLACE_SUBTRACT:
229                 mpz_sub_inpl(&res->mpz, zlhs, zrhs);
230                 break;
231             case MP_BINARY_OP_MULTIPLY:
232             case MP_BINARY_OP_INPLACE_MULTIPLY:
233                 mpz_mul_inpl(&res->mpz, zlhs, zrhs);
234                 break;
235             case MP_BINARY_OP_FLOOR_DIVIDE:
236             case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: {
237                 if (mpz_is_zero(zrhs)) {
238                 zero_division_error:
239                     mp_raise_msg(&mp_type_ZeroDivisionError, MP_ERROR_TEXT("divide by zero"));
240                 }
241                 mpz_t rem;
242                 mpz_init_zero(&rem);
243                 mpz_divmod_inpl(&res->mpz, &rem, zlhs, zrhs);
244                 mpz_deinit(&rem);
245                 break;
246             }
247             case MP_BINARY_OP_MODULO:
248             case MP_BINARY_OP_INPLACE_MODULO: {
249                 if (mpz_is_zero(zrhs)) {
250                     goto zero_division_error;
251                 }
252                 mpz_t quo;
253                 mpz_init_zero(&quo);
254                 mpz_divmod_inpl(&quo, &res->mpz, zlhs, zrhs);
255                 mpz_deinit(&quo);
256                 break;
257             }
258 
259             case MP_BINARY_OP_AND:
260             case MP_BINARY_OP_INPLACE_AND:
261                 mpz_and_inpl(&res->mpz, zlhs, zrhs);
262                 break;
263             case MP_BINARY_OP_OR:
264             case MP_BINARY_OP_INPLACE_OR:
265                 mpz_or_inpl(&res->mpz, zlhs, zrhs);
266                 break;
267             case MP_BINARY_OP_XOR:
268             case MP_BINARY_OP_INPLACE_XOR:
269                 mpz_xor_inpl(&res->mpz, zlhs, zrhs);
270                 break;
271 
272             case MP_BINARY_OP_LSHIFT:
273             case MP_BINARY_OP_INPLACE_LSHIFT:
274             case MP_BINARY_OP_RSHIFT:
275             case MP_BINARY_OP_INPLACE_RSHIFT: {
276                 mp_int_t irhs = mp_obj_int_get_checked(rhs_in);
277                 if (irhs < 0) {
278                     mp_raise_ValueError(MP_ERROR_TEXT("negative shift count"));
279                 }
280                 if (op == MP_BINARY_OP_LSHIFT || op == MP_BINARY_OP_INPLACE_LSHIFT) {
281                     mpz_shl_inpl(&res->mpz, zlhs, irhs);
282                 } else {
283                     mpz_shr_inpl(&res->mpz, zlhs, irhs);
284                 }
285                 break;
286             }
287 
288             case MP_BINARY_OP_POWER:
289             case MP_BINARY_OP_INPLACE_POWER:
290                 if (mpz_is_neg(zrhs)) {
291                     #if MICROPY_PY_BUILTINS_FLOAT
292                     return mp_obj_float_binary_op(op, mpz_as_float(zlhs), rhs_in);
293                     #else
294                     mp_raise_ValueError(MP_ERROR_TEXT("negative power with no float support"));
295                     #endif
296                 }
297                 mpz_pow_inpl(&res->mpz, zlhs, zrhs);
298                 break;
299 
300             default: {
301                 assert(op == MP_BINARY_OP_DIVMOD);
302                 if (mpz_is_zero(zrhs)) {
303                     goto zero_division_error;
304                 }
305                 mp_obj_int_t *quo = mp_obj_int_new_mpz();
306                 mpz_divmod_inpl(&quo->mpz, &res->mpz, zlhs, zrhs);
307                 mp_obj_t tuple[2] = {MP_OBJ_FROM_PTR(quo), MP_OBJ_FROM_PTR(res)};
308                 return mp_obj_new_tuple(2, tuple);
309             }
310         }
311 
312         return MP_OBJ_FROM_PTR(res);
313 
314     } else {
315         int cmp = mpz_cmp(zlhs, zrhs);
316         switch (op) {
317             case MP_BINARY_OP_LESS:
318                 return mp_obj_new_bool(cmp < 0);
319             case MP_BINARY_OP_MORE:
320                 return mp_obj_new_bool(cmp > 0);
321             case MP_BINARY_OP_LESS_EQUAL:
322                 return mp_obj_new_bool(cmp <= 0);
323             case MP_BINARY_OP_MORE_EQUAL:
324                 return mp_obj_new_bool(cmp >= 0);
325             case MP_BINARY_OP_EQUAL:
326                 return mp_obj_new_bool(cmp == 0);
327 
328             default:
329                 return MP_OBJ_NULL; // op not supported
330         }
331     }
332 }
333 
334 #if MICROPY_PY_BUILTINS_POW3
mp_mpz_for_int(mp_obj_t arg,mpz_t * temp)335 STATIC mpz_t *mp_mpz_for_int(mp_obj_t arg, mpz_t *temp) {
336     if (mp_obj_is_small_int(arg)) {
337         mpz_init_from_int(temp, MP_OBJ_SMALL_INT_VALUE(arg));
338         return temp;
339     } else {
340         mp_obj_int_t *arp_p = MP_OBJ_TO_PTR(arg);
341         return &(arp_p->mpz);
342     }
343 }
344 
mp_obj_int_pow3(mp_obj_t base,mp_obj_t exponent,mp_obj_t modulus)345 mp_obj_t mp_obj_int_pow3(mp_obj_t base, mp_obj_t exponent,  mp_obj_t modulus) {
346     if (!mp_obj_is_int(base) || !mp_obj_is_int(exponent) || !mp_obj_is_int(modulus)) {
347         mp_raise_TypeError(MP_ERROR_TEXT("pow() with 3 arguments requires integers"));
348     } else {
349         mp_obj_t result = mp_obj_new_int_from_ull(0); // Use the _from_ull version as this forces an mpz int
350         mp_obj_int_t *res_p = (mp_obj_int_t *)MP_OBJ_TO_PTR(result);
351 
352         mpz_t l_temp, r_temp, m_temp;
353         mpz_t *lhs = mp_mpz_for_int(base,     &l_temp);
354         mpz_t *rhs = mp_mpz_for_int(exponent, &r_temp);
355         mpz_t *mod = mp_mpz_for_int(modulus,  &m_temp);
356 
357         mpz_pow3_inpl(&(res_p->mpz), lhs, rhs, mod);
358 
359         if (lhs == &l_temp) {
360             mpz_deinit(lhs);
361         }
362         if (rhs == &r_temp) {
363             mpz_deinit(rhs);
364         }
365         if (mod == &m_temp) {
366             mpz_deinit(mod);
367         }
368         return result;
369     }
370 }
371 #endif
372 
mp_obj_new_int(mp_int_t value)373 mp_obj_t mp_obj_new_int(mp_int_t value) {
374     if (MP_SMALL_INT_FITS(value)) {
375         return MP_OBJ_NEW_SMALL_INT(value);
376     }
377     return mp_obj_new_int_from_ll(value);
378 }
379 
mp_obj_new_int_from_ll(long long val)380 mp_obj_t mp_obj_new_int_from_ll(long long val) {
381     mp_obj_int_t *o = mp_obj_int_new_mpz();
382     mpz_set_from_ll(&o->mpz, val, true);
383     return MP_OBJ_FROM_PTR(o);
384 }
385 
mp_obj_new_int_from_ull(unsigned long long val)386 mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) {
387     mp_obj_int_t *o = mp_obj_int_new_mpz();
388     mpz_set_from_ll(&o->mpz, val, false);
389     return MP_OBJ_FROM_PTR(o);
390 }
391 
mp_obj_new_int_from_uint(mp_uint_t value)392 mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
393     // SMALL_INT accepts only signed numbers, so make sure the input
394     // value fits completely in the small-int positive range.
395     if ((value & ~MP_SMALL_INT_POSITIVE_MASK) == 0) {
396         return MP_OBJ_NEW_SMALL_INT(value);
397     }
398     return mp_obj_new_int_from_ull(value);
399 }
400 
mp_obj_new_int_from_str_len(const char ** str,size_t len,bool neg,unsigned int base)401 mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) {
402     mp_obj_int_t *o = mp_obj_int_new_mpz();
403     size_t n = mpz_set_from_str(&o->mpz, *str, len, neg, base);
404     *str += n;
405     return MP_OBJ_FROM_PTR(o);
406 }
407 
mp_obj_int_get_truncated(mp_const_obj_t self_in)408 mp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in) {
409     if (mp_obj_is_small_int(self_in)) {
410         return MP_OBJ_SMALL_INT_VALUE(self_in);
411     } else {
412         const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
413         // hash returns actual int value if it fits in mp_int_t
414         return mpz_hash(&self->mpz);
415     }
416 }
417 
mp_obj_int_get_checked(mp_const_obj_t self_in)418 mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {
419     if (mp_obj_is_small_int(self_in)) {
420         return MP_OBJ_SMALL_INT_VALUE(self_in);
421     } else {
422         const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
423         mp_int_t value;
424         if (mpz_as_int_checked(&self->mpz, &value)) {
425             return value;
426         } else {
427             // overflow
428             mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("overflow converting long int to machine word"));
429         }
430     }
431 }
432 
mp_obj_int_get_uint_checked(mp_const_obj_t self_in)433 mp_uint_t mp_obj_int_get_uint_checked(mp_const_obj_t self_in) {
434     if (mp_obj_is_small_int(self_in)) {
435         if (MP_OBJ_SMALL_INT_VALUE(self_in) >= 0) {
436             return MP_OBJ_SMALL_INT_VALUE(self_in);
437         }
438     } else {
439         const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
440         mp_uint_t value;
441         if (mpz_as_uint_checked(&self->mpz, &value)) {
442             return value;
443         }
444     }
445 
446     mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("overflow converting long int to machine word"));
447 }
448 
449 #if MICROPY_PY_BUILTINS_FLOAT
mp_obj_int_as_float_impl(mp_obj_t self_in)450 mp_float_t mp_obj_int_as_float_impl(mp_obj_t self_in) {
451     assert(mp_obj_is_type(self_in, &mp_type_int));
452     mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
453     return mpz_as_float(&self->mpz);
454 }
455 #endif
456 
457 #endif
458