Skip to content

longint with arbitrary precision

Hinerk requested to merge hinerk/firmware:longint_issue into master

Micropython provides three different ways of storing long integer values:

  • MICROPY_LONGINT_IMPL_NONE isn't capable of storing long integer values
  • MICROPY_LONGINT_IMPL_LONGLONG stores a long integer within a long long datatype
  • MICROPY_LONGINT_IMPL_MPZ allows to store arbitrary sized integer values, by storing each digit individually

while the first two explanations are derived from staring at the source, the last one is actually documented within the micropython source:

from

// This mpz module implements arbitrary precision integers.
//
// The storage for each digit is defined by mpz_dig_t.  The actual number of
// bits in mpz_dig_t that are used is defined by MPZ_DIG_SIZE.  The machine must
// also provide a type that is twice as wide as mpz_dig_t, in both signed and
// unsigned versions.
//
// MPZ_DIG_SIZE can be between 4 and 8*sizeof(mpz_dig_t), but it makes most
// sense to have it as large as possible.  If MPZ_DIG_SIZE is not already
// defined then it is auto-detected below, depending on the machine.  The types
// are then set based on the value of MPZ_DIG_SIZE (although they can be freely
// changed so long as the constraints mentioned above are met).

So currently we are using the MICROPY_LONGINT_IMPL_LONGLONG implementation which results in such annoying effects like I reported in issue 125

>>> 10 ** 9 / 10
1e+08
>>> 10 ** 10 / 10
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported types for __truediv__: 'int', 'int'

>>> 10 ** 10 - 10
9999999990
>>> 10 ** 10 - 10.0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported types for __sub__: 'int', 'float'

the context of this merge request is to switch from MICROPY_LONGINT_IMPL_LONGLONG to MICROPY_LONGINT_IMPL_MPZ in order to enable arbitrary integer length

Merge request reports