From dbd852d6a8d64dffab16722d398a149a09bfc9db Mon Sep 17 00:00:00 2001 From: Doug Currie Date: Sat, 30 Jan 2016 22:35:58 -0500 Subject: [PATCH 1/6] Complete implementation of mpz_ and or xor for negative arguments --- py/mpz.c | 189 +++++++++++++++++++++++++++----- tests/basics/int_big_and.py | 117 ++++++++++++++++++++ tests/basics/int_big_or.py | 140 +++++++++++++++++++++++ tests/basics/int_big_xor.py | 129 ++++++++++++++++++++++ tests/misc/non_compliant.py | 19 ---- tests/misc/non_compliant.py.exp | 3 - 6 files changed, 548 insertions(+), 49 deletions(-) diff --git a/py/mpz.c b/py/mpz.c index b3f8b15b60c5b..6d8a54eaeb855 100644 --- a/py/mpz.c +++ b/py/mpz.c @@ -29,9 +29,6 @@ #include "py/mpz.h" -// this is only needed for mp_not_implemented, which should eventually be removed -#include "py/runtime.h" - #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ #define DIG_SIZE (MPZ_DIG_SIZE) @@ -246,6 +243,46 @@ STATIC mp_uint_t mpn_and_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t j return idig + 1 - oidig; } +/* computes i = -(-j & -k) = ~(~(j - 1) & ~(k - 1)) + 1 = ((j - 1) | (k - 1)) + 1 + returns number of digits in i + assumes enough memory in i; assumes normalised j, k + can have i, j, k pointing to same memory +*/ +STATIC mp_uint_t mpn_and_neg2(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen, const mpz_dig_t *kdig, mp_uint_t klen) { + mpz_dig_t *oidig = idig; + mpz_dbl_dig_t carryi = 1; + mpz_dbl_dig_t carryj = 0; + mpz_dbl_dig_t carryk = 0; + + for (; jlen > 0 && klen > 0; --jlen, --klen, ++idig, ++jdig, ++kdig) { + carryk += *kdig + DIG_MASK; + carryj += *jdig + DIG_MASK; + carryi += (carryj | carryk) & DIG_MASK; + *idig = carryi & DIG_MASK; + carryk >>= DIG_SIZE; + carryj >>= DIG_SIZE; + carryi >>= DIG_SIZE; + } + + for (; jlen > 0; --jlen, ++idig, ++jdig) { + carryk += DIG_MASK; + carryj += *jdig + DIG_MASK; + carryi += (carryj | carryk) & DIG_MASK; + *idig = carryi & DIG_MASK; + carryk >>= DIG_SIZE; + carryj >>= DIG_SIZE; + carryi >>= DIG_SIZE; + } + + *idig++ = carryi; + + // remove trailing zeros + for (--idig; idig >= oidig && *idig == 0; --idig) { + } + + return idig + 1 - oidig; +} + /* computes i = j | k returns number of digits in i assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen @@ -292,6 +329,95 @@ STATIC mp_uint_t mpn_xor(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen, return idig + 1 - oidig; } +/* i = (-j) ^ (-k) = ~(j - 1) ^ ~(k - 1) = (j - 1) ^ (k - 1) + i = -(j ^ (-k)) = -(j ^ ~(k - 1)) = ~(j ^ ~(k - 1)) + 1 = (j ^ (k - 1)) + 1 + i = -((-j) ^ k) = -(~(j - 1) ^ k) = ~(~(j - 1) ^ k) + 1 = ((j - 1) ^ k) + 1 + computes general form: + i = ((j - 1 + jc) ^ (k - 1 + kc)) + ic + returns number of digits in i + assumes enough memory in i; assumes normalised j, k; assumes length j >= length k + can have i, j, k pointing to same memory +*/ +STATIC mp_uint_t mpn_xor_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen, const mpz_dig_t *kdig, mp_uint_t klen, + mpz_dbl_dig_t carryi, mpz_dbl_dig_t carryj, mpz_dbl_dig_t carryk) { + mpz_dig_t *oidig = idig; + + for (; jlen > 0 && klen > 0; --jlen, --klen, ++idig, ++jdig, ++kdig) { + carryj += *jdig + DIG_MASK; + carryk += *kdig + DIG_MASK; + carryi += (carryj ^ carryk) & DIG_MASK; + *idig = carryi & DIG_MASK; + carryk >>= DIG_SIZE; + carryj >>= DIG_SIZE; + carryi >>= DIG_SIZE; + } + + for (; jlen > 0; --jlen, ++idig, ++jdig) { + carryj += *jdig + DIG_MASK; + carryi += carryj & DIG_MASK; + *idig = carryi & DIG_MASK; + carryj >>= DIG_SIZE; + carryi >>= DIG_SIZE; + } + + if (0 != carryi) { + *idig++ = carryi; + } + + // remove trailing zeros + for (--idig; idig >= oidig && *idig == 0; --idig) { + } + + return idig + 1 - oidig; +} + +/* i = -((-j) | (-k)) = ~((~j + 1) | (~k + 1)) + 1 + i = -(j | (-k)) = -(j | (~k + 1)) = ~( j | (~k + 1)) + 1 + i = -((-j) | k) = -((~j + 1) | k) = ~((~j + 1) | k ) + 1 + computes general form: + i = ~(((j ^ jm) + jc) | ((k ^ km) + kc)) + 1 where Xm = Xc == 0 ? 0 : DIG_MASK + returns number of digits in i + assumes enough memory in i; assumes normalised j, k; assumes length j >= length k + can have i, j, k pointing to same memory +*/ +STATIC mp_uint_t mpn_or_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen, const mpz_dig_t *kdig, mp_uint_t klen, + mpz_dbl_dig_t carryj, mpz_dbl_dig_t carryk) { + mpz_dig_t *oidig = idig; + mpz_dbl_dig_t carryi = 1; + mpz_dig_t jmask = (0 == carryj) ? 0 : DIG_MASK; + mpz_dig_t kmask = (0 == carryk) ? 0 : DIG_MASK; + + for (; jlen > 0 && klen > 0; --jlen, --klen, ++idig, ++jdig, ++kdig) { + carryj += *jdig ^ jmask; + carryk += *kdig ^ kmask; + carryi += ((carryj | carryk) ^ DIG_MASK) & DIG_MASK; + *idig = carryi & DIG_MASK; + carryk >>= DIG_SIZE; + carryj >>= DIG_SIZE; + carryi >>= DIG_SIZE; + } + + for (; jlen > 0; --jlen, ++idig, ++jdig) { + carryj += *jdig ^ jmask; + carryk += kmask; + carryi += ((carryj | carryk) ^ DIG_MASK) & DIG_MASK; + *idig = carryi & DIG_MASK; + carryk >>= DIG_SIZE; + carryj >>= DIG_SIZE; + carryi >>= DIG_SIZE; + } + + if (0 != carryi) { + *idig++ = carryi; + } + + // remove trailing zeros + for (--idig; idig >= oidig && *idig == 0; --idig) { + } + + return idig + 1 - oidig; +} + /* computes i = i * d1 + d2 returns number of digits in i assumes enough memory in i; assumes normalised i; assumes dmul != 0 @@ -1098,20 +1224,22 @@ void mpz_sub_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { */ void mpz_and_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { if (lhs->neg == rhs->neg) { + // make sure lhs has the most digits + if (lhs->len < rhs->len) { + const mpz_t *temp = lhs; + lhs = rhs; + rhs = temp; + } if (lhs->neg == 0) { - // make sure lhs has the most digits - if (lhs->len < rhs->len) { - const mpz_t *temp = lhs; - lhs = rhs; - rhs = temp; - } // do the and'ing mpz_need_dig(dest, rhs->len); dest->len = mpn_and(dest->dig, lhs->dig, rhs->dig, rhs->len); dest->neg = 0; } else { - // TODO both args are negative - mp_not_implemented("bignum and with negative args"); + // do the and'ing + mpz_need_dig(dest, lhs->len + 1); // + 1 in case we negate a max int for its size + dest->len = mpn_and_neg2(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len); + dest->neg = 1; } } else { // args have different sign @@ -1132,30 +1260,31 @@ void mpz_and_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { can have dest, lhs, rhs the same */ void mpz_or_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { - if (mpn_cmp(lhs->dig, lhs->len, rhs->dig, rhs->len) < 0) { + // make sure lhs has the most digits + if (lhs->len < rhs->len) { // (mpn_cmp(lhs->dig, lhs->len, rhs->dig, rhs->len) < 0) { const mpz_t *temp = lhs; lhs = rhs; rhs = temp; } - if (lhs->neg == rhs->neg) { + if ((0 == lhs->neg) && (0 == rhs->neg)) { mpz_need_dig(dest, lhs->len); dest->len = mpn_or(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len); + dest->neg = 0; } else { - mpz_need_dig(dest, lhs->len); - // TODO - mp_not_implemented("bignum or with negative args"); -// dest->len = mpn_or_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len); + mpz_need_dig(dest, lhs->len + 1); + dest->len = mpn_or_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len, + 0 != lhs->neg, 0 != rhs->neg); + dest->neg = 1; } - - dest->neg = lhs->neg; } /* computes dest = lhs ^ rhs can have dest, lhs, rhs the same */ void mpz_xor_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { - if (mpn_cmp(lhs->dig, lhs->len, rhs->dig, rhs->len) < 0) { + // make sure lhs has the most digits + if (lhs->len < rhs->len) { // (mpn_cmp(lhs->dig, lhs->len, rhs->dig, rhs->len) < 0) { const mpz_t *temp = lhs; lhs = rhs; rhs = temp; @@ -1163,15 +1292,21 @@ void mpz_xor_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { if (lhs->neg == rhs->neg) { mpz_need_dig(dest, lhs->len); - dest->len = mpn_xor(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len); + if (lhs->neg == 0) { + dest->len = mpn_xor(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len); + } else { + dest->len = mpn_xor_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len, 0, 0, 0); + } + dest->neg = 0; } else { - mpz_need_dig(dest, lhs->len); - // TODO - mp_not_implemented("bignum xor with negative args"); -// dest->len = mpn_xor_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len); + mpz_need_dig(dest, lhs->len + 1); + if (lhs->neg == 0) { + dest->len = mpn_xor_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len, 1, 1, 0); + } else { + dest->len = mpn_xor_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len, 1, 0, 1); + } + dest->neg = 1; } - - dest->neg = 0; } /* computes dest = lhs * rhs diff --git a/tests/basics/int_big_and.py b/tests/basics/int_big_and.py index 2dabe80ecfb49..b3bba37c19245 100644 --- a/tests/basics/int_big_and.py +++ b/tests/basics/int_big_and.py @@ -26,3 +26,120 @@ print((-a) & 0xffffffffffffffffffffffffffffffff) print((-a) & 2) print((-(1 << 70)) & 2) + +# test negative on lhs and rhs +mpz = 1 << 70 +a = 123456789012345678901234567890 +print(-1 & (-a)) +print(-2 & (-a)) +print(-2345678901234567890123456789 & (-a)) +print((-a) & (-a)) +print((-a) & (-0xffffffff)) +print((-a) & (-0xffffffffffffffffffffffffffffffff)) +print((-1) & (-0xffffffffffffffffffffffffffffffff)) +print((-a) & (-2)) +print((-mpz) & (-2)) + +# test + + + +print( 97989513389222316022151446562729620153292831887555425160965597396 + & 23716683549865351578586448630079789776107310103486834795830390982) + +print( 53817081128841898634258263553430908085326601592682411889506742059 + & 37042558948907407488299113387826240429667200950043601129661240876) + +print( 26167512042587370698808974207700979337713004510730289760097826496 + & 98456276326770292376138852628141531773120376436197321310863125849) + +print( 21085380307304977067262070503651827226504797285572981274069266136 + & 15928222825828272388778130358888206480162413547887287646273147570) + +print( 40827393422334167255488276244226338235131323044408420081160772273 + & 63815443187857978125545555033672525708399848575557475462799643340) + +print( 5181013159871685724135944379095645225188360725917119022722046448 + & 59734090450462480092384049604830976376887859531148103803093112493) + +print( 283894311 + & 86526825689187217371383854139783231460931720533100376593106943447) + +print( 40019818573920230246248826511203818792007462193311949166285967147 + & 9487909752) + +# test - + + +print( -97989513389222316022151446562729620153292831887555425160965597396 + & 23716683549865351578586448630079789776107310103486834795830390982) + +print( -53817081128841898634258263553430908085326601592682411889506742059 + & 37042558948907407488299113387826240429667200950043601129661240876) + +print( -26167512042587370698808974207700979337713004510730289760097826496 + & 98456276326770292376138852628141531773120376436197321310863125849) + +print( -21085380307304977067262070503651827226504797285572981274069266136 + & 15928222825828272388778130358888206480162413547887287646273147570) + +print( -40827393422334167255488276244226338235131323044408420081160772273 + & 63815443187857978125545555033672525708399848575557475462799643340) + +print( -5181013159871685724135944379095645225188360725917119022722046448 + & 59734090450462480092384049604830976376887859531148103803093112493) + +print( -283894311 + & 86526825689187217371383854139783231460931720533100376593106943447) + +print( -40019818573920230246248826511203818792007462193311949166285967147 + & 9487909752) + +# test + - + +print( 97989513389222316022151446562729620153292831887555425160965597396 + & -23716683549865351578586448630079789776107310103486834795830390982) + +print( 53817081128841898634258263553430908085326601592682411889506742059 + & -37042558948907407488299113387826240429667200950043601129661240876) + +print( 26167512042587370698808974207700979337713004510730289760097826496 + & -98456276326770292376138852628141531773120376436197321310863125849) + +print( 21085380307304977067262070503651827226504797285572981274069266136 + & -15928222825828272388778130358888206480162413547887287646273147570) + +print( 40827393422334167255488276244226338235131323044408420081160772273 + & -63815443187857978125545555033672525708399848575557475462799643340) + +print( 5181013159871685724135944379095645225188360725917119022722046448 + & -59734090450462480092384049604830976376887859531148103803093112493) + +print( 283894311 + & -86526825689187217371383854139783231460931720533100376593106943447) + +print( 40019818573920230246248826511203818792007462193311949166285967147 + & -9487909752) + +# test - - + +print( -97989513389222316022151446562729620153292831887555425160965597396 + & -23716683549865351578586448630079789776107310103486834795830390982) + +print( -53817081128841898634258263553430908085326601592682411889506742059 + & -37042558948907407488299113387826240429667200950043601129661240876) + +print( -26167512042587370698808974207700979337713004510730289760097826496 + & -98456276326770292376138852628141531773120376436197321310863125849) + +print( -21085380307304977067262070503651827226504797285572981274069266136 + & -15928222825828272388778130358888206480162413547887287646273147570) + +print( -40827393422334167255488276244226338235131323044408420081160772273 + & -63815443187857978125545555033672525708399848575557475462799643340) + +print( -5181013159871685724135944379095645225188360725917119022722046448 + & -59734090450462480092384049604830976376887859531148103803093112493) + +print( -283894311 + & -86526825689187217371383854139783231460931720533100376593106943447) + +print( -40019818573920230246248826511203818792007462193311949166285967147 + & -9487909752) diff --git a/tests/basics/int_big_or.py b/tests/basics/int_big_or.py index a279ce742b3fc..0defd984e2a58 100644 --- a/tests/basics/int_big_or.py +++ b/tests/basics/int_big_or.py @@ -2,3 +2,143 @@ a = 0xfffffffffffffffffffffffffffff print(a | (1 << 200)) + + +# test + + + +print(0 | (1 << 80)) +print((1 << 80) | (1 << 80)) +print((1 << 80) | 0) + +a = 0xfffffffffffffffffffffffffffff +print(a | (1 << 100)) +print(a | (1 << 200)) +print(a | a == 0) +print(bool(a | a)) + +print( 97989513389222316022151446562729620153292831887555425160965597396 + | 23716683549865351578586448630079789776107310103486834795830390982) + +print( 53817081128841898634258263553430908085326601592682411889506742059 + | 37042558948907407488299113387826240429667200950043601129661240876) + +print( 26167512042587370698808974207700979337713004510730289760097826496 + | 98456276326770292376138852628141531773120376436197321310863125849) + +print( 21085380307304977067262070503651827226504797285572981274069266136 + | 15928222825828272388778130358888206480162413547887287646273147570) + +print( 40827393422334167255488276244226338235131323044408420081160772273 + | 63815443187857978125545555033672525708399848575557475462799643340) + +print( 5181013159871685724135944379095645225188360725917119022722046448 + | 59734090450462480092384049604830976376887859531148103803093112493) + +print( 283894311 + | 86526825689187217371383854139783231460931720533100376593106943447) + +print( 40019818573920230246248826511203818792007462193311949166285967147 + | 9487909752) + +# test - + + +print((-1 << 80) | (1 << 80)) +print((-1 << 80) | 0) + +print((-a) | (1 << 100)) +print((-a) | (1 << 200)) +print((-a) | a == 0) +print(bool((-a) | a)) + +print( -97989513389222316022151446562729620153292831887555425160965597396 + | 23716683549865351578586448630079789776107310103486834795830390982) + +print( -53817081128841898634258263553430908085326601592682411889506742059 + | 37042558948907407488299113387826240429667200950043601129661240876) + +print( -26167512042587370698808974207700979337713004510730289760097826496 + | 98456276326770292376138852628141531773120376436197321310863125849) + +print( -21085380307304977067262070503651827226504797285572981274069266136 + | 15928222825828272388778130358888206480162413547887287646273147570) + +print( -40827393422334167255488276244226338235131323044408420081160772273 + | 63815443187857978125545555033672525708399848575557475462799643340) + +print( -5181013159871685724135944379095645225188360725917119022722046448 + | 59734090450462480092384049604830976376887859531148103803093112493) + +print( -283894311 + | 86526825689187217371383854139783231460931720533100376593106943447) + +print( -40019818573920230246248826511203818792007462193311949166285967147 + | 9487909752) + +# test + - + +print(0 | (-1 << 80)) +print((1 << 80) | (-1 << 80)) + +print(a | (-1 << 100)) +print(a | (-1 << 200)) +print(a | (-a) == 0) +print(bool(a | (-a))) + +print( 97989513389222316022151446562729620153292831887555425160965597396 + | -23716683549865351578586448630079789776107310103486834795830390982) + +print( 53817081128841898634258263553430908085326601592682411889506742059 + | -37042558948907407488299113387826240429667200950043601129661240876) + +print( 26167512042587370698808974207700979337713004510730289760097826496 + | -98456276326770292376138852628141531773120376436197321310863125849) + +print( 21085380307304977067262070503651827226504797285572981274069266136 + | -15928222825828272388778130358888206480162413547887287646273147570) + +print( 40827393422334167255488276244226338235131323044408420081160772273 + | -63815443187857978125545555033672525708399848575557475462799643340) + +print( 5181013159871685724135944379095645225188360725917119022722046448 + | -59734090450462480092384049604830976376887859531148103803093112493) + +print( 283894311 + | -86526825689187217371383854139783231460931720533100376593106943447) + +print( 40019818573920230246248826511203818792007462193311949166285967147 + | -9487909752) + +# test - - + +print((-1 << 80) | (-1 << 80)) + +print((-a) | (-1 << 100)) +print((-a) | (-1 << 200)) +print((-a) | (-a) == 0) +print(bool((-a) | (-a))) + +print( -97989513389222316022151446562729620153292831887555425160965597396 + | -23716683549865351578586448630079789776107310103486834795830390982) + +print( -53817081128841898634258263553430908085326601592682411889506742059 + | -37042558948907407488299113387826240429667200950043601129661240876) + +print( -26167512042587370698808974207700979337713004510730289760097826496 + | -98456276326770292376138852628141531773120376436197321310863125849) + +print( -21085380307304977067262070503651827226504797285572981274069266136 + | -15928222825828272388778130358888206480162413547887287646273147570) + +print( -40827393422334167255488276244226338235131323044408420081160772273 + | -63815443187857978125545555033672525708399848575557475462799643340) + +print( -5181013159871685724135944379095645225188360725917119022722046448 + | -59734090450462480092384049604830976376887859531148103803093112493) + +print( -283894311 + | -86526825689187217371383854139783231460931720533100376593106943447) + +print( -40019818573920230246248826511203818792007462193311949166285967147 + | -9487909752) + + diff --git a/tests/basics/int_big_xor.py b/tests/basics/int_big_xor.py index 1c6278b291ca5..f14a763a4d9ce 100644 --- a/tests/basics/int_big_xor.py +++ b/tests/basics/int_big_xor.py @@ -1,3 +1,6 @@ + +# test + + + print(0 ^ (1 << 80)) print((1 << 80) ^ (1 << 80)) print((1 << 80) ^ 0) @@ -7,3 +10,129 @@ print(a ^ (1 << 200)) print(a ^ a == 0) print(bool(a ^ a)) + +print( 97989513389222316022151446562729620153292831887555425160965597396 + ^ 23716683549865351578586448630079789776107310103486834795830390982) + +print( 53817081128841898634258263553430908085326601592682411889506742059 + ^ 37042558948907407488299113387826240429667200950043601129661240876) + +print( 26167512042587370698808974207700979337713004510730289760097826496 + ^ 98456276326770292376138852628141531773120376436197321310863125849) + +print( 21085380307304977067262070503651827226504797285572981274069266136 + ^ 15928222825828272388778130358888206480162413547887287646273147570) + +print( 40827393422334167255488276244226338235131323044408420081160772273 + ^ 63815443187857978125545555033672525708399848575557475462799643340) + +print( 5181013159871685724135944379095645225188360725917119022722046448 + ^ 59734090450462480092384049604830976376887859531148103803093112493) + +print( 283894311 + ^ 86526825689187217371383854139783231460931720533100376593106943447) + +print( 40019818573920230246248826511203818792007462193311949166285967147 + ^ 9487909752) + +# test - + + +print((-1 << 80) ^ (1 << 80)) +print((-1 << 80) ^ 0) + +print((-a) ^ (1 << 100)) +print((-a) ^ (1 << 200)) +print((-a) ^ a == 0) +print(bool((-a) ^ a)) + +print( -97989513389222316022151446562729620153292831887555425160965597396 + ^ 23716683549865351578586448630079789776107310103486834795830390982) + +print( -53817081128841898634258263553430908085326601592682411889506742059 + ^ 37042558948907407488299113387826240429667200950043601129661240876) + +print( -26167512042587370698808974207700979337713004510730289760097826496 + ^ 98456276326770292376138852628141531773120376436197321310863125849) + +print( -21085380307304977067262070503651827226504797285572981274069266136 + ^ 15928222825828272388778130358888206480162413547887287646273147570) + +print( -40827393422334167255488276244226338235131323044408420081160772273 + ^ 63815443187857978125545555033672525708399848575557475462799643340) + +print( -5181013159871685724135944379095645225188360725917119022722046448 + ^ 59734090450462480092384049604830976376887859531148103803093112493) + +print( -283894311 + ^ 86526825689187217371383854139783231460931720533100376593106943447) + +print( -40019818573920230246248826511203818792007462193311949166285967147 + ^ 9487909752) + +# test + - + +print(0 ^ (-1 << 80)) +print((1 << 80) ^ (-1 << 80)) + +print(a ^ (-1 << 100)) +print(a ^ (-1 << 200)) +print(a ^ (-a) == 0) +print(bool(a ^ (-a))) + +print( 97989513389222316022151446562729620153292831887555425160965597396 + ^ -23716683549865351578586448630079789776107310103486834795830390982) + +print( 53817081128841898634258263553430908085326601592682411889506742059 + ^ -37042558948907407488299113387826240429667200950043601129661240876) + +print( 26167512042587370698808974207700979337713004510730289760097826496 + ^ -98456276326770292376138852628141531773120376436197321310863125849) + +print( 21085380307304977067262070503651827226504797285572981274069266136 + ^ -15928222825828272388778130358888206480162413547887287646273147570) + +print( 40827393422334167255488276244226338235131323044408420081160772273 + ^ -63815443187857978125545555033672525708399848575557475462799643340) + +print( 5181013159871685724135944379095645225188360725917119022722046448 + ^ -59734090450462480092384049604830976376887859531148103803093112493) + +print( 283894311 + ^ -86526825689187217371383854139783231460931720533100376593106943447) + +print( 40019818573920230246248826511203818792007462193311949166285967147 + ^ -9487909752) + +# test - - + +print((-1 << 80) ^ (-1 << 80)) + +print((-a) ^ (-1 << 100)) +print((-a) ^ (-1 << 200)) +print((-a) ^ (-a) == 0) +print(bool((-a) ^ (-a))) + +print( -97989513389222316022151446562729620153292831887555425160965597396 + ^ -23716683549865351578586448630079789776107310103486834795830390982) + +print( -53817081128841898634258263553430908085326601592682411889506742059 + ^ -37042558948907407488299113387826240429667200950043601129661240876) + +print( -26167512042587370698808974207700979337713004510730289760097826496 + ^ -98456276326770292376138852628141531773120376436197321310863125849) + +print( -21085380307304977067262070503651827226504797285572981274069266136 + ^ -15928222825828272388778130358888206480162413547887287646273147570) + +print( -40827393422334167255488276244226338235131323044408420081160772273 + ^ -63815443187857978125545555033672525708399848575557475462799643340) + +print( -5181013159871685724135944379095645225188360725917119022722046448 + ^ -59734090450462480092384049604830976376887859531148103803093112493) + +print( -283894311 + ^ -86526825689187217371383854139783231460931720533100376593106943447) + +print( -40019818573920230246248826511203818792007462193311949166285967147 + ^ -9487909752) + diff --git a/tests/misc/non_compliant.py b/tests/misc/non_compliant.py index 9c55ac2c38fd4..c760c2accda69 100644 --- a/tests/misc/non_compliant.py +++ b/tests/misc/non_compliant.py @@ -70,22 +70,3 @@ except NotImplementedError: print('NotImplementedError') -mpz = 1 << 70 - -# mpz and with both args negative -try: - -mpz & -2 -except NotImplementedError: - print('NotImplementedError') - -# mpz or with args opposite sign -try: - -mpz | 2 -except NotImplementedError: - print('NotImplementedError') - -# mpz xor with args opposite sign -try: - -mpz ^ 2 -except NotImplementedError: - print('NotImplementedError') diff --git a/tests/misc/non_compliant.py.exp b/tests/misc/non_compliant.py.exp index 5937ccb2fbf25..28b1470d7c580 100644 --- a/tests/misc/non_compliant.py.exp +++ b/tests/misc/non_compliant.py.exp @@ -9,6 +9,3 @@ NotImplementedError NotImplementedError NotImplementedError NotImplementedError -NotImplementedError -NotImplementedError -NotImplementedError From f7cdb8f1acc9b5a73952c43e3c94bfd210adeffa Mon Sep 17 00:00:00 2001 From: Doug Currie Date: Sun, 31 Jan 2016 20:57:35 -0500 Subject: [PATCH 2/6] py: code size optimizations in mpz and_neg or_neg xor_neg --- py/mpz.c | 157 ++++++++++++++++--------------------------------------- 1 file changed, 45 insertions(+), 112 deletions(-) diff --git a/py/mpz.c b/py/mpz.c index 6d8a54eaeb855..7e2b0c55924ec 100644 --- a/py/mpz.c +++ b/py/mpz.c @@ -196,18 +196,7 @@ STATIC mp_uint_t mpn_sub(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen, return idig + 1 - oidig; } -/* computes i = j & k - returns number of digits in i - assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen (jlen argument not needed) - can have i, j, k pointing to same memory -*/ -STATIC mp_uint_t mpn_and(mpz_dig_t *idig, const mpz_dig_t *jdig, const mpz_dig_t *kdig, mp_uint_t klen) { - mpz_dig_t *oidig = idig; - - for (; klen > 0; --klen, ++idig, ++jdig, ++kdig) { - *idig = *jdig & *kdig; - } - +STATIC mp_uint_t mpn_trimmed_length(mpz_dig_t *oidig, mpz_dig_t *idig) { // remove trailing zeros for (--idig; idig >= oidig && *idig == 0; --idig) { } @@ -215,25 +204,16 @@ STATIC mp_uint_t mpn_and(mpz_dig_t *idig, const mpz_dig_t *jdig, const mpz_dig_t return idig + 1 - oidig; } -/* computes i = j & -k = j & (~k + 1) +/* computes i = j & k returns number of digits in i - assumes enough memory in i; assumes normalised j, k + assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen (jlen argument not needed) can have i, j, k pointing to same memory */ -STATIC mp_uint_t mpn_and_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen, const mpz_dig_t *kdig, mp_uint_t klen) { +STATIC mp_uint_t mpn_and(mpz_dig_t *idig, const mpz_dig_t *jdig, const mpz_dig_t *kdig, mp_uint_t klen) { mpz_dig_t *oidig = idig; - mpz_dbl_dig_t carry = 1; - for (; jlen > 0 && klen > 0; --jlen, --klen, ++idig, ++jdig, ++kdig) { - carry += *kdig ^ DIG_MASK; - *idig = (*jdig & carry) & DIG_MASK; - carry >>= DIG_SIZE; - } - - for (; jlen > 0; --jlen, ++idig, ++jdig) { - carry += DIG_MASK; - *idig = (*jdig & carry) & DIG_MASK; - carry >>= DIG_SIZE; + for (; klen > 0; --klen, ++idig, ++jdig, ++kdig) { + *idig = *jdig & *kdig; } // remove trailing zeros @@ -243,44 +223,37 @@ STATIC mp_uint_t mpn_and_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t j return idig + 1 - oidig; } -/* computes i = -(-j & -k) = ~(~(j - 1) & ~(k - 1)) + 1 = ((j - 1) | (k - 1)) + 1 +/* i = -((-j) & (-k)) = ~((~j + 1) & (~k + 1)) + 1 + i = (j & (-k)) = (j & (~k + 1)) = ( j & (~k + 1)) + i = ((-j) & k) = ((~j + 1) & k) = ((~j + 1) & k ) + computes general form: + i = (im ^ (((j ^ jm) + jc) & ((k ^ km) + kc))) + ki where Xm = Xc == 0 ? 0 : DIG_MASK returns number of digits in i - assumes enough memory in i; assumes normalised j, k + assumes enough memory in i; assumes normalised j, k; assumes length j >= length k can have i, j, k pointing to same memory */ -STATIC mp_uint_t mpn_and_neg2(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen, const mpz_dig_t *kdig, mp_uint_t klen) { +STATIC mp_uint_t mpn_and_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen, const mpz_dig_t *kdig, mp_uint_t klen, + mpz_dbl_dig_t carryi, mpz_dbl_dig_t carryj, mpz_dbl_dig_t carryk) { mpz_dig_t *oidig = idig; - mpz_dbl_dig_t carryi = 1; - mpz_dbl_dig_t carryj = 0; - mpz_dbl_dig_t carryk = 0; - - for (; jlen > 0 && klen > 0; --jlen, --klen, ++idig, ++jdig, ++kdig) { - carryk += *kdig + DIG_MASK; - carryj += *jdig + DIG_MASK; - carryi += (carryj | carryk) & DIG_MASK; - *idig = carryi & DIG_MASK; - carryk >>= DIG_SIZE; - carryj >>= DIG_SIZE; - carryi >>= DIG_SIZE; - } + mpz_dig_t imask = (0 == carryi) ? 0 : DIG_MASK; + mpz_dig_t jmask = (0 == carryj) ? 0 : DIG_MASK; + mpz_dig_t kmask = (0 == carryk) ? 0 : DIG_MASK; - for (; jlen > 0; --jlen, ++idig, ++jdig) { - carryk += DIG_MASK; - carryj += *jdig + DIG_MASK; - carryi += (carryj | carryk) & DIG_MASK; + for (; jlen > 0; ++idig, ++jdig) { + carryj += *jdig ^ jmask; + carryk += (--klen <= --jlen) ? (*kdig++ ^ kmask) : kmask; + carryi += ((carryj & carryk) ^ imask) & DIG_MASK; *idig = carryi & DIG_MASK; carryk >>= DIG_SIZE; carryj >>= DIG_SIZE; carryi >>= DIG_SIZE; } - *idig++ = carryi; - - // remove trailing zeros - for (--idig; idig >= oidig && *idig == 0; --idig) { + if (0 != carryi) { + *idig++ = carryi; } - return idig + 1 - oidig; + return mpn_trimmed_length(oidig, idig); } /* computes i = j | k @@ -342,9 +315,9 @@ STATIC mp_uint_t mpn_xor_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t j mpz_dbl_dig_t carryi, mpz_dbl_dig_t carryj, mpz_dbl_dig_t carryk) { mpz_dig_t *oidig = idig; - for (; jlen > 0 && klen > 0; --jlen, --klen, ++idig, ++jdig, ++kdig) { + for (; jlen > 0; ++idig, ++jdig) { carryj += *jdig + DIG_MASK; - carryk += *kdig + DIG_MASK; + carryk += (--klen <= --jlen) ? (*kdig++ + DIG_MASK) : DIG_MASK; carryi += (carryj ^ carryk) & DIG_MASK; *idig = carryi & DIG_MASK; carryk >>= DIG_SIZE; @@ -352,23 +325,11 @@ STATIC mp_uint_t mpn_xor_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t j carryi >>= DIG_SIZE; } - for (; jlen > 0; --jlen, ++idig, ++jdig) { - carryj += *jdig + DIG_MASK; - carryi += carryj & DIG_MASK; - *idig = carryi & DIG_MASK; - carryj >>= DIG_SIZE; - carryi >>= DIG_SIZE; - } - if (0 != carryi) { *idig++ = carryi; } - // remove trailing zeros - for (--idig; idig >= oidig && *idig == 0; --idig) { - } - - return idig + 1 - oidig; + return mpn_trimmed_length(oidig, idig); } /* i = -((-j) | (-k)) = ~((~j + 1) | (~k + 1)) + 1 @@ -387,19 +348,9 @@ STATIC mp_uint_t mpn_or_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jl mpz_dig_t jmask = (0 == carryj) ? 0 : DIG_MASK; mpz_dig_t kmask = (0 == carryk) ? 0 : DIG_MASK; - for (; jlen > 0 && klen > 0; --jlen, --klen, ++idig, ++jdig, ++kdig) { + for (; jlen > 0; ++idig, ++jdig) { carryj += *jdig ^ jmask; - carryk += *kdig ^ kmask; - carryi += ((carryj | carryk) ^ DIG_MASK) & DIG_MASK; - *idig = carryi & DIG_MASK; - carryk >>= DIG_SIZE; - carryj >>= DIG_SIZE; - carryi >>= DIG_SIZE; - } - - for (; jlen > 0; --jlen, ++idig, ++jdig) { - carryj += *jdig ^ jmask; - carryk += kmask; + carryk += (--klen <= --jlen) ? (*kdig++ ^ kmask) : kmask; carryi += ((carryj | carryk) ^ DIG_MASK) & DIG_MASK; *idig = carryi & DIG_MASK; carryk >>= DIG_SIZE; @@ -411,11 +362,7 @@ STATIC mp_uint_t mpn_or_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jl *idig++ = carryi; } - // remove trailing zeros - for (--idig; idig >= oidig && *idig == 0; --idig) { - } - - return idig + 1 - oidig; + return mpn_trimmed_length(oidig, idig); } /* computes i = i * d1 + d2 @@ -1219,40 +1166,26 @@ void mpz_sub_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { } } -/* computes dest = lhs & rhs +/* computes dest = lhs | rhs can have dest, lhs, rhs the same */ void mpz_and_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { - if (lhs->neg == rhs->neg) { - // make sure lhs has the most digits - if (lhs->len < rhs->len) { - const mpz_t *temp = lhs; - lhs = rhs; - rhs = temp; - } - if (lhs->neg == 0) { - // do the and'ing - mpz_need_dig(dest, rhs->len); - dest->len = mpn_and(dest->dig, lhs->dig, rhs->dig, rhs->len); - dest->neg = 0; - } else { - // do the and'ing - mpz_need_dig(dest, lhs->len + 1); // + 1 in case we negate a max int for its size - dest->len = mpn_and_neg2(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len); - dest->neg = 1; - } + // make sure lhs has the most digits + if (lhs->len < rhs->len) { + const mpz_t *temp = lhs; + lhs = rhs; + rhs = temp; + } + + if ((0 == lhs->neg) && (0 == rhs->neg)) { + mpz_need_dig(dest, lhs->len); + dest->len = mpn_and(dest->dig, lhs->dig, rhs->dig, rhs->len); + dest->neg = 0; } else { - // args have different sign - // make sure lhs is the positive arg - if (rhs->neg == 0) { - const mpz_t *temp = lhs; - lhs = rhs; - rhs = temp; - } mpz_need_dig(dest, lhs->len + 1); - dest->len = mpn_and_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len); - assert(dest->len <= dest->alloc); - dest->neg = 0; + dest->len = mpn_and_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len, + lhs->neg == rhs->neg, 0 != lhs->neg, 0 != rhs->neg); + dest->neg = lhs->neg & rhs->neg; } } From 14b46e2196ad0e5d0a44b83954714ea1983b02d6 Mon Sep 17 00:00:00 2001 From: Doug Currie Date: Mon, 1 Feb 2016 11:41:15 -0500 Subject: [PATCH 3/6] py: save a few more __text bytes in mpz_neg_and_or_xor --- py/mpz.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/py/mpz.c b/py/mpz.c index 7e2b0c55924ec..4b8191fb8caa2 100644 --- a/py/mpz.c +++ b/py/mpz.c @@ -1217,7 +1217,7 @@ void mpz_or_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { */ void mpz_xor_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { // make sure lhs has the most digits - if (lhs->len < rhs->len) { // (mpn_cmp(lhs->dig, lhs->len, rhs->dig, rhs->len) < 0) { + if (lhs->len < rhs->len) { const mpz_t *temp = lhs; lhs = rhs; rhs = temp; @@ -1233,11 +1233,8 @@ void mpz_xor_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { dest->neg = 0; } else { mpz_need_dig(dest, lhs->len + 1); - if (lhs->neg == 0) { - dest->len = mpn_xor_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len, 1, 1, 0); - } else { - dest->len = mpn_xor_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len, 1, 0, 1); - } + dest->len = mpn_xor_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len, 1, + 0 == lhs->neg, 0 == rhs->neg); dest->neg = 1; } } From 30b3cb7703d40921fa2d7478834a50a9bc06ce00 Mon Sep 17 00:00:00 2001 From: Doug Currie Date: Mon, 1 Feb 2016 12:48:45 -0500 Subject: [PATCH 4/6] py: fix comments in py/mpz.c per code review --- py/mpz.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/py/mpz.c b/py/mpz.c index 4b8191fb8caa2..12de30edcadeb 100644 --- a/py/mpz.c +++ b/py/mpz.c @@ -227,7 +227,7 @@ STATIC mp_uint_t mpn_and(mpz_dig_t *idig, const mpz_dig_t *jdig, const mpz_dig_t i = (j & (-k)) = (j & (~k + 1)) = ( j & (~k + 1)) i = ((-j) & k) = ((~j + 1) & k) = ((~j + 1) & k ) computes general form: - i = (im ^ (((j ^ jm) + jc) & ((k ^ km) + kc))) + ki where Xm = Xc == 0 ? 0 : DIG_MASK + i = (im ^ (((j ^ jm) + jc) & ((k ^ km) + kc))) + ic where Xm = Xc == 0 ? 0 : DIG_MASK returns number of digits in i assumes enough memory in i; assumes normalised j, k; assumes length j >= length k can have i, j, k pointing to same memory @@ -1166,7 +1166,7 @@ void mpz_sub_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { } } -/* computes dest = lhs | rhs +/* computes dest = lhs & rhs can have dest, lhs, rhs the same */ void mpz_and_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { From 3ea800d56d353d8a53f3b364da1e3acae102c492 Mon Sep 17 00:00:00 2001 From: Doug Currie Date: Mon, 1 Feb 2016 13:57:45 -0500 Subject: [PATCH 5/6] py: compile time option MICROPY_MPZ_BITWISE_SPEEDIER for benchmarking --- py/mpz.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/py/mpz.c b/py/mpz.c index 12de30edcadeb..2a707704e78a4 100644 --- a/py/mpz.c +++ b/py/mpz.c @@ -204,6 +204,8 @@ STATIC mp_uint_t mpn_trimmed_length(mpz_dig_t *oidig, mpz_dig_t *idig) { return idig + 1 - oidig; } +#if MICROPY_MPZ_BITWISE_SPEEDIER + /* computes i = j & k returns number of digits in i assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen (jlen argument not needed) @@ -223,6 +225,8 @@ STATIC mp_uint_t mpn_and(mpz_dig_t *idig, const mpz_dig_t *jdig, const mpz_dig_t return idig + 1 - oidig; } +#endif + /* i = -((-j) & (-k)) = ~((~j + 1) & (~k + 1)) + 1 i = (j & (-k)) = (j & (~k + 1)) = ( j & (~k + 1)) i = ((-j) & k) = ((~j + 1) & k) = ((~j + 1) & k ) @@ -256,6 +260,8 @@ STATIC mp_uint_t mpn_and_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t j return mpn_trimmed_length(oidig, idig); } +#if MICROPY_MPZ_BITWISE_SPEEDIER + /* computes i = j | k returns number of digits in i assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen @@ -277,6 +283,10 @@ STATIC mp_uint_t mpn_or(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen, return idig - oidig; } +#endif + +#if MICROPY_MPZ_BITWISE_SPEEDIER + /* computes i = j ^ k returns number of digits in i assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen @@ -302,6 +312,8 @@ STATIC mp_uint_t mpn_xor(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen, return idig + 1 - oidig; } +#endif + /* i = (-j) ^ (-k) = ~(j - 1) ^ ~(k - 1) = (j - 1) ^ (k - 1) i = -(j ^ (-k)) = -(j ^ ~(k - 1)) = ~(j ^ ~(k - 1)) + 1 = (j ^ (k - 1)) + 1 i = -((-j) ^ k) = -(~(j - 1) ^ k) = ~(~(j - 1) ^ k) + 1 = ((j - 1) ^ k) + 1 @@ -341,6 +353,9 @@ STATIC mp_uint_t mpn_xor_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t j assumes enough memory in i; assumes normalised j, k; assumes length j >= length k can have i, j, k pointing to same memory */ + +#if MICROPY_MPZ_BITWISE_SPEEDIER + STATIC mp_uint_t mpn_or_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen, const mpz_dig_t *kdig, mp_uint_t klen, mpz_dbl_dig_t carryj, mpz_dbl_dig_t carryk) { mpz_dig_t *oidig = idig; @@ -365,6 +380,34 @@ STATIC mp_uint_t mpn_or_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jl return mpn_trimmed_length(oidig, idig); } +#else + +STATIC mp_uint_t mpn_or_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen, const mpz_dig_t *kdig, mp_uint_t klen, + mpz_dbl_dig_t carryi, mpz_dbl_dig_t carryj, mpz_dbl_dig_t carryk) { + mpz_dig_t *oidig = idig; + mpz_dig_t imask = (0 == carryi) ? 0 : DIG_MASK; + mpz_dig_t jmask = (0 == carryj) ? 0 : DIG_MASK; + mpz_dig_t kmask = (0 == carryk) ? 0 : DIG_MASK; + + for (; jlen > 0; ++idig, ++jdig) { + carryj += *jdig ^ jmask; + carryk += (--klen <= --jlen) ? (*kdig++ ^ kmask) : kmask; + carryi += ((carryj | carryk) ^ imask) & DIG_MASK; + *idig = carryi & DIG_MASK; + carryk >>= DIG_SIZE; + carryj >>= DIG_SIZE; + carryi >>= DIG_SIZE; + } + + if (0 != carryi) { + *idig++ = carryi; + } + + return mpn_trimmed_length(oidig, idig); +} + +#endif + /* computes i = i * d1 + d2 returns number of digits in i assumes enough memory in i; assumes normalised i; assumes dmul != 0 @@ -1177,6 +1220,8 @@ void mpz_and_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { rhs = temp; } +#if MICROPY_MPZ_BITWISE_SPEEDIER + if ((0 == lhs->neg) && (0 == rhs->neg)) { mpz_need_dig(dest, lhs->len); dest->len = mpn_and(dest->dig, lhs->dig, rhs->dig, rhs->len); @@ -1187,6 +1232,15 @@ void mpz_and_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { lhs->neg == rhs->neg, 0 != lhs->neg, 0 != rhs->neg); dest->neg = lhs->neg & rhs->neg; } + +#else + + mpz_need_dig(dest, lhs->len + (lhs->neg || rhs->neg)); + dest->len = mpn_and_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len, + (lhs->neg == rhs->neg) ? lhs->neg : 0, lhs->neg, rhs->neg); + dest->neg = lhs->neg & rhs->neg; + +#endif } /* computes dest = lhs | rhs @@ -1194,12 +1248,14 @@ void mpz_and_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { */ void mpz_or_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { // make sure lhs has the most digits - if (lhs->len < rhs->len) { // (mpn_cmp(lhs->dig, lhs->len, rhs->dig, rhs->len) < 0) { + if (lhs->len < rhs->len) { const mpz_t *temp = lhs; lhs = rhs; rhs = temp; } +#if MICROPY_MPZ_BITWISE_SPEEDIER + if ((0 == lhs->neg) && (0 == rhs->neg)) { mpz_need_dig(dest, lhs->len); dest->len = mpn_or(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len); @@ -1210,6 +1266,15 @@ void mpz_or_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { 0 != lhs->neg, 0 != rhs->neg); dest->neg = 1; } + +#else + + mpz_need_dig(dest, lhs->len + (lhs->neg || rhs->neg)); + dest->len = mpn_or_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len, + (lhs->neg || rhs->neg), lhs->neg, rhs->neg); + dest->neg = lhs->neg | rhs->neg; + +#endif } /* computes dest = lhs ^ rhs @@ -1223,6 +1288,8 @@ void mpz_xor_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { rhs = temp; } +#if MICROPY_MPZ_BITWISE_SPEEDIER + if (lhs->neg == rhs->neg) { mpz_need_dig(dest, lhs->len); if (lhs->neg == 0) { @@ -1237,6 +1304,15 @@ void mpz_xor_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { 0 == lhs->neg, 0 == rhs->neg); dest->neg = 1; } + +#else + + mpz_need_dig(dest, lhs->len + (lhs->neg || rhs->neg)); + dest->len = mpn_xor_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len, + (lhs->neg != rhs->neg), 0 == lhs->neg, 0 == rhs->neg); + dest->neg = lhs->neg ^ rhs->neg; + +#endif } /* computes dest = lhs * rhs From 233e47c50be1f557169ee6f82740a48104ed1a36 Mon Sep 17 00:00:00 2001 From: Doug Currie Date: Tue, 2 Feb 2016 17:09:40 -0500 Subject: [PATCH 6/6] py: rename MICROPY_MPZ_BITWISE_SPEEDIER to MICROPY_MPZ_BITWISE_FAST --- py/mpz.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/py/mpz.c b/py/mpz.c index 2a707704e78a4..bce34aa24e52e 100644 --- a/py/mpz.c +++ b/py/mpz.c @@ -204,7 +204,7 @@ STATIC mp_uint_t mpn_trimmed_length(mpz_dig_t *oidig, mpz_dig_t *idig) { return idig + 1 - oidig; } -#if MICROPY_MPZ_BITWISE_SPEEDIER +#if MICROPY_MPZ_BITWISE_FAST /* computes i = j & k returns number of digits in i @@ -260,7 +260,7 @@ STATIC mp_uint_t mpn_and_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t j return mpn_trimmed_length(oidig, idig); } -#if MICROPY_MPZ_BITWISE_SPEEDIER +#if MICROPY_MPZ_BITWISE_FAST /* computes i = j | k returns number of digits in i @@ -285,7 +285,7 @@ STATIC mp_uint_t mpn_or(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen, #endif -#if MICROPY_MPZ_BITWISE_SPEEDIER +#if MICROPY_MPZ_BITWISE_FAST /* computes i = j ^ k returns number of digits in i @@ -354,7 +354,7 @@ STATIC mp_uint_t mpn_xor_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t j can have i, j, k pointing to same memory */ -#if MICROPY_MPZ_BITWISE_SPEEDIER +#if MICROPY_MPZ_BITWISE_FAST STATIC mp_uint_t mpn_or_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen, const mpz_dig_t *kdig, mp_uint_t klen, mpz_dbl_dig_t carryj, mpz_dbl_dig_t carryk) { @@ -1220,7 +1220,7 @@ void mpz_and_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { rhs = temp; } -#if MICROPY_MPZ_BITWISE_SPEEDIER +#if MICROPY_MPZ_BITWISE_FAST if ((0 == lhs->neg) && (0 == rhs->neg)) { mpz_need_dig(dest, lhs->len); @@ -1254,7 +1254,7 @@ void mpz_or_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { rhs = temp; } -#if MICROPY_MPZ_BITWISE_SPEEDIER +#if MICROPY_MPZ_BITWISE_FAST if ((0 == lhs->neg) && (0 == rhs->neg)) { mpz_need_dig(dest, lhs->len); @@ -1288,7 +1288,7 @@ void mpz_xor_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { rhs = temp; } -#if MICROPY_MPZ_BITWISE_SPEEDIER +#if MICROPY_MPZ_BITWISE_FAST if (lhs->neg == rhs->neg) { mpz_need_dig(dest, lhs->len); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy