aboutsummaryrefslogtreecommitdiff
path: root/py/mpz.c
AgeCommit message (Collapse)Author
2021-12-21py/mpz: Fix bugs with bitwise of -0 by ensuring all 0's are positive.Damien George
This commit makes sure that the value zero is always encoded in an mpz_t as neg=0 and len=0 (previously it was just len=0). This invariant is needed for some of the bitwise operations that operate on negative numbers, because they cannot handle -0. For example (-((1<<100)-(1<<100)))|1 was being computed as -65535, instead of 1. Fixes issue #8042. Signed-off-by: Damien George <damien@micropython.org>
2021-06-24all: Fix signed shifts and NULL access errors from -fsanitize=undefined.Jeff Epler
Fixes the following (the line numbers match commit 0e87459e2bfd07): ../../extmod/crypto-algorithms/sha256.c:49:19: runtime error: left shif... ../../extmod/moduasyncio.c:106:35: runtime error: member access within ... ../../py/binary.c:210:13: runtime error: left shift of negative value -... ../../py/mpz.c:744:16: runtime error: negation of -9223372036854775808 ... ../../py/objint.c:109:22: runtime error: left shift of 1 by 31 places c... ../../py/objint_mpz.c:374:9: runtime error: left shift of 4611686018427... ../../py/objint_mpz.c:374:9: runtime error: left shift of negative valu... ../../py/parsenum.c:106:14: runtime error: left shift of 46116860184273... ../../py/runtime.c:395:33: runtime error: left shift of negative value ... ../../py/showbc.c:177:28: runtime error: left shift of negative value -... ../../py/vm.c:321:36: runtime error: left shift of negative value -1``` Testing was done on an amd64 Debian Buster system using gcc-8.3 and these settings: CFLAGS += -g3 -Og -fsanitize=undefined LDFLAGS += -fsanitize=undefined The introduced TASK_PAIRHEAP macro's conditional (x ? &x->i : NULL) assembles (under amd64 gcc 8.3 -Os) to the same as &x->i, since i is the initial field of the struct. However, for the purposes of undefined behavior analysis the conditional is needed. Signed-off-by: Jeff Epler <jepler@gmail.com>
2021-02-08py/mpz: Fix overflow of borrow in mpn_div.Damien George
For certain operands to mpn_div, the existing code path for `DIG_SIZE == MPZ_DBL_DIG_SIZE / 2` had a bug in it where borrow could still overflow in the `(x >= *n || *n - x <= borrow)` branch, ie `borrow + x - (mpz_dbl_dig_t)*n` overflows the borrow variable. In such cases the subsequent right-shift of borrow would not bring in the overflow bit, leading to an error in the result. An example division that had overflow when MPZ_DIG_SIZE = 16 is `(2 ** 48 - 1) ** 2 // (2 ** 48 - 1)`. This is fixed in this commit by simplifying the code and handling the low digits of borrow first, and then the upper bits (to shift down) separately. There is no longer a distinction between `DIG_SIZE < MPZ_DBL_DIG_SIZE / 2` and `DIG_SIZE == MPZ_DBL_DIG_SIZE / 2`. This commit also simplifies the second part of the calculation so that borrow does not need to be negated (instead the code just works knowing that borrow is negative and using + instead of - in calculations involving borrow). Fixes #6777. Signed-off-by: Damien George <damien@micropython.org>
2021-02-04py: Rename WORD_MSBIT_HIGH to MP_OBJ_WORD_MSBIT_HIGH.Damien George
To make it clear it is for mp_obj_t/mp_uint_t "word" types, and to prefix this macro with MP_. Signed-off-by: Damien George <damien@micropython.org>
2020-11-11py/mpz: Do sign extension in mpz_as_bytes for negative values.Damien George
Signed-off-by: Damien George <damien@micropython.org>
2020-04-23all: Format code to add space after C++-style comment start.stijn
Note: the uncrustify configuration is explicitly set to 'add' instead of 'force' in order not to alter the comments which use extra spaces after // as a means of indenting text for clarity.
2020-02-28all: Reformat C and Python source code with tools/codeformat.py.Damien George
This is run with uncrustify 0.70.1, and black 19.10b0.
2020-02-18py: Factor out definition of mp_float_union_t to one location.Damien George
2018-05-21py/mpz: Avoid undefined behavior at integer overflow in mpz_hash.Jeff Epler
Before this, ubsan would detect a problem when executing hash(006699999999999999999999999999999999999999999999999999999999999999999999) ../../py/mpz.c:1539:20: runtime error: left shift of 1067371580458 by 32 places cannot be represented in type 'mp_int_t' (aka 'long') When the overflow does occur it now happens as defined by the rules of unsigned arithmetic.
2018-02-25py/mpz: In mpz_clone, remove unused check for NULL dig.Damien George
This path for src->deg==NULL is never used because mpz_clone() is always called with an argument that has a non-zero integer value, and hence has some digits allocated to it (mpz_clone() is a static function private to mpz.c all callers of this function first check if the integer value is zero and if so take a special-case path, bypassing the call to mpz_clone()). There is some unused and commented-out functions that may actually pass a zero-valued mpz to mpz_clone(), so some TODOs are added to these function in case they are needed in the future.
2017-12-29py/mpz: In mpz_as_str_inpl, convert always-false checks to assertions.Damien George
There are two checks that are always false so can be converted to (negated) assertions to save code space and execution time. They are: 1. The check of the str parameter, which is required to be non-NULL as per the original comment that it has enough space in it as calculated by mp_int_format_size. And for all uses of this function str is indeed non-NULL. 2. The check of the base parameter, which is already required to be between 2 and 16 (inclusive) via the assertion in mp_int_format_size.
2017-12-29py/mpz: Simplify handling of borrow and quo adjustment in mpn_div.Damien George
The motivation behind this patch is to remove unreachable code in mpn_div. This unreachable code was added some time ago in 9a21d2e070c9ee0ef2c003f3a668e635c6ae4401, when a loop in mpn_div was copied and adjusted to work when mpz_dig_t was exactly half of the size of mpz_dbl_dig_t (a common case). The loop was copied correctly but it wasn't noticed at the time that the final part of the calculation of num-quo*den could be optimised, and hence unreachable code was left for a case that never occurred. The observation for the optimisation is that the initial value of quo in mpn_div is either exact or too large (never too small), and therefore the subtraction of quo*den from num may subtract exactly enough or too much (but never too little). Using this observation the part of the algorithm that handles the borrow value can be simplified, and most importantly this eliminates the unreachable code. The new code has been tested with DIG_SIZE=3 and DIG_SIZE=4 by dividing all possible combinations of non-negative integers with between 0 and 3 (inclusive) mpz digits.
2017-12-19py/mpz: Apply a small code-size optimisation.Damien George
2017-12-19py/mpz: Fix pow3 function so it handles the case when 3rd arg is 1.Damien George
In this case the result should always be 0, even if 2nd arg is 0.
2017-07-31all: Use the name MicroPython consistently in commentsAlexander Steffen
There were several different spellings of MicroPython present in comments, when there should be only one.
2017-07-25py: Implement raising a big-int to a negative power.Damien George
Before this patch raising a big-int to a negative power would just return 0. Now it returns a floating-point number with the correct value.
2017-07-25py/mpz: Make mpz_is_zero() an inline function.Damien George
It's more efficient as an inline function, and saves code size.
2017-04-25py/mpz: In mpn_sub, use existing function to remove trailing zeros.Damien George
2017-04-25py/mpz: Strip trailing zeros from mpz value when set from bytes.Damien George
2017-02-16py/mpz: Change type of "base" args from mp_uint_t to unsigned int.Damien George
2017-02-16py/mpz: Remove obsolete declaration of mpz_as_str_size.Damien George
2017-02-16py/mpz: Convert mp_uint_t to size_t where appropriate.Damien George
2017-02-02py: Added optimised support for 3-argument calls to builtin.pow()Nicko van Someren
Updated modbuiltin.c to add conditional support for 3-arg calls to pow() using MICROPY_PY_BUILTINS_POW3 config parameter. Added support in objint_mpz.c for for optimised implementation.
2017-01-21py/mpz: Implement mpz_set_from_bytes() as a foundation for int.from_bytes().Paul Sokolovsky
2016-12-28py/mpz: Fix assertion in mpz_set_from_str which checks value of base.Damien George
2016-12-14py/mpz: Remove unreachable code in mpn_or_neg functions.Damien George
2016-10-31py: fix null pointer dereference in mpz.c, fix missing va_end in warning.cPavol Rusnak
2016-10-11py: Factor duplicated function to calculate size of formatted int.Damien George
2016-10-11py/mpz: Use assert to verify mpz does not have a fixed digit buffer.Damien George
2016-10-11py/mpz: In divmod, replace check for rhs!=0 with assert.Damien George
The check for division by zero is made by the caller of this function.
2016-05-09py/mpz: Fix mpn_div so that it doesn't modify memory of denominator.Damien George
Previous to this patch bignum division and modulo would temporarily modify the RHS argument to the operation (eg x/y would modify y), but on return the RHS would be restored to its original value. This is not allowed because arguments to binary operations are const, and in particular might live in ROM. The modification was to normalise the arg (and then unnormalise before returning), and this patch makes it so the normalisation is done on the fly and the arg is now accessed as read-only. This change doesn't increase the order complexity of the operation, and actually reduces code size.
2016-05-08py/mpz: Do Python style division/modulo within bignum divmod routine.Damien George
This patch consolidates the Python logic for division/modulo to one place within the bignum code.
2016-05-08py/mpz: Fix bug with overflowing C-shift in division routine.Damien George
When DIG_SIZE=32, a uint32_t is used to store limbs, and no normalisation is needed because the MSB is already set, then there will be left and right shifts (in C) by 32 of a 32-bit variable, leading to undefined behaviour. This patch fixes this bug.
2016-02-03py/mpz: Add commented-out mpz_pow3_inpl function, to compute (x**y)%z.Damien George
This function computes (x**y)%z in an efficient way. For large arguments this operation is otherwise not computable by doing x**y and then %z. It's currently not used, but is added in case it's useful one day.
2016-02-03py/mpz: Complete implementation of mpz_{and,or,xor} for negative args.Doug Currie
For these 3 bitwise operations there are now fast functions for positive-only arguments, and general functions for arbitrary sign arguments (the fast functions are the existing implementation). By default the fast functions are not used (to save space) and instead the general functions are used for all operations. Enable MICROPY_OPT_MPZ_BITWISE to use the fast functions for positive arguments.
2016-01-08py/mpz: Fix conversion of float to mpz so it works on big endian archs.Damien George
2015-11-22py/mpz: Normalize (remove leading zeros) xor operation result.Paul Sokolovsky
2015-10-01py/mpz: Fix bignum anding of large negative with smaller positive int.Damien George
2015-10-01py/mpz: Force rhs of mpz_shl_inpl/mpz_shr_inpl to be unsigned.Damien George
Python semantics are that rhs of shift must be non-negative, so there's no need to handle negative values in the underlying mpz implementation.
2015-10-01py/mpz: Raise NotImplError instead of failing assertion.Damien George
2015-04-25py: Fix handling of negative numbers in struct.pack of q/Q.Damien George
2015-04-25py: Support conversion of bignum to bytes.Damien George
This gets int.to_bytes working for bignum, and also struct.pack with 'q' and 'Q' args on 32-bit machines. Addresses issue #1155.
2015-04-22py/mpz.c: Fix bug with shl not truncating zero digits correctly.Damien George
2015-04-09py: Adjust some spaces in code style/format, purely for consistency.Damien George
2015-03-12py: Make some mpz functions static and remove unused ones.Damien George
2015-03-02py: Clean up and comment out unused functions in mpz.Damien George
2015-01-27py: Fix comparison of minus-zero long int.Damien George
2015-01-24py: Fix issue in mpz_set_from_float() when mp_int_t is larger than floatDavid Steinberg
2015-01-24py: Move mp_float_t related defines to misc.hDavid Steinberg
2015-01-20py, unix: Allow to compile with -Wunused-parameter.Damien George
See issue #699.