Branch data Line data Source code
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 <stdlib.h>
28 : : #include <assert.h>
29 : : #include <string.h>
30 : :
31 : : #include "py/parsenum.h"
32 : : #include "py/smallint.h"
33 : : #include "py/objint.h"
34 : : #include "py/objstr.h"
35 : : #include "py/runtime.h"
36 : : #include "py/binary.h"
37 : :
38 : : #if MICROPY_PY_BUILTINS_FLOAT
39 : : #include <math.h>
40 : : #endif
41 : :
42 : : // This dispatcher function is expected to be independent of the implementation of long int
43 : 324656 : static mp_obj_t mp_obj_int_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
44 : 324656 : (void)type_in;
45 : 324656 : mp_arg_check_num(n_args, n_kw, 0, 2, false);
46 : :
47 [ + + + ]: 324656 : switch (n_args) {
48 : : case 0:
49 : : return MP_OBJ_NEW_SMALL_INT(0);
50 : :
51 : 324452 : case 1: {
52 : 324452 : mp_buffer_info_t bufinfo;
53 : 324452 : mp_obj_t o = mp_unary_op(MP_UNARY_OP_INT_MAYBE, args[0]);
54 [ + + ]: 324448 : if (o != MP_OBJ_NULL) {
55 : : return o;
56 [ + + ]: 165149 : } else if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_READ)) {
57 : : // a textual representation, parse it
58 : 646 : return mp_parse_num_integer(bufinfo.buf, bufinfo.len, 0, NULL);
59 : : #if MICROPY_PY_BUILTINS_FLOAT
60 [ - + - + : 164503 : } else if (mp_obj_is_float(args[0])) {
- + + - +
+ ]
61 : 164499 : return mp_obj_new_int_from_float(mp_obj_float_get(args[0]));
62 : : #endif
63 : : } else {
64 : 4 : mp_raise_TypeError_int_conversion(args[0]);
65 : : }
66 : : }
67 : :
68 : 192 : case 2:
69 : : default: {
70 : : // should be a string, parse it
71 : 192 : size_t l;
72 : 192 : const char *s = mp_obj_str_get_data(args[0], &l);
73 : 192 : return mp_parse_num_integer(s, l, mp_obj_get_int(args[1]), NULL);
74 : : }
75 : : }
76 : : }
77 : :
78 : : #if MICROPY_PY_BUILTINS_FLOAT
79 : :
80 : : typedef enum {
81 : : MP_FP_CLASS_FIT_SMALLINT,
82 : : MP_FP_CLASS_FIT_LONGINT,
83 : : MP_FP_CLASS_OVERFLOW
84 : : } mp_fp_as_int_class_t;
85 : :
86 : 164831 : static mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) {
87 : 164831 : union {
88 : : mp_float_t f;
89 : : #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
90 : : uint32_t i;
91 : : #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
92 : : uint32_t i[2];
93 : : #endif
94 : 164831 : } u = {val};
95 : :
96 : 164831 : uint32_t e;
97 : : #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
98 : : e = u.i;
99 : : #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
100 : 164831 : e = u.i[MP_ENDIANNESS_LITTLE];
101 : : #endif
102 : : #define MP_FLOAT_SIGN_SHIFT_I32 ((MP_FLOAT_FRAC_BITS + MP_FLOAT_EXP_BITS) % 32)
103 : : #define MP_FLOAT_EXP_SHIFT_I32 (MP_FLOAT_FRAC_BITS % 32)
104 : :
105 [ + + ]: 164831 : if (e & (1U << MP_FLOAT_SIGN_SHIFT_I32)) {
106 : : #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
107 : 159095 : e |= u.i[MP_ENDIANNESS_BIG] != 0;
108 : : #endif
109 [ + + ]: 159095 : if ((e & ~(1U << MP_FLOAT_SIGN_SHIFT_I32)) == 0) {
110 : : // handle case of -0 (when sign is set but rest of bits are zero)
111 : : e = 0;
112 : : } else {
113 : 159071 : e += ((1U << MP_FLOAT_EXP_BITS) - 1) << MP_FLOAT_EXP_SHIFT_I32;
114 : : }
115 : : } else {
116 : 5736 : e &= ~((1U << MP_FLOAT_EXP_SHIFT_I32) - 1);
117 : : }
118 : : // 8 * sizeof(uintptr_t) counts the number of bits for a small int
119 : : // TODO provide a way to configure this properly
120 [ + + ]: 164807 : if (e <= ((8 * sizeof(uintptr_t) + MP_FLOAT_EXP_BIAS - 3) << MP_FLOAT_EXP_SHIFT_I32)) {
121 : 160375 : return MP_FP_CLASS_FIT_SMALLINT;
122 : : }
123 : : #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
124 : : if (e <= (((sizeof(long long) * MP_BITS_PER_BYTE) + MP_FLOAT_EXP_BIAS - 2) << MP_FLOAT_EXP_SHIFT_I32)) {
125 : : return MP_FP_CLASS_FIT_LONGINT;
126 : : }
127 : : #endif
128 : : #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ
129 : : return MP_FP_CLASS_FIT_LONGINT;
130 : : #else
131 : : return MP_FP_CLASS_OVERFLOW;
132 : : #endif
133 : : }
134 : : #undef MP_FLOAT_SIGN_SHIFT_I32
135 : : #undef MP_FLOAT_EXP_SHIFT_I32
136 : :
137 : 164931 : mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
138 : 164931 : mp_float_union_t u = {val};
139 : : // IEEE-754: if biased exponent is all 1 bits...
140 [ + + ]: 164931 : if (u.p.exp == ((1 << MP_FLOAT_EXP_BITS) - 1)) {
141 : : // ...then number is Inf (positive or negative) if fraction is 0, else NaN.
142 [ + + ]: 100 : if (u.p.frc == 0) {
143 : 60 : mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("can't convert inf to int"));
144 : : } else {
145 : 40 : mp_raise_ValueError(MP_ERROR_TEXT("can't convert NaN to int"));
146 : : }
147 : : } else {
148 : 164831 : mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val);
149 [ + + ]: 164831 : if (icl == MP_FP_CLASS_FIT_SMALLINT) {
150 : 160375 : return MP_OBJ_NEW_SMALL_INT((mp_int_t)val);
151 : : #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ
152 : : } else {
153 : 4456 : mp_obj_int_t *o = mp_obj_int_new_mpz();
154 : 4456 : mpz_set_from_float(&o->mpz, val);
155 : 4456 : return MP_OBJ_FROM_PTR(o);
156 : : }
157 : : #else
158 : : #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
159 : : } else if (icl == MP_FP_CLASS_FIT_LONGINT) {
160 : : return mp_obj_new_int_from_ll((long long)val);
161 : : #endif
162 : : } else {
163 : : mp_raise_ValueError(MP_ERROR_TEXT("float too big"));
164 : : }
165 : : #endif
166 : : }
167 : : }
168 : :
169 : : #endif
170 : :
171 : : #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
172 : : typedef mp_longint_impl_t fmt_int_t;
173 : : typedef unsigned long long fmt_uint_t;
174 : : #else
175 : : typedef mp_int_t fmt_int_t;
176 : : typedef mp_uint_t fmt_uint_t;
177 : : #endif
178 : :
179 : 178334 : void mp_obj_int_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
180 : 178334 : (void)kind;
181 : : // The size of this buffer is rather arbitrary. If it's not large
182 : : // enough, a dynamic one will be allocated.
183 : 178334 : char stack_buf[sizeof(fmt_int_t) * 4];
184 : 178334 : char *buf = stack_buf;
185 : 178334 : size_t buf_size = sizeof(stack_buf);
186 : 178334 : size_t fmt_size;
187 : :
188 : 178334 : char *str = mp_obj_int_formatted(&buf, &buf_size, &fmt_size, self_in, 10, NULL, '\0', '\0');
189 : 178334 : mp_print_str(print, str);
190 : :
191 [ + + ]: 178334 : if (buf != stack_buf) {
192 : 8500 : m_del(char, buf, buf_size);
193 : : }
194 : 178334 : }
195 : :
196 : : static const uint8_t log_base2_floor[] = {
197 : : 0, 1, 1, 2,
198 : : 2, 2, 2, 3,
199 : : 3, 3, 3, 3,
200 : : 3, 3, 3, 4,
201 : : /* if needed, these are the values for higher bases
202 : : 4, 4, 4, 4,
203 : : 4, 4, 4, 4,
204 : : 4, 4, 4, 4,
205 : : 4, 4, 4, 5
206 : : */
207 : : };
208 : :
209 : 257276 : size_t mp_int_format_size(size_t num_bits, int base, const char *prefix, char comma) {
210 [ - + ]: 257276 : assert(2 <= base && base <= 16);
211 : 257276 : size_t num_digits = num_bits / log_base2_floor[base - 1] + 1;
212 [ + + ]: 257276 : size_t num_commas = comma ? num_digits / 3 : 0;
213 [ + + ]: 257276 : size_t prefix_len = prefix ? strlen(prefix) : 0;
214 : 257276 : return num_digits + num_commas + prefix_len + 2; // +1 for sign, +1 for null byte
215 : : }
216 : :
217 : : // This routine expects you to pass in a buffer and size (in *buf and *buf_size).
218 : : // If, for some reason, this buffer is too small, then it will allocate a
219 : : // buffer and return the allocated buffer and size in *buf and *buf_size. It
220 : : // is the callers responsibility to free this allocated buffer.
221 : : //
222 : : // The resulting formatted string will be returned from this function and the
223 : : // formatted size will be in *fmt_size.
224 : 257276 : char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in,
225 : : int base, const char *prefix, char base_char, char comma) {
226 : 257276 : fmt_int_t num;
227 : : #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE
228 : : // Only have small ints; get the integer value to format.
229 : : num = MP_OBJ_SMALL_INT_VALUE(self_in);
230 : : #else
231 [ + + ]: 257276 : if (mp_obj_is_small_int(self_in)) {
232 : : // A small int; get the integer value to format.
233 : 234606 : num = MP_OBJ_SMALL_INT_VALUE(self_in);
234 : : } else {
235 [ + - - + ]: 22670 : assert(mp_obj_is_exact_type(self_in, &mp_type_int));
236 : : // Not a small int.
237 : : #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
238 : : const mp_obj_int_t *self = self_in;
239 : : // Get the value to format; mp_obj_get_int truncates to mp_int_t.
240 : : num = self->val;
241 : : #else
242 : : // Delegate to the implementation for the long int.
243 : 22670 : return mp_obj_int_formatted_impl(buf, buf_size, fmt_size, self_in, base, prefix, base_char, comma);
244 : : #endif
245 : : }
246 : : #endif
247 : :
248 : 234606 : char sign = '\0';
249 [ + + ]: 234606 : if (num < 0) {
250 : 4272 : num = -num;
251 : 4272 : sign = '-';
252 : : }
253 : :
254 : 234606 : size_t needed_size = mp_int_format_size(sizeof(fmt_int_t) * 8, base, prefix, comma);
255 [ + + ]: 234608 : if (needed_size > *buf_size) {
256 : 784 : *buf = m_new(char, needed_size);
257 : 784 : *buf_size = needed_size;
258 : : }
259 : 234608 : char *str = *buf;
260 : :
261 : 234608 : char *b = str + needed_size;
262 : 234608 : *(--b) = '\0';
263 : 234608 : char *last_comma = b;
264 : :
265 [ + + ]: 234608 : if (num == 0) {
266 : 62773 : *(--b) = '0';
267 : : } else {
268 : 337715 : do {
269 : : // The cast to fmt_uint_t is because num is positive and we want unsigned arithmetic
270 : 337715 : int c = (fmt_uint_t)num % base;
271 : 337715 : num = (fmt_uint_t)num / base;
272 [ + + ]: 337715 : if (c >= 10) {
273 : 21046 : c += base_char - 10;
274 : : } else {
275 : 316669 : c += '0';
276 : : }
277 : 337715 : *(--b) = c;
278 [ + + + - : 337715 : if (comma && num != 0 && b > str && (last_comma - b) == 3) {
+ + ]
279 : 8 : *(--b) = comma;
280 : 8 : last_comma = b;
281 : : }
282 : : }
283 [ + + ]: 337715 : while (b > str && num != 0);
284 : : }
285 [ + + ]: 234608 : if (prefix) {
286 : 23460 : size_t prefix_len = strlen(prefix);
287 : 23460 : char *p = b - prefix_len;
288 [ + + ]: 23460 : if (p > str) {
289 : 25499 : b = p;
290 [ + + ]: 25499 : while (*prefix) {
291 : 2040 : *p++ = *prefix++;
292 : : }
293 : : }
294 : : }
295 [ + + ]: 234608 : if (sign && b > str) {
296 : 4272 : *(--b) = sign;
297 : : }
298 : 234608 : *fmt_size = *buf + needed_size - b - 1;
299 : :
300 : 234608 : return b;
301 : : }
302 : :
303 : : #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE
304 : :
305 : : int mp_obj_int_sign(mp_obj_t self_in) {
306 : : mp_int_t val = mp_obj_get_int(self_in);
307 : : if (val < 0) {
308 : : return -1;
309 : : } else if (val > 0) {
310 : : return 1;
311 : : } else {
312 : : return 0;
313 : : }
314 : : }
315 : :
316 : : // This is called for operations on SMALL_INT that are not handled by mp_unary_op
317 : : mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) {
318 : : return MP_OBJ_NULL; // op not supported
319 : : }
320 : :
321 : : // This is called for operations on SMALL_INT that are not handled by mp_binary_op
322 : : mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
323 : : return mp_obj_int_binary_op_extra_cases(op, lhs_in, rhs_in);
324 : : }
325 : :
326 : : // This is called only with strings whose value doesn't fit in SMALL_INT
327 : : mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) {
328 : : mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("long int not supported in this build"));
329 : : return mp_const_none;
330 : : }
331 : :
332 : : // This is called when an integer larger than a SMALL_INT is needed (although val might still fit in a SMALL_INT)
333 : : mp_obj_t mp_obj_new_int_from_ll(long long val) {
334 : : mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("small int overflow"));
335 : : return mp_const_none;
336 : : }
337 : :
338 : : // This is called when an integer larger than a SMALL_INT is needed (although val might still fit in a SMALL_INT)
339 : : mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) {
340 : : mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("small int overflow"));
341 : : return mp_const_none;
342 : : }
343 : :
344 : : mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
345 : : // SMALL_INT accepts only signed numbers, so make sure the input
346 : : // value fits completely in the small-int positive range.
347 : : if ((value & ~MP_SMALL_INT_POSITIVE_MASK) == 0) {
348 : : return MP_OBJ_NEW_SMALL_INT(value);
349 : : }
350 : : mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("small int overflow"));
351 : : return mp_const_none;
352 : : }
353 : :
354 : : mp_obj_t mp_obj_new_int(mp_int_t value) {
355 : : if (MP_SMALL_INT_FITS(value)) {
356 : : return MP_OBJ_NEW_SMALL_INT(value);
357 : : }
358 : : mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("small int overflow"));
359 : : return mp_const_none;
360 : : }
361 : :
362 : : mp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in) {
363 : : return MP_OBJ_SMALL_INT_VALUE(self_in);
364 : : }
365 : :
366 : : mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {
367 : : return MP_OBJ_SMALL_INT_VALUE(self_in);
368 : : }
369 : :
370 : : #endif // MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE
371 : :
372 : : // This dispatcher function is expected to be independent of the implementation of long int
373 : : // It handles the extra cases for integer-like arithmetic
374 : 492 : mp_obj_t mp_obj_int_binary_op_extra_cases(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
375 [ + + ]: 492 : if (rhs_in == mp_const_false) {
376 : : // false acts as 0
377 : 8 : return mp_binary_op(op, lhs_in, MP_OBJ_NEW_SMALL_INT(0));
378 [ + + ]: 484 : } else if (rhs_in == mp_const_true) {
379 : : // true acts as 0
380 : 9 : return mp_binary_op(op, lhs_in, MP_OBJ_NEW_SMALL_INT(1));
381 [ + + ]: 475 : } else if (op == MP_BINARY_OP_MULTIPLY) {
382 [ + + + - : 422 : if (mp_obj_is_str_or_bytes(rhs_in) || mp_obj_is_type(rhs_in, &mp_type_tuple) || mp_obj_is_type(rhs_in, &mp_type_list)) {
+ - + + -
+ - + - +
+ - + + -
+ - + - +
+ - + + ]
383 : : // multiply is commutative for these types, so delegate to them
384 : 418 : return mp_binary_op(op, rhs_in, lhs_in);
385 : : }
386 : : }
387 : : return MP_OBJ_NULL; // op not supported
388 : : }
389 : :
390 : : // this is a classmethod
391 : 72 : static mp_obj_t int_from_bytes(size_t n_args, const mp_obj_t *args) {
392 : : // TODO: Support signed param (assumes signed=False at the moment)
393 : :
394 : : // get the buffer info
395 : 72 : mp_buffer_info_t bufinfo;
396 : 72 : mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
397 : :
398 : 72 : const byte *buf = (const byte *)bufinfo.buf;
399 : 72 : int delta = 1;
400 [ + + + + ]: 72 : bool big_endian = n_args < 3 || args[2] != MP_OBJ_NEW_QSTR(MP_QSTR_little);
401 [ + + ]: 72 : if (!big_endian) {
402 : 48 : buf += bufinfo.len - 1;
403 : 48 : delta = -1;
404 : : }
405 : :
406 : 72 : mp_uint_t value = 0;
407 : 72 : size_t len = bufinfo.len;
408 [ + + ]: 756 : for (; len--; buf += delta) {
409 : : #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
410 [ + + ]: 708 : if (value > (MP_SMALL_INT_MAX >> 8)) {
411 : : // Result will overflow a small-int so construct a big-int
412 : 24 : return mp_obj_int_from_bytes_impl(big_endian, bufinfo.len, bufinfo.buf);
413 : : }
414 : : #endif
415 : 684 : value = (value << 8) | *buf;
416 : : }
417 : 48 : return mp_obj_new_int_from_uint(value);
418 : : }
419 : :
420 : : static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_from_bytes_fun_obj, 2, 4, int_from_bytes);
421 : : static MP_DEFINE_CONST_CLASSMETHOD_OBJ(int_from_bytes_obj, MP_ROM_PTR(&int_from_bytes_fun_obj));
422 : :
423 : 228 : static mp_obj_t int_to_bytes(size_t n_args, const mp_obj_t *args) {
424 : : // TODO: Support signed (currently behaves as if signed=(val < 0))
425 : 228 : bool overflow;
426 : :
427 [ + + ]: 228 : mp_int_t dlen = n_args < 2 ? 1 : mp_obj_get_int(args[1]);
428 [ + + ]: 220 : if (dlen < 0) {
429 : 4 : mp_raise_ValueError(NULL);
430 : : }
431 [ + + + + ]: 224 : bool big_endian = n_args < 3 || args[2] != MP_OBJ_NEW_QSTR(MP_QSTR_little);
432 : :
433 : 224 : vstr_t vstr;
434 : 224 : vstr_init_len(&vstr, dlen);
435 : 224 : byte *data = (byte *)vstr.buf;
436 : :
437 : : #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
438 [ + + ]: 224 : if (!mp_obj_is_small_int(args[0])) {
439 : 100 : overflow = !mp_obj_int_to_bytes_impl(args[0], big_endian, dlen, data);
440 : : } else
441 : : #endif
442 : : {
443 : 124 : mp_int_t val = MP_OBJ_SMALL_INT_VALUE(args[0]);
444 : 124 : int slen = 0; // Number of bytes to represent val
445 : :
446 : : // This logic has a twin in objint_longlong.c
447 [ + + ]: 124 : if (val > 0) {
448 : 80 : slen = (sizeof(mp_int_t) * 8 - mp_clz_mpi(val) + 7) / 8;
449 [ + + ]: 44 : } else if (val < -1) {
450 : 24 : slen = (sizeof(mp_int_t) * 8 - mp_clz_mpi(~val) + 8) / 8;
451 : : } else {
452 : : // clz of 0 is defined, so 0 and -1 map to 0 and 1
453 : 20 : slen = -val;
454 : : }
455 : :
456 [ + + ]: 124 : if (slen <= dlen) {
457 [ + + ]: 96 : memset(data, val < 0 ? 0xFF : 0x00, dlen);
458 [ + + ]: 96 : mp_binary_set_int(slen, big_endian, data + (big_endian ? (dlen - slen) : 0), val);
459 : 96 : overflow = false;
460 : : } else {
461 : : overflow = true;
462 : : }
463 : : }
464 : :
465 [ + + ]: 196 : if (overflow) {
466 : 48 : mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("buffer too small"));
467 : : }
468 : :
469 : 176 : return mp_obj_new_bytes_from_vstr(&vstr);
470 : : }
471 : : static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_to_bytes_obj, 1, 4, int_to_bytes);
472 : :
473 : : static const mp_rom_map_elem_t int_locals_dict_table[] = {
474 : : { MP_ROM_QSTR(MP_QSTR_from_bytes), MP_ROM_PTR(&int_from_bytes_obj) },
475 : : { MP_ROM_QSTR(MP_QSTR_to_bytes), MP_ROM_PTR(&int_to_bytes_obj) },
476 : : };
477 : :
478 : : static MP_DEFINE_CONST_DICT(int_locals_dict, int_locals_dict_table);
479 : :
480 : : MP_DEFINE_CONST_OBJ_TYPE(
481 : : mp_type_int,
482 : : MP_QSTR_int,
483 : : MP_TYPE_FLAG_NONE,
484 : : make_new, mp_obj_int_make_new,
485 : : print, mp_obj_int_print,
486 : : unary_op, mp_obj_int_unary_op,
487 : : binary_op, mp_obj_int_binary_op,
488 : : locals_dict, &int_locals_dict
489 : : );
|