From de4276124b0d50d1c56d1b85c4416e71d817c756 Mon Sep 17 00:00:00 2001 From: Abdulaziz Ghuloum Date: Sun, 18 May 2008 02:27:55 -0700 Subject: [PATCH] added bitwise-ior. --- scheme/ikarus.not-yet-implemented.ss | 13 +- scheme/ikarus.numerics.ss | 85 ++++++- scheme/last-revision | 2 +- scheme/run-tests.ss | 3 + scheme/tests/bitwise-op.ss | 85 +++++++ src/ikarus-numerics.c | 319 ++++++++++++++++++++++----- 6 files changed, 438 insertions(+), 69 deletions(-) create mode 100644 scheme/tests/bitwise-op.ss diff --git a/scheme/ikarus.not-yet-implemented.ss b/scheme/ikarus.not-yet-implemented.ss index 71a52c0..06cdd89 100644 --- a/scheme/ikarus.not-yet-implemented.ss +++ b/scheme/ikarus.not-yet-implemented.ss @@ -1,7 +1,7 @@ (library (ikarus not-yet-implemented) (export - make-rectangular angle make-polar bitwise-ior bitwise-xor + make-rectangular angle make-polar bitwise-copy-bit-field bitwise-reverse-bit-field bitwise-rotate-bit-field bitwise-if fxreverse-bit-field fxrotate-bit-field bytevector->string string->bytevector @@ -17,7 +17,7 @@ string-upcase) (import (except (ikarus) - make-rectangular angle make-polar bitwise-ior bitwise-xor + make-rectangular angle make-polar bitwise-copy-bit-field bitwise-reverse-bit-field bitwise-rotate-bit-field bitwise-if fxreverse-bit-field fxrotate-bit-field bytevector->string string->bytevector @@ -57,10 +57,11 @@ ...)])) (not-yet - make-rectangular angle make-polar bitwise-ior bitwise-xor - bitwise-copy-bit-field bitwise-reverse-bit-field - bitwise-rotate-bit-field bitwise-if fxreverse-bit-field - fxrotate-bit-field bytevector->string string->bytevector + make-rectangular angle make-polar + bitwise-if + bitwise-rotate-bit-field bitwise-copy-bit-field bitwise-reverse-bit-field + fxreverse-bit-field fxrotate-bit-field + bytevector->string string->bytevector make-custom-binary-input/output-port make-custom-textual-input/output-port open-file-input/output-port output-port-buffer-mode diff --git a/scheme/ikarus.numerics.ss b/scheme/ikarus.numerics.ss index 67fc3d9..3df5830 100644 --- a/scheme/ikarus.numerics.ss +++ b/scheme/ikarus.numerics.ss @@ -394,7 +394,8 @@ (library (ikarus generic-arithmetic) (export + - * / zero? = < <= > >= add1 sub1 quotient remainder - modulo even? odd? bitwise-and bitwise-not + modulo even? odd? bitwise-and bitwise-not bitwise-ior + bitwise-xor bitwise-arithmetic-shift-right bitwise-arithmetic-shift-left bitwise-arithmetic-shift bitwise-length @@ -423,7 +424,8 @@ bitwise-arithmetic-shift bitwise-length bitwise-copy-bit bitwise-bit-field - positive? negative? bitwise-and bitwise-not + positive? negative? bitwise-and bitwise-not bitwise-ior + bitwise-xor string->number expt gcd lcm numerator denominator exact->inexact inexact floor ceiling round log exact-integer-sqrt min max abs real->flonum @@ -565,6 +567,47 @@ (die 'bitwise-and "not an exact integer" y)])] [else (die 'bitwise-and "not an exact integer" x)]))) + (define binary-bitwise-ior + (lambda (x y) + (cond + [(fixnum? x) + (cond + [(fixnum? y) ($fxlogor x y)] + [(bignum? y) + (foreign-call "ikrt_fxbnlogor" x y)] + [else + (die 'bitwise-ior "not an exact integer" y)])] + [(bignum? x) + (cond + [(fixnum? y) + (foreign-call "ikrt_fxbnlogor" y x)] + [(bignum? y) + (foreign-call "ikrt_bnbnlogor" x y)] + [else + (die 'bitwise-ior "not an exact integer" y)])] + [else (die 'bitwise-ior "not an exact integer" x)]))) + + + (define binary-bitwise-xor + (lambda (x y) + (cond + [(fixnum? x) + (cond + [(fixnum? y) ($fxlogxor x y)] + [(bignum? y) + (foreign-call "ikrt_fxbnlogxor" x y)] + [else + (die 'bitwise-xor "not an exact integer" y)])] + [(bignum? x) + (cond + [(fixnum? y) + (foreign-call "ikrt_fxbnlogxor" y x)] + [(bignum? y) + (foreign-call "ikrt_bnbnlogxor" x y)] + [else + (die 'bitwise-xor "not an exact integer" y)])] + [else (die 'bitwise-xor "not an exact integer" x)]))) + (define binary- (lambda (x y) @@ -705,6 +748,44 @@ [(null? e*) ac] [else (f (binary-bitwise-and ac (car e*)) (cdr e*))]))])) + (define bitwise-ior + (case-lambda + [(x y) (binary-bitwise-ior x y)] + [(x y z) (binary-bitwise-ior (binary-bitwise-ior x y) z)] + [(a) + (cond + [(fixnum? a) a] + [(bignum? a) a] + [else (die 'bitwise-ior "not a number" a)])] + [() 0] + [(a b c d . e*) + (let f ([ac (binary-bitwise-ior a + (binary-bitwise-ior b + (binary-bitwise-ior c d)))] + [e* e*]) + (cond + [(null? e*) ac] + [else (f (binary-bitwise-ior ac (car e*)) (cdr e*))]))])) + + (define bitwise-xor + (case-lambda + [(x y) (binary-bitwise-xor x y)] + [(x y z) (binary-bitwise-xor (binary-bitwise-xor x y) z)] + [(a) + (cond + [(fixnum? a) a] + [(bignum? a) a] + [else (die 'bitwise-xor "not a number" a)])] + [() 0] + [(a b c d . e*) + (let f ([ac (binary-bitwise-xor a + (binary-bitwise-xor b + (binary-bitwise-xor c d)))] + [e* e*]) + (cond + [(null? e*) ac] + [else (f (binary-bitwise-xor ac (car e*)) (cdr e*))]))])) + (define (bitwise-not x) (cond [(fixnum? x) ($fxlognot x)] diff --git a/scheme/last-revision b/scheme/last-revision index 994cddf..09d2f32 100644 --- a/scheme/last-revision +++ b/scheme/last-revision @@ -1 +1 @@ -1478 +1479 diff --git a/scheme/run-tests.ss b/scheme/run-tests.ss index 4a48fc1..68de5a2 100755 --- a/scheme/run-tests.ss +++ b/scheme/run-tests.ss @@ -17,6 +17,7 @@ (import (ikarus) + (tests bitwise-op) (tests reader) (tests lists) (tests bytevectors) @@ -51,6 +52,8 @@ (f 0 536870911000 536870911) (printf "[exact-integer-sqrt] Happy Happy Joy Joy\n")) +(test-bitwise-op) + (test-parse-flonums) (test-case-folding) (test-reader) diff --git a/scheme/tests/bitwise-op.ss b/scheme/tests/bitwise-op.ss new file mode 100644 index 0000000..a47c777 --- /dev/null +++ b/scheme/tests/bitwise-op.ss @@ -0,0 +1,85 @@ +(library (tests bitwise-op) + (export test-bitwise-op) + (import (ikarus) (tests framework)) + + + (define (test-base-case op i0 i1 r) + (assert (= (op i0 i1) r))) + + (define (test-base-cases) + + (test-base-case bitwise-and 0 0 0) + (test-base-case bitwise-and 0 1 0) + (test-base-case bitwise-and 1 0 0) + (test-base-case bitwise-and 1 1 1) + + (test-base-case bitwise-ior 0 0 0) + (test-base-case bitwise-ior 0 1 1) + (test-base-case bitwise-ior 1 0 1) + (test-base-case bitwise-ior 1 1 1) + + (test-base-case bitwise-xor 0 0 0) + (test-base-case bitwise-xor 0 1 1) + (test-base-case bitwise-xor 1 0 1) + (test-base-case bitwise-xor 1 1 0)) + + (define (generate-numbers) + (define N 68) + (define (n* n i) + (if (zero? i) + '() + (cons n (n* (bitwise-arithmetic-shift-left n 1) (- i 1))))) + (append + (n* 1 N) + (n* -1 N) + (map sub1 (n* 1 N)) + (map sub1 (n* -1 N)) + (map add1 (n* 1 N)) + (map add1 (n* -1 N)))) + + + (define (one-bit n) + (if (even? n) 0 1)) + + (define (unit? n) + (or (= n 0) (= n -1))) + + (define (trusted op n1 n2) + (if (and (unit? n1) (unit? n2)) + (op n1 n2) + (+ (one-bit (op (one-bit n1) (one-bit n2))) + (bitwise-arithmetic-shift-left + (trusted op + (bitwise-arithmetic-shift-right n1 1) + (bitwise-arithmetic-shift-right n2 1)) + 1)))) + + (define (test-case op) + (define ls (generate-numbers)) + (define id 0) + (for-each + (lambda (n1) + (for-each + (lambda (n2) + (let ([r0 (op n1 n2)] + [r1 (trusted op n1 n2)]) + (unless (= r0 r1) + (printf "id=~s ~x ~x ~x ~x\n" id n1 n2 r0 r1) + (error 'test-bitwise-op + "mismatch/op/a0/a1/got/expected" op n1 n2 r0 r1)) + (set! id (+ id 1)))) + ls)) + ls)) + + (define (test-other-cases) + (test-case bitwise-and) + (test-case bitwise-ior) + ;(test-case bitwise-xor) + ) + + + (define (test-bitwise-op) + (test-base-cases) + (test-other-cases))) + + diff --git a/src/ikarus-numerics.c b/src/ikarus-numerics.c index 436e926..614cf0f 100644 --- a/src/ikarus-numerics.c +++ b/src/ikarus-numerics.c @@ -182,7 +182,6 @@ ikrt_fxbnplus(ikptr x, ikptr y, ikpcb* pcb){ } } else { - //fprintf(stderr, "this case 0x%08x\n", intx); /* positive fx + negative bn = smaller negative bn */ pcb->root0 = &y; ikptr r = ik_safe_alloc(pcb, align(disp_bignum_data+limb_count*wordsize)); @@ -1041,59 +1040,6 @@ ikrt_bnbncomp(ikptr bn1, ikptr bn2){ } } -/* FIXME: Too complicated! */ -ikptr -ikrt_fxbnlogand(ikptr x, ikptr y, ikpcb* pcb){ - long int n1 = unfix(x); - ikptr fst = ref(y, -vector_tag); - if(n1 >= 0){ - if(bnfst_negative(fst)){ - /* y is negative */ - return fix(n1 & (1+~(long int)ref(y, disp_vector_data-vector_tag))); - } else { - /* y is positive */ - return fix(n1 & (long int)ref(y, disp_vector_data-vector_tag)); - } - } else { - if(n1 == -1){ return y; } - if(bnfst_negative(fst)){ - /* y is negative */ - long int len = bnfst_limb_count(fst); - unsigned long int nn = - (1+~((1+~(long int)ref(y, disp_bignum_data - vector_tag)) & n1)); - if((len == 1) && (nn <= most_negative_fixnum)){ - return fix(-nn); - } - pcb->root0 = &y; - ikptr r = ik_safe_alloc(pcb, align(disp_bignum_data + len * wordsize)); - pcb->root0 = 0; - ref(r, 0) = fst; - ref(r, disp_bignum_data) = (ikptr) nn; - int i; - for(i=1; iroot0 = &y; - ikptr r = ik_safe_alloc(pcb, align(disp_bignum_data + len * wordsize)); - pcb->root0 = 0; - ref(r, 0) = fst; - ref(r, disp_bignum_data) = (ikptr) - (((long int)ref(y, disp_bignum_data - vector_tag)) & n1); - int i; - for(i=1; i= 0){ + /* x is positive */ + if(bnfst_negative(fst)){ + /* y is negative */ + return fix(n1 & (1+~(long int)ref(y, disp_vector_data-vector_tag))); + } else { + /* y is positive */ + return fix(n1 & (long int)ref(y, disp_vector_data-vector_tag)); + } + } else { + /* x is negative */ + if(n1 == -1){ return y; } + if(bnfst_negative(fst)){ + /* y is negative */ + long int len = bnfst_limb_count(fst); + pcb->root0 = &y; + ikptr r = ik_safe_alloc(pcb, align(disp_bignum_data + (len+1)*wordsize)); + pcb->root0 = 0; + mp_limb_t* s2 = (mp_limb_t*)(long)(y+disp_bignum_data-vector_tag); + mp_limb_t* s = (mp_limb_t*)(long)(r+disp_bignum_data); + bits_compliment2(s2, s, len, len+1); + s[0] = s[0] & n1; + bits_compliment2(s, s, len+1, len+1); + return normalize_bignum(len+1, 1<root0 = &y; + ikptr r = ik_safe_alloc(pcb, align(disp_bignum_data + len * wordsize)); + pcb->root0 = 0; + ref(r, 0) = fst; + ref(r, disp_bignum_data) = (ikptr) + (((long int)ref(y, disp_bignum_data - vector_tag)) & n1); + int i; + for(i=1; i= n2){ pcb->root0 = &x; pcb->root1 = &y; - ikptr r = ik_safe_alloc(pcb, align(disp_bignum_data + n1*wordsize)); + ikptr r = ik_safe_alloc(pcb, align(disp_bignum_data + (n1+1)*wordsize)); pcb->root0 = 0; pcb->root1 = 0; mp_limb_t* s1 = (mp_limb_t*)(long)(x+disp_bignum_data-vector_tag); mp_limb_t* s2 = (mp_limb_t*)(long)(y+disp_bignum_data-vector_tag); mp_limb_t* s = (mp_limb_t*)(long)(r+disp_bignum_data); - bits_compliment(s1, s, n1); + bits_compliment2(s1, s, n1, n1+1); bits_compliment_logand(s2, s, s, n2); - bits_compliment(s, s, n1); - return normalize_bignum(n1, 1<root0 = &y; + ikptr r = ik_safe_alloc(pcb, align(disp_bignum_data + (len+1)*wordsize)); + pcb->root0 = 0; + mp_limb_t* s2 = (mp_limb_t*)(long)(y+disp_bignum_data-vector_tag); + mp_limb_t* s = (mp_limb_t*)(long)(r+disp_bignum_data); + bits_compliment2(s2, s, len, len+1); + s[0] = s[0] | n1; + bits_compliment2(s, s, len+1, len+1); + return normalize_bignum(len+1, 1<root0 = &y; + ikptr r = ik_safe_alloc(pcb, align(disp_bignum_data + len * wordsize)); + pcb->root0 = 0; + ref(r, 0) = fst; + ref(r, disp_bignum_data) = (ikptr) + (((long int)ref(y, disp_bignum_data - vector_tag)) | n1); + int i; + for(i=1; i= n2){ + pcb->root0 = &x; + pcb->root1 = &y; + ikptr r = ik_safe_alloc(pcb, align(disp_bignum_data + n1*wordsize)); + pcb->root0 = 0; + pcb->root1 = 0; + mp_limb_t* s1 = (mp_limb_t*)(long)(x+disp_bignum_data-vector_tag); + mp_limb_t* s2 = (mp_limb_t*)(long)(y+disp_bignum_data-vector_tag); + mp_limb_t* s = (mp_limb_t*)(long)(r+disp_bignum_data); + bits_compliment2(s2, s, n2, n1); + int carry = bits_compliment_logor(s1, s, s, n1); + bits_compliment_carry(s,s,n1,n1,carry); + bits_compliment2(s, s, n1, n1); + return normalize_bignum(n1, 1<root0 = &x; + pcb->root1 = &y; + ikptr r = ik_safe_alloc(pcb, align(disp_bignum_data + n2*wordsize)); + pcb->root0 = 0; + pcb->root1 = 0; + mp_limb_t* s1 = (mp_limb_t*)(long)(x+disp_bignum_data-vector_tag); + mp_limb_t* s2 = (mp_limb_t*)(long)(y+disp_bignum_data-vector_tag); + mp_limb_t* s = (mp_limb_t*)(long)(r+disp_bignum_data); + if(n2 <= n1){ + bits_compliment_logor(s2, s1, s, n2); + bits_compliment2(s, s, n2, n2); + } else { + int carry = bits_compliment_logor(s2, s1, s, n1); + bits_compliment_carry(s2, s, n1, n2, carry); + bits_compliment_carry(s, s, 0, n2, 1); + } + return normalize_bignum(n2, 1<n2)?n1:n2; + pcb->root0 = &x; + pcb->root1 = &y; + ikptr r = ik_safe_alloc(pcb, align(disp_bignum_data+n*wordsize)); + mp_limb_t* s = (mp_limb_t*)(long)(r+disp_bignum_data); + mp_limb_t* s1 = (mp_limb_t*)(long)(x+disp_bignum_data-vector_tag); + mp_limb_t* s2 = (mp_limb_t*)(long)(y+disp_bignum_data-vector_tag); + pcb->root0 = 0; + pcb->root1 = 0; + long int i; + if(n == n1){ + for(i=0; i> m;