Skip to content

Arithmetic comparison errors involving sys.maxsize #1448

Closed

Description

@pramasoul
Micro Python v1.4.4-251-g21ffa7c on 2015-08-30; PYBv1.0 with STM32F405RG
Type "help()" for more information.
>>> import sys
>>> sys.maxsize == sys.maxsize - 1 + 1 # expect True                                                           
False
>>> sys.maxsize > sys.maxsize - 1 + 1  # expect False                                                          
True

The error occurs within sys.maxsize and 2 * sys.maxsize + 1:

>>> sys.maxsize - 1 == sys.maxsize - 2 + 1 # expect True                                                       
True
>>> 2 * sys.maxsize + 1 == 2 * sys.maxsize - 1 + 1 + 1 # expect True                                           
False
>>> 2 * sys.maxsize + 2 == 2 * sys.maxsize - 1 + 1 + 2 # expect True                                           
True

Yet everywhere equivalence is expected, the string representations are equal:

>>> str(sys.maxsize) == str(sys.maxsize - 1 + 1) # expect True                                                 
True
>>> str(2 * sys.maxsize + 1) == str(2 * sys.maxsize - 1 + 1 + 1) # expect True
True

The unix build behaves the same.

Note that both stmhal/mpconfigport.h and unix/mpconfigport.h have:

#define MICROPY_LONGINT_IMPL        (MICROPY_LONGINT_IMPL_MPZ)
...
#define MICROPY_PY_SYS_MAXSIZE      (1)

which puts us in objint_mpz.c. I had no luck finding odd behavior around bit crossings using:

def test(n):
    x = 1
    for i in range(n):
        x += x+1
        if x == sys.maxsize:
            print("arithmetic == at", i+1, x, hex(x))
        if hex(x) == hex(sys.maxsize):
            print("hex() == at", i+1, x, hex(x))
        yield x-1 == x-1 - 1 + 1
        yield x   == x   - 1 + 1
        yield x+1 == x+1 - 1 + 1

On pyboard:

>>> all(test(2050))
hex() == at 30 2147483647 0x7fffffff
True

And unix:

>>> all(test(2050))
hex() == at 62 9223372036854775807 0x7fffffffffffffff
True

Cpython of course gives:

>>> all(test(2050))
arithmetic == at 62 9223372036854775807 0x7fffffffffffffff
hex() == at 62 9223372036854775807 0x7fffffffffffffff
True

Activity

  1. dpgeorge commented on Aug 31, 2015

    @dpgeorge
    Member

    Nice find! The problem is in objint_mpz.c, in the definition of mp_maxsize_obj. I think the .len field is wrong (line 61). Try making .len=2 on 64-bit unix.

  2. pramasoul commented on Aug 31, 2015

    @pramasoul
    Author

    Making .len=2 on 64-bit unix does indeed give correct behavior. What preprocessor expression should I use in place of MPZ_NUM_DIG_FOR_INT to give the correct value across platforms?

    const mp_obj_int_t mp_maxsize_obj = {
        {&mp_type_int},
        {.fixed_dig = 1, .len = MPZ_NUM_DIG_FOR_INT, .alloc = MPZ_NUM_DIG_FOR_INT, .dig = (mpz_dig_t*)maxsize_dig}                                                                                               
    };
  3. dpgeorge commented on Sep 1, 2015

    @dpgeorge
    Member

    What preprocessor expression should I use

    I don't know, it has to be worked out. Maybe the definition of MPZ_NUM_DIG_FOR_INT can be fixed.

  4. hosaka commented on Sep 15, 2015

    @hosaka
    Contributor

    I think the problem with the MPZ_NUM_DIG_FOR_INT macro was the +1 in it's definition. Removing it makes the number of digits stay at 2 for 32/64 bit unix. Let me know if it's okay to open a pull req.

    #define MPZ_NUM_DIG_FOR_INT (sizeof(mp_int_t) * 8 / MPZ_DIG_SIZE + 1)
    #define MPZ_NUM_DIG_FOR_LL (sizeof(long long) * 8 / MPZ_DIG_SIZE + 1)
  5. dpgeorge commented on Sep 15, 2015

    @dpgeorge
    Member

    Fixed in 8b4fb4f.

    @Alex-March I just beat you to it! In this case the calculation was trying to round the division up, so the correct fix is (+ MPZ_DIG_SIZE-1) before the division. Also I fixed the definition of sys.maxsize to make it more robust.

    Yes, you are always welcome to open a PR :)

  6. hosaka commented on Sep 15, 2015

    @hosaka
    Contributor

    @dpgeorge good timing, thanks!

  7. added a commit that references this issue on Jan 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions