Skip to content

Commit 196990b

Browse files
committed
Merge pull request adafruit#364 from pfalcon/mpz-unbreak-int-long
objint_mpz: Quick&dirty implementation of bitwise operations.
2 parents 23261f3 + 57207b8 commit 196990b

3 files changed

Lines changed: 148 additions & 7 deletions

File tree

py/mpz.c

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,69 @@ STATIC uint mpn_sub(mpz_dig_t *idig, const mpz_dig_t *jdig, uint jlen, const mpz
173173
return idig + 1 - oidig;
174174
}
175175

176+
/* computes i = j & k
177+
returns number of digits in i
178+
assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen
179+
can have i, j, k pointing to same memory
180+
*/
181+
STATIC uint mpn_and(mpz_dig_t *idig, const mpz_dig_t *jdig, uint jlen, const mpz_dig_t *kdig, uint klen) {
182+
mpz_dig_t *oidig = idig;
183+
184+
jlen -= klen;
185+
186+
for (; klen > 0; --klen, ++idig, ++jdig, ++kdig) {
187+
*idig = *jdig & *kdig;
188+
}
189+
190+
for (; jlen > 0; --jlen, ++idig) {
191+
*idig = 0;
192+
}
193+
194+
return idig - oidig;
195+
}
196+
197+
/* computes i = j | k
198+
returns number of digits in i
199+
assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen
200+
can have i, j, k pointing to same memory
201+
*/
202+
STATIC uint mpn_or(mpz_dig_t *idig, const mpz_dig_t *jdig, uint jlen, const mpz_dig_t *kdig, uint klen) {
203+
mpz_dig_t *oidig = idig;
204+
205+
jlen -= klen;
206+
207+
for (; klen > 0; --klen, ++idig, ++jdig, ++kdig) {
208+
*idig = *jdig | *kdig;
209+
}
210+
211+
for (; jlen > 0; --jlen, ++idig, ++jdig) {
212+
*idig = *jdig;
213+
}
214+
215+
return idig - oidig;
216+
}
217+
218+
/* computes i = j ^ k
219+
returns number of digits in i
220+
assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen
221+
can have i, j, k pointing to same memory
222+
*/
223+
STATIC uint mpn_xor(mpz_dig_t *idig, const mpz_dig_t *jdig, uint jlen, const mpz_dig_t *kdig, uint klen) {
224+
mpz_dig_t *oidig = idig;
225+
226+
jlen -= klen;
227+
228+
for (; klen > 0; --klen, ++idig, ++jdig, ++kdig) {
229+
*idig = *jdig ^ *kdig;
230+
}
231+
232+
for (; jlen > 0; --jlen, ++idig, ++jdig) {
233+
*idig = *jdig;
234+
}
235+
236+
return idig - oidig;
237+
}
238+
176239
/* computes i = i * d1 + d2
177240
returns number of digits in i
178241
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) {
805868
}
806869
}
807870

871+
/* computes dest = lhs & rhs
872+
can have dest, lhs, rhs the same
873+
*/
874+
void mpz_and_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) {
875+
if (mpn_cmp(lhs->dig, lhs->len, rhs->dig, rhs->len) < 0) {
876+
const mpz_t *temp = lhs;
877+
lhs = rhs;
878+
rhs = temp;
879+
}
880+
881+
if (lhs->neg == rhs->neg) {
882+
mpz_need_dig(dest, lhs->len);
883+
dest->len = mpn_and(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len);
884+
} else {
885+
mpz_need_dig(dest, lhs->len);
886+
// TODO
887+
assert(0);
888+
// dest->len = mpn_and_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len);
889+
}
890+
891+
dest->neg = lhs->neg;
892+
}
893+
894+
/* computes dest = lhs | rhs
895+
can have dest, lhs, rhs the same
896+
*/
897+
void mpz_or_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) {
898+
if (mpn_cmp(lhs->dig, lhs->len, rhs->dig, rhs->len) < 0) {
899+
const mpz_t *temp = lhs;
900+
lhs = rhs;
901+
rhs = temp;
902+
}
903+
904+
if (lhs->neg == rhs->neg) {
905+
mpz_need_dig(dest, lhs->len);
906+
dest->len = mpn_or(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len);
907+
} else {
908+
mpz_need_dig(dest, lhs->len);
909+
// TODO
910+
assert(0);
911+
// dest->len = mpn_or_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len);
912+
}
913+
914+
dest->neg = lhs->neg;
915+
}
916+
917+
/* computes dest = lhs ^ rhs
918+
can have dest, lhs, rhs the same
919+
*/
920+
void mpz_xor_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) {
921+
if (mpn_cmp(lhs->dig, lhs->len, rhs->dig, rhs->len) < 0) {
922+
const mpz_t *temp = lhs;
923+
lhs = rhs;
924+
rhs = temp;
925+
}
926+
927+
if (lhs->neg == rhs->neg) {
928+
mpz_need_dig(dest, lhs->len);
929+
dest->len = mpn_xor(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len);
930+
} else {
931+
mpz_need_dig(dest, lhs->len);
932+
// TODO
933+
assert(0);
934+
// dest->len = mpn_xor_neg(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len);
935+
}
936+
937+
dest->neg = 0;
938+
}
939+
808940
/* computes dest = lhs * rhs
809941
can have dest, lhs, rhs the same
810942
*/

py/mpz.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ void mpz_add_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
5959
void mpz_sub_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
6060
void mpz_mul_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
6161
void mpz_pow_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
62+
void mpz_and_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
63+
void mpz_or_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
64+
void mpz_xor_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
6265

6366
mpz_t *mpz_gcd(const mpz_t *z1, const mpz_t *z2);
6467
mpz_t *mpz_lcm(const mpz_t *z1, const mpz_t *z2);

py/objint_mpz.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
7878
return mp_obj_new_float(flhs / frhs);
7979
#endif
8080

81-
} else if (op <= RT_BINARY_OP_POWER) {
81+
} else if (op <= RT_BINARY_OP_INPLACE_POWER) {
8282
mp_obj_int_t *res = mp_obj_int_new_mpz();
8383

8484
switch (op) {
@@ -119,12 +119,18 @@ mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
119119
break;
120120
}
121121

122-
//case RT_BINARY_OP_AND:
123-
//case RT_BINARY_OP_INPLACE_AND:
124-
//case RT_BINARY_OP_OR:
125-
//case RT_BINARY_OP_INPLACE_OR:
126-
//case RT_BINARY_OP_XOR:
127-
//case RT_BINARY_OP_INPLACE_XOR:
122+
case RT_BINARY_OP_AND:
123+
case RT_BINARY_OP_INPLACE_AND:
124+
mpz_and_inpl(&res->mpz, zlhs, zrhs);
125+
break;
126+
case RT_BINARY_OP_OR:
127+
case RT_BINARY_OP_INPLACE_OR:
128+
mpz_or_inpl(&res->mpz, zlhs, zrhs);
129+
break;
130+
case RT_BINARY_OP_XOR:
131+
case RT_BINARY_OP_INPLACE_XOR:
132+
mpz_xor_inpl(&res->mpz, zlhs, zrhs);
133+
break;
128134

129135
case RT_BINARY_OP_LSHIFT:
130136
case RT_BINARY_OP_INPLACE_LSHIFT:

0 commit comments

Comments
 (0)