LCOV - code coverage report
Current view: top level - py - objint_mpz.c (source / functions) Hit Total Coverage
Test: unix_coverage_v1.24.0-7-g548babf8a.info Lines: 218 218 100.0 %
Date: 2024-10-30 09:06:48 Functions: 18 18 100.0 %
Branches: 143 163 87.7 %

           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 <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                 :            : 
      77                 :      25474 : mp_obj_int_t *mp_obj_int_new_mpz(void) {
      78                 :      25474 :     mp_obj_int_t *o = mp_obj_malloc(mp_obj_int_t, &mp_type_int);
      79                 :      25474 :     mpz_init_zero(&o->mpz);
      80                 :      25474 :     return o;
      81                 :            : }
      82                 :            : 
      83                 :            : // This routine expects you to pass in a buffer and size (in *buf and buf_size).
      84                 :            : // If, for some reason, this buffer is too small, then it will allocate a
      85                 :            : // buffer and return the allocated buffer and size in *buf and *buf_size. It
      86                 :            : // is the callers responsibility to free this allocated buffer.
      87                 :            : //
      88                 :            : // The resulting formatted string will be returned from this function and the
      89                 :            : // formatted size will be in *fmt_size.
      90                 :            : //
      91                 :            : // This particular routine should only be called for the mpz representation of the int.
      92                 :      22670 : char *mp_obj_int_formatted_impl(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in,
      93                 :            :     int base, const char *prefix, char base_char, char comma) {
      94   [ +  -  -  + ]:      22670 :     assert(mp_obj_is_exact_type(self_in, &mp_type_int));
      95                 :      22670 :     const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
      96                 :            : 
      97                 :      22670 :     size_t needed_size = mp_int_format_size(mpz_max_num_bits(&self->mpz), base, prefix, comma);
      98         [ +  + ]:      22670 :     if (needed_size > *buf_size) {
      99                 :      12940 :         *buf = m_new(char, needed_size);
     100                 :      12940 :         *buf_size = needed_size;
     101                 :            :     }
     102                 :      22670 :     char *str = *buf;
     103                 :            : 
     104                 :      22670 :     *fmt_size = mpz_as_str_inpl(&self->mpz, base, prefix, base_char, comma, str);
     105                 :            : 
     106                 :      22670 :     return str;
     107                 :            : }
     108                 :            : 
     109                 :         24 : mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf) {
     110                 :         24 :     mp_obj_int_t *o = mp_obj_int_new_mpz();
     111                 :         24 :     mpz_set_from_bytes(&o->mpz, big_endian, len, buf);
     112                 :         24 :     return MP_OBJ_FROM_PTR(o);
     113                 :            : }
     114                 :            : 
     115                 :        132 : bool mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf) {
     116   [ +  -  -  + ]:        132 :     assert(mp_obj_is_exact_type(self_in, &mp_type_int));
     117                 :        132 :     mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
     118                 :        132 :     return mpz_as_bytes(&self->mpz, big_endian, self->mpz.neg, len, buf);
     119                 :            : }
     120                 :            : 
     121                 :      79538 : int mp_obj_int_sign(mp_obj_t self_in) {
     122         [ +  + ]:      79538 :     if (mp_obj_is_small_int(self_in)) {
     123                 :      75026 :         mp_int_t val = MP_OBJ_SMALL_INT_VALUE(self_in);
     124         [ +  + ]:      75026 :         if (val < 0) {
     125                 :            :             return -1;
     126         [ +  + ]:      74170 :         } else if (val > 0) {
     127                 :            :             return 1;
     128                 :            :         } else {
     129                 :      37359 :             return 0;
     130                 :            :         }
     131                 :            :     }
     132                 :       4512 :     mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
     133         [ +  + ]:       4512 :     if (self->mpz.len == 0) {
     134                 :            :         return 0;
     135         [ +  + ]:       4508 :     } else if (self->mpz.neg == 0) {
     136                 :            :         return 1;
     137                 :            :     } else {
     138                 :         14 :         return -1;
     139                 :            :     }
     140                 :            : }
     141                 :            : 
     142                 :        604 : mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) {
     143                 :        604 :     mp_obj_int_t *o = MP_OBJ_TO_PTR(o_in);
     144   [ +  +  +  +  :        604 :     switch (op) {
                +  +  + ]
     145                 :         24 :         case MP_UNARY_OP_BOOL:
     146         [ -  + ]:         24 :             return mp_obj_new_bool(!mpz_is_zero(&o->mpz));
     147                 :         12 :         case MP_UNARY_OP_HASH:
     148                 :         12 :             return MP_OBJ_NEW_SMALL_INT(mpz_hash(&o->mpz));
     149                 :            :         case MP_UNARY_OP_POSITIVE:
     150                 :            :             return o_in;
     151                 :        534 :         case MP_UNARY_OP_NEGATIVE: { mp_obj_int_t *o2 = mp_obj_int_new_mpz();
     152                 :        534 :                                      mpz_neg_inpl(&o2->mpz, &o->mpz);
     153                 :        534 :                                      return MP_OBJ_FROM_PTR(o2);
     154                 :            :         }
     155                 :         12 :         case MP_UNARY_OP_INVERT: { mp_obj_int_t *o2 = mp_obj_int_new_mpz();
     156                 :         12 :                                    mpz_not_inpl(&o2->mpz, &o->mpz);
     157                 :         12 :                                    return MP_OBJ_FROM_PTR(o2);
     158                 :            :         }
     159                 :         10 :         case MP_UNARY_OP_ABS: {
     160                 :         10 :             mp_obj_int_t *self = MP_OBJ_TO_PTR(o_in);
     161         [ +  + ]:         10 :             if (self->mpz.neg == 0) {
     162                 :            :                 return o_in;
     163                 :            :             }
     164                 :          6 :             mp_obj_int_t *self2 = mp_obj_int_new_mpz();
     165                 :          6 :             mpz_abs_inpl(&self2->mpz, &self->mpz);
     166                 :          6 :             return MP_OBJ_FROM_PTR(self2);
     167                 :            :         }
     168                 :            :         case MP_UNARY_OP_INT_MAYBE:
     169                 :            :             return o_in;
     170                 :          4 :         default:
     171                 :          4 :             return MP_OBJ_NULL;      // op not supported
     172                 :            :     }
     173                 :            : }
     174                 :            : 
     175                 :      34596 : mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
     176                 :      34596 :     const mpz_t *zlhs;
     177                 :      34596 :     const mpz_t *zrhs;
     178                 :      34596 :     mpz_t z_int;
     179                 :      34596 :     mpz_dig_t z_int_dig[MPZ_NUM_DIG_FOR_INT];
     180                 :            : 
     181                 :            :     // lhs could be a small int (eg small-int + mpz)
     182         [ +  + ]:      34596 :     if (mp_obj_is_small_int(lhs_in)) {
     183                 :        822 :         mpz_init_fixed_from_int(&z_int, z_int_dig, MPZ_NUM_DIG_FOR_INT, MP_OBJ_SMALL_INT_VALUE(lhs_in));
     184                 :        822 :         zlhs = &z_int;
     185                 :            :     } else {
     186   [ +  -  -  + ]:      33774 :         assert(mp_obj_is_exact_type(lhs_in, &mp_type_int));
     187                 :      33774 :         zlhs = &((mp_obj_int_t *)MP_OBJ_TO_PTR(lhs_in))->mpz;
     188                 :            :     }
     189                 :            : 
     190                 :            :     // if rhs is small int, then lhs was not (otherwise mp_binary_op handles it)
     191         [ +  + ]:      34596 :     if (mp_obj_is_small_int(rhs_in)) {
     192                 :      24622 :         mpz_init_fixed_from_int(&z_int, z_int_dig, MPZ_NUM_DIG_FOR_INT, MP_OBJ_SMALL_INT_VALUE(rhs_in));
     193                 :      24622 :         zrhs = &z_int;
     194   [ +  +  +  + ]:       9974 :     } else if (mp_obj_is_exact_type(rhs_in, &mp_type_int)) {
     195                 :       9470 :         zrhs = &((mp_obj_int_t *)MP_OBJ_TO_PTR(rhs_in))->mpz;
     196                 :            :     #if MICROPY_PY_BUILTINS_FLOAT
     197   [ -  +  -  +  :        504 :     } else if (mp_obj_is_float(rhs_in)) {
          -  +  -  +  +  
                +  +  + ]
     198                 :          8 :         return mp_obj_float_binary_op(op, mpz_as_float(zlhs), rhs_in);
     199                 :            :     #endif
     200                 :            :     #if MICROPY_PY_BUILTINS_COMPLEX
     201   [ -  +  -  +  :        496 :     } else if (mp_obj_is_type(rhs_in, &mp_type_complex)) {
          -  +  -  +  +  
                +  +  + ]
     202                 :          4 :         return mp_obj_complex_binary_op(op, mpz_as_float(zlhs), 0, rhs_in);
     203                 :            :     #endif
     204                 :            :     } else {
     205                 :            :         // delegate to generic function to check for extra cases
     206                 :        492 :         return mp_obj_int_binary_op_extra_cases(op, lhs_in, rhs_in);
     207                 :            :     }
     208                 :            : 
     209                 :            :     #if MICROPY_PY_BUILTINS_FLOAT
     210         [ +  + ]:      34092 :     if (op == MP_BINARY_OP_TRUE_DIVIDE || op == MP_BINARY_OP_INPLACE_TRUE_DIVIDE) {
     211         [ +  + ]:          8 :         if (mpz_is_zero(zrhs)) {
     212                 :          4 :             goto zero_division_error;
     213                 :            :         }
     214                 :          4 :         mp_float_t flhs = mpz_as_float(zlhs);
     215                 :          4 :         mp_float_t frhs = mpz_as_float(zrhs);
     216                 :          4 :         return mp_obj_new_float(flhs / frhs);
     217                 :            :     }
     218                 :            :     #endif
     219                 :            : 
     220         [ +  + ]:      34084 :     if (op >= MP_BINARY_OP_INPLACE_OR && op < MP_BINARY_OP_CONTAINS) {
     221                 :      17850 :         mp_obj_int_t *res = mp_obj_int_new_mpz();
     222                 :            : 
     223   [ +  +  +  +  :      17850 :         switch (op) {
          +  +  +  +  +  
                +  +  + ]
     224                 :        124 :             case MP_BINARY_OP_ADD:
     225                 :            :             case MP_BINARY_OP_INPLACE_ADD:
     226                 :        124 :                 mpz_add_inpl(&res->mpz, zlhs, zrhs);
     227                 :        124 :                 break;
     228                 :        146 :             case MP_BINARY_OP_SUBTRACT:
     229                 :            :             case MP_BINARY_OP_INPLACE_SUBTRACT:
     230                 :        146 :                 mpz_sub_inpl(&res->mpz, zlhs, zrhs);
     231                 :        146 :                 break;
     232                 :       5386 :             case MP_BINARY_OP_MULTIPLY:
     233                 :            :             case MP_BINARY_OP_INPLACE_MULTIPLY:
     234                 :       5386 :                 mpz_mul_inpl(&res->mpz, zlhs, zrhs);
     235                 :       5386 :                 break;
     236                 :            :             case MP_BINARY_OP_FLOOR_DIVIDE:
     237                 :            :             case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: {
     238         [ +  + ]:       8950 :                 if (mpz_is_zero(zrhs)) {
     239                 :          4 :                 zero_division_error:
     240                 :         16 :                     mp_raise_msg(&mp_type_ZeroDivisionError, MP_ERROR_TEXT("divide by zero"));
     241                 :            :                 }
     242                 :       8946 :                 mpz_t rem;
     243                 :       8946 :                 mpz_init_zero(&rem);
     244                 :       8946 :                 mpz_divmod_inpl(&res->mpz, &rem, zlhs, zrhs);
     245                 :       8946 :                 mpz_deinit(&rem);
     246                 :       8946 :                 break;
     247                 :            :             }
     248                 :            :             case MP_BINARY_OP_MODULO:
     249                 :            :             case MP_BINARY_OP_INPLACE_MODULO: {
     250         [ +  + ]:        496 :                 if (mpz_is_zero(zrhs)) {
     251                 :          4 :                     goto zero_division_error;
     252                 :            :                 }
     253                 :        492 :                 mpz_t quo;
     254                 :        492 :                 mpz_init_zero(&quo);
     255                 :        492 :                 mpz_divmod_inpl(&quo, &res->mpz, zlhs, zrhs);
     256                 :        492 :                 mpz_deinit(&quo);
     257                 :        492 :                 break;
     258                 :            :             }
     259                 :            : 
     260                 :        232 :             case MP_BINARY_OP_AND:
     261                 :            :             case MP_BINARY_OP_INPLACE_AND:
     262                 :        232 :                 mpz_and_inpl(&res->mpz, zlhs, zrhs);
     263                 :        232 :                 break;
     264                 :        160 :             case MP_BINARY_OP_OR:
     265                 :            :             case MP_BINARY_OP_INPLACE_OR:
     266                 :        160 :                 mpz_or_inpl(&res->mpz, zlhs, zrhs);
     267                 :        160 :                 break;
     268                 :        156 :             case MP_BINARY_OP_XOR:
     269                 :            :             case MP_BINARY_OP_INPLACE_XOR:
     270                 :        156 :                 mpz_xor_inpl(&res->mpz, zlhs, zrhs);
     271                 :        156 :                 break;
     272                 :            : 
     273                 :       1782 :             case MP_BINARY_OP_LSHIFT:
     274                 :            :             case MP_BINARY_OP_INPLACE_LSHIFT:
     275                 :            :             case MP_BINARY_OP_RSHIFT:
     276                 :            :             case MP_BINARY_OP_INPLACE_RSHIFT: {
     277                 :       1782 :                 mp_int_t irhs = mp_obj_int_get_checked(rhs_in);
     278         [ +  + ]:       1782 :                 if (irhs < 0) {
     279                 :          8 :                     mp_raise_ValueError(MP_ERROR_TEXT("negative shift count"));
     280                 :            :                 }
     281         [ +  + ]:       1774 :                 if (op == MP_BINARY_OP_LSHIFT || op == MP_BINARY_OP_INPLACE_LSHIFT) {
     282                 :       1298 :                     mpz_shl_inpl(&res->mpz, zlhs, irhs);
     283                 :            :                 } else {
     284                 :        476 :                     mpz_shr_inpl(&res->mpz, zlhs, irhs);
     285                 :            :                 }
     286                 :            :                 break;
     287                 :            :             }
     288                 :            : 
     289                 :            :             case MP_BINARY_OP_POWER:
     290                 :            :             case MP_BINARY_OP_INPLACE_POWER:
     291         [ +  + ]:        386 :                 if (mpz_is_neg(zrhs)) {
     292                 :            :                     #if MICROPY_PY_BUILTINS_FLOAT
     293                 :          4 :                     return mp_obj_float_binary_op(op, mpz_as_float(zlhs), rhs_in);
     294                 :            :                     #else
     295                 :            :                     mp_raise_ValueError(MP_ERROR_TEXT("negative power with no float support"));
     296                 :            :                     #endif
     297                 :            :                 }
     298                 :        382 :                 mpz_pow_inpl(&res->mpz, zlhs, zrhs);
     299                 :        382 :                 break;
     300                 :            : 
     301                 :            :             case MP_BINARY_OP_DIVMOD: {
     302         [ +  + ]:         20 :                 if (mpz_is_zero(zrhs)) {
     303                 :          4 :                     goto zero_division_error;
     304                 :            :                 }
     305                 :         16 :                 mp_obj_int_t *quo = mp_obj_int_new_mpz();
     306                 :         16 :                 mpz_divmod_inpl(&quo->mpz, &res->mpz, zlhs, zrhs);
     307                 :         16 :                 mp_obj_t tuple[2] = {MP_OBJ_FROM_PTR(quo), MP_OBJ_FROM_PTR(res)};
     308                 :         16 :                 return mp_obj_new_tuple(2, tuple);
     309                 :            :             }
     310                 :            : 
     311                 :            :             default:
     312                 :            :                 return MP_OBJ_NULL; // op not supported
     313                 :            :         }
     314                 :            : 
     315                 :            :         // Check if the result fits in a small-int, and if so just return that.
     316                 :      17798 :         mp_int_t res_small;
     317         [ +  + ]:      17798 :         if (mpz_as_int_checked(&res->mpz, &res_small)) {
     318         [ +  + ]:        808 :             if (MP_SMALL_INT_FITS(res_small)) {
     319                 :        702 :                 return MP_OBJ_NEW_SMALL_INT(res_small);
     320                 :            :             }
     321                 :            :         }
     322                 :            : 
     323                 :            :         return MP_OBJ_FROM_PTR(res);
     324                 :            : 
     325                 :            :     } else {
     326                 :      16234 :         int cmp = mpz_cmp(zlhs, zrhs);
     327   [ +  +  +  +  :      16234 :         switch (op) {
                   +  + ]
     328                 :        174 :             case MP_BINARY_OP_LESS:
     329         [ +  + ]:        274 :                 return mp_obj_new_bool(cmp < 0);
     330                 :       7136 :             case MP_BINARY_OP_MORE:
     331         [ +  + ]:       7224 :                 return mp_obj_new_bool(cmp > 0);
     332                 :        164 :             case MP_BINARY_OP_LESS_EQUAL:
     333         [ +  + ]:        240 :                 return mp_obj_new_bool(cmp <= 0);
     334                 :        160 :             case MP_BINARY_OP_MORE_EQUAL:
     335         [ +  + ]:        232 :                 return mp_obj_new_bool(cmp >= 0);
     336                 :       8584 :             case MP_BINARY_OP_EQUAL:
     337         [ +  + ]:      16780 :                 return mp_obj_new_bool(cmp == 0);
     338                 :            : 
     339                 :            :             default:
     340                 :            :                 return MP_OBJ_NULL; // op not supported
     341                 :            :         }
     342                 :            :     }
     343                 :            : }
     344                 :            : 
     345                 :            : #if MICROPY_PY_BUILTINS_POW3
     346                 :        144 : static mpz_t *mp_mpz_for_int(mp_obj_t arg, mpz_t *temp) {
     347         [ +  + ]:        144 :     if (mp_obj_is_small_int(arg)) {
     348                 :         96 :         mpz_init_from_int(temp, MP_OBJ_SMALL_INT_VALUE(arg));
     349                 :         96 :         return temp;
     350                 :            :     } else {
     351                 :         48 :         mp_obj_int_t *arp_p = MP_OBJ_TO_PTR(arg);
     352                 :         48 :         return &(arp_p->mpz);
     353                 :            :     }
     354                 :            : }
     355                 :            : 
     356                 :         60 : mp_obj_t mp_obj_int_pow3(mp_obj_t base, mp_obj_t exponent,  mp_obj_t modulus) {
     357   [ +  +  +  +  :         60 :     if (!mp_obj_is_int(base) || !mp_obj_is_int(exponent) || !mp_obj_is_int(modulus)) {
          +  -  +  +  +  
          +  +  -  +  +  
             +  +  -  + ]
     358                 :         12 :         mp_raise_TypeError(MP_ERROR_TEXT("pow() with 3 arguments requires integers"));
     359                 :            :     } else {
     360                 :         48 :         mp_obj_t result = mp_obj_new_int_from_ull(0); // Use the _from_ull version as this forces an mpz int
     361                 :         48 :         mp_obj_int_t *res_p = (mp_obj_int_t *)MP_OBJ_TO_PTR(result);
     362                 :            : 
     363                 :         48 :         mpz_t l_temp, r_temp, m_temp;
     364                 :         48 :         mpz_t *lhs = mp_mpz_for_int(base,     &l_temp);
     365                 :         48 :         mpz_t *rhs = mp_mpz_for_int(exponent, &r_temp);
     366                 :         48 :         mpz_t *mod = mp_mpz_for_int(modulus,  &m_temp);
     367                 :            : 
     368                 :         48 :         mpz_pow3_inpl(&(res_p->mpz), lhs, rhs, mod);
     369                 :            : 
     370         [ +  + ]:         48 :         if (lhs == &l_temp) {
     371                 :         36 :             mpz_deinit(lhs);
     372                 :            :         }
     373         [ +  + ]:         48 :         if (rhs == &r_temp) {
     374                 :         32 :             mpz_deinit(rhs);
     375                 :            :         }
     376         [ +  + ]:         48 :         if (mod == &m_temp) {
     377                 :         28 :             mpz_deinit(mod);
     378                 :            :         }
     379                 :         48 :         return result;
     380                 :            :     }
     381                 :            : }
     382                 :            : #endif
     383                 :            : 
     384                 :     137728 : mp_obj_t mp_obj_new_int(mp_int_t value) {
     385         [ +  + ]:     137728 :     if (MP_SMALL_INT_FITS(value)) {
     386                 :     137724 :         return MP_OBJ_NEW_SMALL_INT(value);
     387                 :            :     }
     388                 :          4 :     return mp_obj_new_int_from_ll(value);
     389                 :            : }
     390                 :            : 
     391                 :       1425 : mp_obj_t mp_obj_new_int_from_ll(long long val) {
     392                 :       1425 :     mp_obj_int_t *o = mp_obj_int_new_mpz();
     393                 :       1425 :     mpz_set_from_ll(&o->mpz, val, true);
     394                 :       1425 :     return MP_OBJ_FROM_PTR(o);
     395                 :            : }
     396                 :            : 
     397                 :        192 : mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) {
     398                 :        192 :     mp_obj_int_t *o = mp_obj_int_new_mpz();
     399                 :        192 :     mpz_set_from_ll(&o->mpz, val, false);
     400                 :        192 :     return MP_OBJ_FROM_PTR(o);
     401                 :            : }
     402                 :            : 
     403                 :       2725 : mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
     404                 :            :     // SMALL_INT accepts only signed numbers, so make sure the input
     405                 :            :     // value fits completely in the small-int positive range.
     406         [ +  + ]:       2725 :     if ((value & ~MP_SMALL_INT_POSITIVE_MASK) == 0) {
     407                 :       2665 :         return MP_OBJ_NEW_SMALL_INT(value);
     408                 :            :     }
     409                 :         60 :     return mp_obj_new_int_from_ull(value);
     410                 :            : }
     411                 :            : 
     412                 :        957 : mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) {
     413                 :        957 :     mp_obj_int_t *o = mp_obj_int_new_mpz();
     414                 :        957 :     size_t n = mpz_set_from_str(&o->mpz, *str, len, neg, base);
     415                 :        957 :     *str += n;
     416                 :        957 :     return MP_OBJ_FROM_PTR(o);
     417                 :            : }
     418                 :            : 
     419                 :       1828 : mp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in) {
     420         [ +  + ]:       1828 :     if (mp_obj_is_small_int(self_in)) {
     421                 :       1824 :         return MP_OBJ_SMALL_INT_VALUE(self_in);
     422                 :            :     } else {
     423                 :          4 :         const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
     424                 :            :         // hash returns actual int value if it fits in mp_int_t
     425                 :          4 :         return mpz_hash(&self->mpz);
     426                 :            :     }
     427                 :            : }
     428                 :            : 
     429                 :       1792 : mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {
     430         [ +  + ]:       1792 :     if (mp_obj_is_small_int(self_in)) {
     431                 :       1786 :         return MP_OBJ_SMALL_INT_VALUE(self_in);
     432                 :            :     } else {
     433                 :          6 :         const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
     434                 :          6 :         mp_int_t value;
     435         [ +  + ]:          6 :         if (mpz_as_int_checked(&self->mpz, &value)) {
     436                 :            :             // mp_obj_int_t objects should always contain a value that is a large
     437                 :            :             // integer (if the value fits in a small-int then it should have been
     438                 :            :             // converted to a small-int object), and so this code-path should never
     439                 :            :             // be taken in normal circumstances.
     440                 :          2 :             return value;
     441                 :            :         } else {
     442                 :            :             // overflow
     443                 :          4 :             mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("overflow converting long int to machine word"));
     444                 :            :         }
     445                 :            :     }
     446                 :            : }
     447                 :            : 
     448                 :          8 : mp_uint_t mp_obj_int_get_uint_checked(mp_const_obj_t self_in) {
     449         [ +  + ]:          8 :     if (mp_obj_is_small_int(self_in)) {
     450         [ +  + ]:          4 :         if (MP_OBJ_SMALL_INT_VALUE(self_in) >= 0) {
     451                 :          2 :             return MP_OBJ_SMALL_INT_VALUE(self_in);
     452                 :            :         }
     453                 :            :     } else {
     454                 :          4 :         const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
     455                 :          4 :         mp_uint_t value;
     456         [ +  + ]:          4 :         if (mpz_as_uint_checked(&self->mpz, &value)) {
     457                 :          2 :             return value;
     458                 :            :         }
     459                 :            :     }
     460                 :            : 
     461                 :          4 :     mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("overflow converting long int to machine word"));
     462                 :            : }
     463                 :            : 
     464                 :            : #if MICROPY_PY_BUILTINS_FLOAT
     465                 :      21624 : mp_float_t mp_obj_int_as_float_impl(mp_obj_t self_in) {
     466   [ +  -  -  + ]:      21624 :     assert(mp_obj_is_exact_type(self_in, &mp_type_int));
     467                 :      21624 :     mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
     468                 :      21624 :     return mpz_as_float(&self->mpz);
     469                 :            : }
     470                 :            : #endif
     471                 :            : 
     472                 :            : #endif

Generated by: LCOV version 1.15-5-g462f71d