How to get a ll out of an objint (inverse of mp_obj_new_int_from_ll)

C programming, build, interpreter/VM.
Target audience: MicroPython Developers.
Post Reply
BramPeeters
Posts: 49
Joined: Wed Jan 31, 2018 3:10 pm

How to get a ll out of an objint (inverse of mp_obj_new_int_from_ll)

Post by BramPeeters » Thu Sep 27, 2018 5:04 pm

Hi,

After creating an objint with mp_obj_new_int_from_ll, is there a way to get the long long out of there afterwards?
At the moment I am only seeing the mp_int_t mp_obj_get_int(mp_const_obj_t arg) function, but that returns an mp_int_t which is not suppose to have the long long size.

Is mp_obj_int_to_bytes_impl intended for that, with a pointer to a 'long long' as buffer argument ?
Or will this be some internal representation since i am using MICROPY_LONGINT_IMPL_MPZ (not really familiar with how this stores large numbers)

Thanks
Bram

stijn
Posts: 350
Joined: Thu Apr 24, 2014 9:13 am

Re: How to get a ll out of an objint (inverse of mp_obj_new_int_from_ll)

Post by stijn » Thu Sep 27, 2018 6:33 pm

Don't have time to check all my code but this should get you started; as far as I know it depends on sizeof(long long) and on whether you're building as 32bit or 64bit. For instance in a 64bit build where sizeof(long long) is the same as sizeof(mp_int_t) you can just use mp_obj_get_int. But for a 32bit build where sizeof(long long) is 8, I apparently also found no built-in way and ended up with this at one point (note this works for signed as well, just needs casting):

Code: Select all

    //mpz -> 64bit integer for 32bit builds
    inline std::uint64_t mpz_to_64bit_int( const mp_obj_int_t* arg, bool is_signed )
    {
      static_assert( MPZ_DIG_SIZE == 16, "Expected MPZ_DIG_SIZE == 16" );

      //see mpz_as_int_checked
      const std::uint64_t maxCalcThreshold = is_signed ? 140737488355327 : 281474976710655;

      auto i = &arg->mpz;
      if( !is_signed && i->neg )
        RaiseTypeException( "Source integer must be unsigned" );

      auto d = i->dig + i->len;
      std::uint64_t val = 0;

      while( d-- > i->dig )
      {
        if( val > maxCalcThreshold )
          RaiseOverflowException( "Value too large for 64bit integer" );
        val = ( val << MPZ_DIG_SIZE ) | *d;
      }

#ifdef _MSC_VER
  #pragma warning( disable : 4146 )
#endif
      if( i->neg )
        val = -val;
#ifdef _MSC_VER
  #pragma warning( default : 4146 )
#endif

      return val;
    }
 

BramPeeters
Posts: 49
Joined: Wed Jan 31, 2018 3:10 pm

Re: How to get a ll out of an objint (inverse of mp_obj_new_int_from_ll)

Post by BramPeeters » Thu Sep 27, 2018 7:21 pm

My int's are 32 bit and long long's 64 bit, so thank you very much !

Post Reply