mirror of
https://github.com/justinethier/cyclone.git
synced 2025-05-20 14:19:17 +02:00
176 lines
5.3 KiB
Scheme
176 lines
5.3 KiB
Scheme
;;; "60.scm", bit access and operations for integers for Scheme
|
|
;;; Copyright (C) 1991, 1993, 2001, 2003, 2005 Aubrey Jaffer
|
|
;;; Copyright (C) 2017 Koz Ross
|
|
;
|
|
;Permission to copy this software, to modify it, to redistribute it,
|
|
;to distribute modified versions, and to use it for any purpose is
|
|
;granted, subject to the following restrictions and understandings.
|
|
;
|
|
;1. Any copy made of this software must include this copyright notice
|
|
;in full.
|
|
;
|
|
;2. I have made no warranty or representation that the operation of
|
|
;this software will be error-free, and I am under no obligation to
|
|
;provide any services, by way of maintenance, update, or otherwise.
|
|
;
|
|
;3. In conjunction with products arising from the use of this
|
|
;material, there shall be no use of my name in any advertising,
|
|
;promotional, or sales literature without prior written consent in
|
|
;each case.
|
|
|
|
(define-c raw-logand
|
|
"(void* data, int argc, closure _, object k, object x, object y)"
|
|
"Cyc_check_int(data, x);
|
|
Cyc_check_int(data, y);
|
|
int result = ((int)unbox_number(x)) & ((int)unbox_number(y));
|
|
return_closcall1(data, k, obj_int2obj(result));")
|
|
|
|
(define (logand x . rest)
|
|
(if (null? rest)
|
|
x
|
|
(logand (raw-logand x (car rest)) (cdr rest))))
|
|
|
|
(define bitwise-and logand)
|
|
|
|
(define-c raw-logior
|
|
"(void* data, int argc, closure _, object k, object x, object y)"
|
|
"Cyc_check_int(data, x);
|
|
Cyc_check_int(data, y);
|
|
int result = ((int)unbox_number(x)) | ((int)unbox_number(y));
|
|
return_closcall1(data, k, obj_int2obj(result));")
|
|
|
|
(define (logior x . rest)
|
|
(if (null? rest)
|
|
x
|
|
(logior (raw-logior x (car rest)) (cdr rest))))
|
|
|
|
(define bitwise-ior logior)
|
|
|
|
(define-c raw-logxor
|
|
"(void* data, int argc, closure _, object k, object x, object y)"
|
|
"Cyc_check_int(data, x);
|
|
Cyc_check_int(data, y);
|
|
int result = ((int)unbox_number(x)) ^ ((int)unbox_number(y));
|
|
return_closcall1(data, k, obj_int2obj(result));")
|
|
|
|
(define (logxor x . rest)
|
|
(if (null? rest)
|
|
x
|
|
(logxor (raw-logxor x (car rest)) (cdr rest))))
|
|
|
|
(define-c lognot
|
|
"(void* data, int argc, closure _, object k, object x)"
|
|
"Cyc_check_int(data, x);
|
|
int result = ~(((int)unbox_number(x)));
|
|
return_closcall1(data, k, obj_int2obj(result));")
|
|
|
|
(define bitwise-not lognot)
|
|
|
|
(define-c bitwise-if
|
|
"(void* data, int argc, closure _, object k,
|
|
object mask, object n0, object n1)"
|
|
"Cyc_check_int(data, mask);
|
|
Cyc_check_int(data, n0);
|
|
Cyc_check_int(data, n1);
|
|
int m = unbox_number(mask);
|
|
int result = (m & ((int)unbox_number(n0))) | ((~m) & ((int)unbox_number(n1)));
|
|
return_closcall1(data, k, obj_int2obj(result));")
|
|
|
|
(define bitwise-merge bitwise-if)
|
|
|
|
(define (logtest n1 n2)
|
|
(not (zero? (logand n1 n2))))
|
|
|
|
(define (logcount n)
|
|
(define lookup #u8(0 1 1 2 1 2 2 3 1 2 2 3 2 3 3 4))
|
|
(define (logcount-rec n tot)
|
|
(if (zero? n)
|
|
tot
|
|
(logcount-rec (quotient n 16)
|
|
(+ (bytevector-u8-ref lookup (modulo n 16)) tot))))
|
|
(cond
|
|
((negative? n) (logcount-rec (lognot n) 0))
|
|
((positive? n) (logcount-rec n 0))
|
|
(else 0)))
|
|
|
|
(define bit-count logcount)
|
|
|
|
(define (integer-length x)
|
|
(exact (ceiling (log x 2))))
|
|
|
|
(define (log2-binary-factors n)
|
|
(- (integer-length (logand n (- n))) 1))
|
|
|
|
(define first-set-bit log2-binary-factors)
|
|
|
|
(define (logbit? index n)
|
|
(logtest (expt 2 index) n))
|
|
|
|
(define bit-set? logbit?)
|
|
|
|
(define (copy-bit index to bool)
|
|
(if bool
|
|
(logior to (ash 1 index))
|
|
(logand to (lognot (ash 1 index)))))
|
|
|
|
(define (bit-field n start end)
|
|
(logand (lognot (ash -1 (- end start)))
|
|
(ash n (- start))))
|
|
|
|
(define (copy-bit-field to from start end)
|
|
(bitwise-if (ash (lognot (ash -1 (- end start))) start)
|
|
(ash from start)
|
|
to))
|
|
|
|
(define-c ash
|
|
"(void* data, int argc, closure _, object k, object n, object count)"
|
|
"Cyc_check_int(data, n);
|
|
Cyc_check_int(data, count);
|
|
int x = unbox_number(n);
|
|
int y = unbox_number(count);
|
|
int result = (y < 0) ? (x >> y) : (x << y);
|
|
return_closcall1(data, k, obj_int2obj(result));")
|
|
|
|
(define arithmetic-shift ash)
|
|
|
|
(define (rotate-bit-field n count start end)
|
|
(define width (- end start))
|
|
(set! count (modulo count width))
|
|
(let ((mask (lognot (ash -1 width))))
|
|
(define zn (logand mask (ash n (- start))))
|
|
(logior (ash
|
|
(logior (logand mask (ash zn count))
|
|
(ash zn (- count width)))
|
|
start)
|
|
(logand (lognot (ash mask start)) n))))
|
|
|
|
(define (bit-reverse k n)
|
|
(do ((m (if (negative? n) (lognot n) n) (ash m -1))
|
|
(k (- k 1) (- k 1))
|
|
(rvs 0 (logior (ash rvs 1) (logand 1 m))))
|
|
((negative? k) (if (negative? n) (lognot rvs) rvs))))
|
|
|
|
(define (reverse-bit-field n start end)
|
|
(define width (- end start))
|
|
(let ((mask (lognot (ash -1 width))))
|
|
(define zn (logand mask (arithmetic-shift n (- start))))
|
|
(logior (arithmetic-shift (bit-reverse width zn) start)
|
|
(logand (lognot (ash mask start)) n))))
|
|
|
|
(define (integer->list k . len)
|
|
(if (null? len)
|
|
(do ((k k (ash k -1))
|
|
(lst '() (cons (odd? k) lst)))
|
|
((<= k 0) lst))
|
|
(do ((idx (- (car len) 1) (- idx 1))
|
|
(k k (ash k -1))
|
|
(lst '() (cons (odd? k) lst)))
|
|
((negative? idx) lst))))
|
|
|
|
(define (list->integer bools)
|
|
(do ((bs bools (cdr bs))
|
|
(acc 0 (+ acc acc (if (car bs) 1 0))))
|
|
((null? bs) acc)))
|
|
|
|
(define (booleans->integer . bools)
|
|
(list->integer bools))
|