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:
parent
fd232c3ef7
commit
57207b8818
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;
|
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
|
/* computes i = i * d1 + d2
|
||||||
returns number of digits in i
|
returns number of digits in i
|
||||||
assumes enough memory in i; assumes normalised i; assumes dmul != 0
|
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
|
/* computes dest = lhs * rhs
|
||||||
can have dest, lhs, rhs the same
|
can have dest, lhs, rhs the same
|
||||||
*/
|
*/
|
||||||
|
|
3
py/mpz.h
3
py/mpz.h
|
@ -59,6 +59,9 @@ void mpz_add_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
|
||||||
void mpz_sub_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
|
void mpz_sub_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
|
||||||
void mpz_mul_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
|
void mpz_mul_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
|
||||||
void mpz_pow_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
|
void mpz_pow_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);
|
||||||
|
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);
|
||||||
|
|
||||||
mpz_t *mpz_gcd(const mpz_t *z1, const mpz_t *z2);
|
mpz_t *mpz_gcd(const mpz_t *z1, const mpz_t *z2);
|
||||||
mpz_t *mpz_lcm(const mpz_t *z1, const mpz_t *z2);
|
mpz_t *mpz_lcm(const mpz_t *z1, const mpz_t *z2);
|
||||||
|
|
|
@ -78,7 +78,7 @@ mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
||||||
return mp_obj_new_float(flhs / frhs);
|
return mp_obj_new_float(flhs / frhs);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} else if (op <= RT_BINARY_OP_POWER) {
|
} else if (op <= RT_BINARY_OP_INPLACE_POWER) {
|
||||||
mp_obj_int_t *res = mp_obj_int_new_mpz();
|
mp_obj_int_t *res = mp_obj_int_new_mpz();
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
|
@ -119,12 +119,18 @@ mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//case RT_BINARY_OP_AND:
|
case RT_BINARY_OP_AND:
|
||||||
//case RT_BINARY_OP_INPLACE_AND:
|
case RT_BINARY_OP_INPLACE_AND:
|
||||||
//case RT_BINARY_OP_OR:
|
mpz_and_inpl(&res->mpz, zlhs, zrhs);
|
||||||
//case RT_BINARY_OP_INPLACE_OR:
|
break;
|
||||||
//case RT_BINARY_OP_XOR:
|
case RT_BINARY_OP_OR:
|
||||||
//case RT_BINARY_OP_INPLACE_XOR:
|
case RT_BINARY_OP_INPLACE_OR:
|
||||||
|
mpz_or_inpl(&res->mpz, zlhs, zrhs);
|
||||||
|
break;
|
||||||
|
case RT_BINARY_OP_XOR:
|
||||||
|
case RT_BINARY_OP_INPLACE_XOR:
|
||||||
|
mpz_xor_inpl(&res->mpz, zlhs, zrhs);
|
||||||
|
break;
|
||||||
|
|
||||||
case RT_BINARY_OP_LSHIFT:
|
case RT_BINARY_OP_LSHIFT:
|
||||||
case RT_BINARY_OP_INPLACE_LSHIFT:
|
case RT_BINARY_OP_INPLACE_LSHIFT:
|
||||||
|
|
Loading…
Reference in New Issue