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

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

fix bitwise-count (remove wrong quick path)

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