mirror of
https://github.com/micropython/micropython.git
synced 2026-01-06 12:10:13 +01:00
objint_mpz: Quick&dirty implementation of bitwise operations.
Made solely to unbreak int-long.py test which in turn uncovered thinko with implementation of inplace ops. On mpz level, bitwise ops implemented only for same-sign numbers, and are not efficient (unconditional calling of mpn_cmp() is apparently superfluous).
This commit is contained in:
132
py/mpz.c
132
py/mpz.c
@@ -173,6 +173,69 @@ STATIC uint mpn_sub(mpz_dig_t *idig, const mpz_dig_t *jdig, uint jlen, const mpz
|
||||
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
|
||||
can have i, j, k pointing to same memory
|
||||
*/
|
||||
STATIC uint mpn_and(mpz_dig_t *idig, const mpz_dig_t *jdig, uint jlen, const mpz_dig_t *kdig, uint klen) {
|
||||
mpz_dig_t *oidig = idig;
|
||||
|
||||
jlen -= klen;
|
||||
|
||||
for (; klen > 0; --klen, ++idig, ++jdig, ++kdig) {
|
||||
*idig = *jdig & *kdig;
|
||||
}
|
||||
|
||||
for (; jlen > 0; --jlen, ++idig) {
|
||||
*idig = 0;
|
||||
}
|
||||
|
||||
return idig - oidig;
|
||||
}
|
||||
|
||||
/* computes i = j | k
|
||||
returns number of digits in i
|
||||
assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen
|
||||
can have i, j, k pointing to same memory
|
||||
*/
|
||||
STATIC uint mpn_or(mpz_dig_t *idig, const mpz_dig_t *jdig, uint jlen, const mpz_dig_t *kdig, uint klen) {
|
||||
mpz_dig_t *oidig = idig;
|
||||
|
||||
jlen -= klen;
|
||||
|
||||
for (; klen > 0; --klen, ++idig, ++jdig, ++kdig) {
|
||||
*idig = *jdig | *kdig;
|
||||
}
|
||||
|
||||
for (; jlen > 0; --jlen, ++idig, ++jdig) {
|
||||
*idig = *jdig;
|
||||
}
|
||||
|
||||
return idig - oidig;
|
||||
}
|
||||
|
||||
/* computes i = j ^ k
|
||||
returns number of digits in i
|
||||
assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen
|
||||
can have i, j, k pointing to same memory
|
||||
*/
|
||||
STATIC uint mpn_xor(mpz_dig_t *idig, const mpz_dig_t *jdig, uint jlen, const mpz_dig_t *kdig, uint klen) {
|
||||
mpz_dig_t *oidig = idig;
|
||||
|
||||
jlen -= klen;
|
||||
|
||||
for (; klen > 0; --klen, ++idig, ++jdig, ++kdig) {
|
||||
*idig = *jdig ^ *kdig;
|
||||
}
|
||||
|
||||
for (; jlen > 0; --jlen, ++idig, ++jdig) {
|
||||
*idig = *jdig;
|
||||
}
|
||||
|
||||
return idig - oidig;
|
||||
}
|
||||
|
||||
/* computes i = i * d1 + d2
|
||||
returns number of digits in i
|
||||
assumes enough memory in i; assumes normalised i; assumes dmul != 0
|
||||
@@ -805,6 +868,75 @@ void mpz_sub_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *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 (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) {
|
||||
mpz_need_dig(dest, lhs->len);
|
||||
dest->len = mpn_and(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len);
|
||||
} else {
|
||||
mpz_need_dig(dest, lhs->len);
|
||||
// TODO
|
||||
assert(0);
|
||||
// dest->len = mpn_and_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len);
|
||||
}
|
||||
|
||||
dest->neg = lhs->neg;
|
||||
}
|
||||
|
||||
/* computes dest = lhs | 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) {
|
||||
const mpz_t *temp = lhs;
|
||||
lhs = rhs;
|
||||
rhs = temp;
|
||||
}
|
||||
|
||||
if (lhs->neg == rhs->neg) {
|
||||
mpz_need_dig(dest, lhs->len);
|
||||
dest->len = mpn_or(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len);
|
||||
} else {
|
||||
mpz_need_dig(dest, lhs->len);
|
||||
// TODO
|
||||
assert(0);
|
||||
// dest->len = mpn_or_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len);
|
||||
}
|
||||
|
||||
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) {
|
||||
const mpz_t *temp = lhs;
|
||||
lhs = rhs;
|
||||
rhs = temp;
|
||||
}
|
||||
|
||||
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);
|
||||
} else {
|
||||
mpz_need_dig(dest, lhs->len);
|
||||
// TODO
|
||||
assert(0);
|
||||
// dest->len = mpn_xor_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len);
|
||||
}
|
||||
|
||||
dest->neg = 0;
|
||||
}
|
||||
|
||||
/* computes dest = lhs * rhs
|
||||
can have dest, lhs, rhs the same
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user