source: project/release/5/bitwise-utils/trunk/bitwise-utils.scm @ 38599

Last change on this file since 38599 was 38599, checked in by Kon Lovett, 6 months ago

add srfi-60 inspired routines

File size: 7.4 KB
Line 
1;;;; bitwise-utils.scm  -*- Scheme -*-
2;;;; Kon Lovett, Apr '20
3
4;portions
5
6;;;; "logical.scm", bit access and operations for integers for Scheme
7;;; Copyright (C) 1991, 1993, 2001, 2003, 2005 Aubrey Jaffer
8;
9;Permission to copy this software, to modify it, to redistribute it,
10;to distribute modified versions, and to use it for any purpose is
11;granted, subject to the following restrictions and understandings.
12;
13;1.  Any copy made of this software must include this copyright notice
14;in full.
15;
16;2.  I have made no warranty or representation that the operation of
17;this software will be error-free, and I am under no obligation to
18;provide any services, by way of maintenance, update, or otherwise.
19;
20;3.  In conjunction with products arising from the use of this
21;material, there shall be no use of my name in any advertising,
22;promotional, or sales literature without prior written consent in
23;each case.
24
25;;;; Issues
26;;
27
28#>
29/* Number of 1 bits */
30static unsigned int
31C_uword_bits( C_uword n )
32{
33# define TWO( c )       ( ((C_uword) 1u) << (c))
34# define MASK( c )      (((C_uword) -1) / (TWO( TWO( c ) ) + 1u))
35# define COUNT( x, c )  ((x) & MASK( c )) + (((x) >> (TWO( c ))) & MASK( c ))
36
37  if (0 == n) return (unsigned int) 0;
38
39        n = COUNT( n, 0 );
40        n = COUNT( n, 1 );
41        n = COUNT( n, 2 );
42        n = COUNT( n, 3 );
43        n = COUNT( n, 4 );
44# ifdef C_SIXTY_FOUR
45        n = COUNT( n, 5 );
46# endif
47
48        return (unsigned int) n;
49
50# undef COUNT
51# undef MASK
52# undef TWO
53}
54<#
55
56(module bitwise-utils
57
58(;export
59  arithmetic-shift-left arithmetic-shift-right
60  logical-shift-left logical-shift-right
61  bitwise-mask
62  bitwise-join
63  bitwise-split
64  bitwise-count
65  bitwise-merge
66  bitwise-nth?
67  bitwise-any?
68  bitwise-first-set
69  bitwise-reverse
70  bitwise-set-nth
71  bitwise-field bitwise-field-copy bitwise-field-reverse bitwise-field-rotate
72  integer->list list->integer)
73
74
75(import scheme)
76(import (only (chicken base) sub1 add1 fixnum? foldl cut))
77(import (chicken type))
78(import (chicken foreign))
79(import (only (chicken bitwise)
80  integer-length arithmetic-shift bit->boolean
81  bitwise-not bitwise-and bitwise-ior))
82
83;;
84
85(: arithmetic-shift-left (integer fixnum --> integer))
86(: arithmetic-shift-right (integer fixnum --> integer))
87(: logical-shift-left (integer fixnum --> integer))
88(: logical-shift-right (integer fixnum --> integer))
89(: bitwise-mask (fixnum #!optional boolean fixnum --> integer))
90(: bitwise-join (integer #!rest integer --> integer))
91(: bitwise-split (integer fixnum --> (list-of integer)))
92(: bitwise-count (integer --> fixnum))
93(: bitwise-merge (integer integer integer --> integer))
94(: bitwise-nth? (integer fixnum --> boolean))
95(: bitwise-any? (integer integer --> boolean))
96(: bitwise-first-set (integer --> fixnum))
97(: bitwise-reverse (integer fixnum --> integer))
98(: bitwise-rotate (integer fixnum fixnum --> integer))
99(: bitwise-set-nth (integer fixnum boolean --> integer))
100(: bitwise-field (integer fixnum fixnum --> integer))
101(: bitwise-field-copy (integer integer fixnum fixnum --> integer))
102(: bitwise-field-reverse (integer fixnum fixnum --> integer))
103(: bitwise-field-rotate (integer fixnum fixnum fixnum --> integer))
104(: integer->list (integer #!optional boolean --> (list-of fixnum)))
105(: list->integer (list --> integer))
106
107;observes sign - does sign extend
108(define arithmetic-shift-left arithmetic-shift)
109(define (arithmetic-shift-right n w) (arithmetic-shift n (- w)))
110
111;5 #t => +0...011111
112;5 #f => -1...100000
113(define (bitwise-mask b #!optional (on? #t))
114  (if (zero? b) 0
115    (let ((res (arithmetic-shift-left -1 b)))
116      (if on? (bitwise-not res) res) ) ) )
117
118(define (*logical-shift-right n w)
119  (bitwise-and (arithmetic-shift-right n w) (bitwise-mask (- (integer-length n) w))) )
120
121;preserves sign - doesn't sign extend
122(define logical-shift-left arithmetic-shift-left)
123(define (logical-shift-right n w)
124  (if (zero? w) n
125    (let ((res (*logical-shift-right (abs n) w)))
126      (if (negative? n) (- res) res) ) ) )
127
128(define (*bitwise-join a b)
129  (bitwise-ior (logical-shift-left a (integer-length b)) b) )
130
131;#b10 #b0000001 #b101 => #b101101
132(define (bitwise-join n . ns) (foldl (cut *bitwise-join <> <>) n ns))
133
134;babcdef 2 => ba bc de f
135;0 2 => '()
136;123 0 => '()
137(define (bitwise-split n w)
138  (if (or (zero? n) (zero? w)) `(,n)
139    (let ((neg? (negative? n)) (mask (bitwise-mask w)))
140      (let loop ((n (abs n)) (ns '()))
141        (if (zero? n) (if neg? (map - ns) ns)
142          (loop (*logical-shift-right n w) (cons (bitwise-and n mask) ns)) ) ) ) ) )
143
144(define (bitwise-abs n) (if (negative? n) (bitwise-not n) n))
145
146(define *uword-size* (foreign-type-size "C_uword"))
147
148(cond-expand
149  (64bit
150    (define uword-bitwise-count
151      (foreign-lambda* unsigned-int ((integer64 n))
152        "return( C_uword_bits( (C_uword) n ) );")) )
153  (else ;32bit
154    (define uword-bitwise-count
155      (foreign-lambda* unsigned-int ((integer32 n))
156        "return( C_uword_bits( (C_uword) n ) );")) ) )
157
158(define (bitwise-count n)
159  (let ((n (bitwise-abs n)))
160    (if (fixnum? n) (uword-bitwise-count n)
161      (foldl
162        (lambda (c i) (+ c (uword-bitwise-count i)))
163        0
164        (bitwise-split n (* 8 *uword-size*))) ) ) )
165
166(define (bitwise-merge mask n0 n1)
167  (bitwise-ior
168    (bitwise-and mask n0)
169    (bitwise-and (bitwise-not mask) n1)) )
170
171(define (bitwise-nth? index n)
172  (bit->boolean n index) )
173
174(define (bitwise-any? n1 n2)
175  (not (zero? (bitwise-and n1 n2))) )
176
177(define (bitwise-first-set n)
178  (sub1 (integer-length (bitwise-and n (- n)))) )
179
180(define (bitwise-reverse n k)
181  (do ((m (bitwise-abs n) (arithmetic-shift m -1))
182       (k (sub1 k) (sub1 k))
183       (rvs 0 (bitwise-ior (arithmetic-shift rvs 1) (bitwise-and 1 m))))
184      ((negative? k) (if (negative? n) (bitwise-not rvs) rvs))))
185
186(define (bitwise-rotate k count len)
187  (bitwise-field-rotate k count 0 len) )
188
189(define (bitwise-set-nth to index bool)
190  (if bool
191    (bitwise-ior to (arithmetic-shift 1 index))
192    (bitwise-and to (bitwise-not (arithmetic-shift 1 index))) ) )
193
194(define (bitwise-field n start end)
195  (bitwise-and
196    (bitwise-not (arithmetic-shift -1 (- end start)))
197          (arithmetic-shift-right n start)) )
198
199(define (bitwise-field-copy to from start end)
200  (bitwise-merge
201    (arithmetic-shift (bitwise-not (arithmetic-shift -1 (- end start))) start)
202    (arithmetic-shift from start)
203    to) )
204
205(define (bitwise-field-reverse n start end)
206  (let* (
207    (width (- end start))
208    (mask (bitwise-mask width))
209    (zn (bitwise-and mask (arithmetic-shift-right n start))) )
210    (bitwise-ior
211      (arithmetic-shift (bitwise-reverse zn width) start)
212            (bitwise-and (bitwise-not (arithmetic-shift mask start)) n)) ) )
213
214(define (bitwise-field-rotate n count start end)
215  (let* (
216    (width (- end start))
217    (count (modulo count width))
218    (mask (bitwise-mask width))
219    (zn (bitwise-and mask (arithmetic-shift-right n start))) )
220    (bitwise-ior
221      (arithmetic-shift
222        (bitwise-ior
223          (bitwise-and mask (arithmetic-shift zn count))
224          (arithmetic-shift zn (- count width)))
225        start)
226            (bitwise-and (bitwise-not (arithmetic-shift mask start)) n)) ) )
227
228(define (integer->list k #!optional len)
229  (if (not len)
230    (do ((k k (arithmetic-shift k -1))
231         (lst '() (cons (add1 k) lst)) )
232        ((<= k 0) lst))
233    (do ((idx (sub1 len) (sub1 idx))
234         (k k (arithmetic-shift k -1))
235         (lst '() (cons (add1 k) lst)))
236        ((negative? idx) lst)) ) )
237
238(define (list->integer bools)
239  (do ((bs bools (cdr bs))
240       (acc 0 (+ acc acc (if (car bs) 1 0))))
241      ((null? bs) acc)) )
242
243) ;bitwise-utils
Note: See TracBrowser for help on using the repository browser.