Rename *ll* and *ul* to ll and ul in in-interval
[maxima.git] / share / contrib / bitwise / bitwise.lisp
blob461deef5d8acacdf3d80d58d99add9da25f4112b
2 ;; Maxima bit functions
3 ;; Copyright (C) 2008 Volker van Nek
5 ;; This source code is licensed under the terms of the Lisp Lesser
6 ;; GNU Public License (LLGPL). The LLGPL consists of a preamble, published
7 ;; by Franz Inc. (http://opensource.franz.com/preamble.html), and the GNU
8 ;; Library General Public License (LGPL), version 2, or (at your option)
9 ;; any later version. When the preamble conflicts with the LGPL,
10 ;; the preamble takes precedence.
12 ;; This library is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ;; Library General Public License for details.
17 ;; You should have received a copy of the GNU Library General Public
18 ;; License along with this library; if not, write to the
19 ;; Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 ;; Boston, MA 02110-1301, USA.
23 ;; functions at Maxima level:
25 ;; bit_not bitwise NOT
26 ;; bit_and bitwise AND
27 ;; bit_xor bitwise XOR
28 ;; bit_or bitwise OR
29 ;; bit_lsh bitwise LEFT SHIFT
30 ;; bit_rsh bitwise RIGHT SHIFT
32 ;; bit_length number of necessary bits to represent a positive integer
33 ;; bit_onep test for bit 1
36 ;; comments in this file use the following abbreviations:
37 ;; i,j,k : literal integers
38 ;; x,y,z : any expression
39 ;; di,dj,dk : declared integer
40 ;; de, do : declared even resp. odd
42 (in-package :maxima)
44 (macsyma-module bitwise)
47 (eval-when
48 (:compile-toplevel :execute)
49 (defvar old-ibase *read-base*)
50 (setq *read-base* 10.) )
53 ;; I'm not sure if we should add the property 'integer-valued to these functions
54 ;; if we allow bit_not(bit_not(x)) --> x, bit_and(x) --> x, etc. for any expression x
55 (setf (get '$bit_not 'integer-valued) t)
56 (setf (get '$bit_and 'integer-valued) t)
57 (setf (get '$bit_xor 'integer-valued) t)
58 (setf (get '$bit_or 'integer-valued) t)
59 (setf (get '$bit_lsh 'integer-valued) t)
60 (setf (get '$bit_rsh 'integer-valued) t)
61 (setf (get '$bit_length 'integer-valued) t)
65 ;; ERROR if at least one arg to bit_function is a non-integer constant, string or Maxima list
67 (defun badargcheck (a f n)
68 (if (or (and (not (integerp a)) ($constantp a))
69 (stringp a)
70 ($listp a))
71 (let ((s (format nil "bad ~@[~:r~] argument to `~a': ~a" n f ($sconcat a))))
72 (merror "~m" s))))
76 ;; bitwise NOT
78 (defprop $bit_not simp-bit-not operators)
80 (defun simp-bit-not (a tmp z)
81 (declare (ignore tmp))
82 (oneargcheck a)
83 (setq a (simplifya (cadr a) z))
84 (badargcheck a "bit_not" nil)
85 (cond ((integerp a) ;; bit_not(i) --> bitwise NOT i
86 (lognot a))
87 ((and (listp a) (listp (car a)) (equal (caar a) '$bit_not))
88 (cadr a)) ;; bit_not(bit_not(x)) --> x ;; di instead of x ?
89 ((maxima-integerp a) ;; bit_not(di) --> - di - 1
90 (meval `((mplus) ((mminus) ,a) -1)))
92 `(($bit_not simp) ,a)) )) ;; return unevaluated
96 ;; bitwise AND
98 (defprop $bit_and simp-bit-and operators)
100 (defun simp-bit-and (args tmp z)
101 (declare (ignore tmp))
102 (setq args (cdr args))
104 ;; trivial case bit_and() --> -1
105 (if (null args) (return-from simp-bit-and -1))
107 (let ((acc nil) (n 1) (ints nil))
109 ;; check and simplify the arguments
110 (dolist (a args)
111 (badargcheck a "bit_and" n)
112 (setq n (1+ n))
113 (push (simplifya a z) acc) )
115 ;; separate the arguments into a list of literal integers and the rest
116 ;; and remove duplicates bit_and(x,x,y) --> bit_and(x,y)
117 (setq args (sorted-remove-duplicates (sort acc '$orderlessp)))
118 (do ((a (car args)))
119 ((or (null args) (not (integerp a))))
120 (push a ints)
121 (setq args (cdr args))
122 (setq a (car args)) )
124 ;; apply logand to the list of literal integers and return if possible
125 (setq n (apply #'logand ints))
126 (if (null args) (return-from simp-bit-and n)) ;; bit_and(i,j) --> bitwise i AND j
127 (cond ((zerop n) (return-from simp-bit-and 0)) ;; bit_and(0,x) --> 0
128 ((= n -1) (setq ints nil)) ;; bit_and(-1,x) --> bit_and(x) ( --> x see below )
129 (t (setq ints (list n)))) ;; bit_and(i,j,x) --> bit_and(bit_and(i,j),x)
131 ;; if twos complement occurs bit_and(x,bit_not(x),y) --> 0
132 (setq acc nil)
133 (do ((a (car args)))
134 ((null (cdr args)) (push a acc))
135 (if (some #'(lambda (b) (equal t (meval `(($is) (($equal) (($bit_not simp) ,a) ,b))))) (cdr args))
136 (return-from simp-bit-and 0))
137 (push a acc)
138 (setq args (cdr args))
139 (setq a (car args)) )
141 ;; even or odd declared objects bit_and(1,de,y) --> 0
142 (if (and (= n 1) (some #'(lambda (b) ($featurep b '$even)) acc))
143 (return-from simp-bit-and 0))
144 ;; bit_and(1,do) --> 1
145 (if (and (= n 1) (every #'(lambda (b) ($featurep b '$odd)) acc))
146 (return-from simp-bit-and 1))
148 ;; if one arg remains bit_and(x) --> x ;; di instead of x ?
149 (setq args (append ints (reverse acc)))
150 (if (= 1 (length args))
151 ;;(and (= 1 (length args)) (maxima-integerp (car args))); if we require bit_and(di) --> di
152 (return-from simp-bit-and (car args)))
154 ;; return unevaluated if no previous return-from occurred
155 `(($bit_and simp) ,@args)))
159 ;; helpers for $bit_xor
161 (defun sorted-remove-pairs (l)
162 (do ((a (car l) (car l)) (acc nil))
163 ((null l) (reverse acc))
164 (cond ((and (cdr l) (like a (cadr l)))
165 (setq l (cddr l)))
166 (t (push a acc)
167 (setq l (cdr l))) )))
169 (defun remove-twos-complement (n l)
170 (do ((a (car l) (car l)) (acc nil))
171 ((null l) (reverse acc))
172 (cond ((equal t (meval `(($is) (($equal) (($bit_not) ,a) ,n))))
173 (return-from remove-twos-complement (append (reverse acc) (cdr l))))
174 (t (push a acc)
175 (setq l (cdr l))) )))
179 ;; bitwise EXCLUSIVE OR
181 (defprop $bit_xor simp-bit-xor operators)
183 (defun simp-bit-xor (args tmp z)
184 (declare (ignore tmp))
185 (setq args (cdr args))
187 ;; trivial case bit_xor() --> 0
188 (if (null args) (return-from simp-bit-xor 0))
190 (let ((acc nil) (n 1) (ints nil))
192 ;; check and simplify the arguments
193 (dolist (a args)
194 (badargcheck a "bit_xor" n)
195 (setq n (1+ n))
196 (push (simplifya a z) acc) )
198 ;; separate the arguments into a list of literal integers and the rest
199 ;; and remove pairs bit_xor(x,x,y,z) --> bit_xor(y,z)
201 (setq args (sorted-remove-pairs (sort acc '$orderlessp)))
202 (do ((a (car args)))
203 ((or (null args) (not (integerp a))))
204 (push a ints)
205 (setq args (cdr args))
206 (setq a (car args)) )
208 ;; apply logxor to the list of integers and return if possible
209 (setq n (apply #'logxor ints))
210 (if (null args) (return-from simp-bit-xor n)) ;; bit_xor(i,j) --> bitwise i XOR j
211 (setq ints (list n)) ;; bit_xor(i,j,x) --> bit_xor(bit_xor(i,j),x)
213 ;; if twos complement occurs bit_xor(x,bit_not(x),y,z) --> bit_xor(-1,y,z)
214 (setq acc nil)
215 (do ((a (car args)))
216 ((null (cdr args)) (and a (push a acc)))
217 (cond ((some #'(lambda (b) (equal t (meval `(($is) (($equal) (($bit_not) ,a) ,b))))) (cdr args))
218 (rplacd args (remove-twos-complement a (cdr args)))
219 (setq ints (list (setq n (1- (- n))))))
220 (t (push a acc)))
221 (setq args (cdr args))
222 (setq a (car args)) )
223 (setq acc (reverse acc))
225 ;; n might have been changed in previous step; 0 occurs
226 (if (zerop n) (setq ints nil)) ;; bit_xor(0,x) --> bit_xor(x) ( --> x see below)
228 ;; if there is an even or odd declared object bit_xor(1,de,y) --> bit_xor(de+1,y) --> recurse
229 (if (and (= n 1) (some #'(lambda (b) ($featurep b '$even)) acc))
230 (progn
231 (do ((a (car acc) (car acc)) (bcc nil))
232 ((null acc) (setq acc (reverse bcc)))
233 (if ($featurep a '$even)
234 (progn
235 (setq acc (append (reverse bcc) (list (meval `((mplus) ,a 1))) (cdr acc)))
236 (setq n 0)
237 (setq ints nil)
238 (return-from simp-bit-xor (meval `(($bit_xor simp) ,@acc))) ))
239 (push a bcc)
240 (setq acc (cdr acc))) ))
241 ;; bit_xor(1,do,y) --> bit_xor(do-1,y) --> recurse
242 (if (and (= n 1) (some #'(lambda (b) ($featurep b '$odd)) acc))
243 (progn
244 (do ((a (car acc) (car acc)) (bcc nil))
245 ((null acc) (setq acc (reverse bcc)))
246 (if ($featurep a '$odd)
247 (progn
248 (setq acc (append (reverse bcc) (list (meval `((mplus) ,a ((mminus) 1)))) (cdr acc)))
249 (setq n 0)
250 (setq ints nil)
251 (return-from simp-bit-xor (meval `(($bit_xor simp) ,@acc))) ))
252 (push a bcc)
253 (setq acc (cdr acc))) ))
255 ;; -1 occurs bit_xor(-1,x,y) --> bit_xor(bit_not(x),y) --> recurse
256 (if (and acc (= n -1))
257 (return-from simp-bit-xor
258 (meval `(($bit_xor simp)
259 ,@(cons (meval `(($bit_not simp) ,(car acc))) (cdr acc)) )) ))
261 ;; if one arg remains bit_xor(x) --> x ;; di instead of x ?
262 (setq args (append ints acc))
263 (if (= 1 (length args))
264 (return-from simp-bit-xor (car args)))
266 ;; return unevaluated if no previous return-from occurred
267 `(($bit_xor simp) ,@args)))
271 ;; bitwise OR
273 (defprop $bit_or simp-bit-or operators)
275 (defun simp-bit-or (args tmp z)
276 (declare (ignore tmp))
277 (setq args (cdr args))
279 ;; trivial case bit_or() --> 0
280 (if (null args) (return-from simp-bit-or 0))
282 (let ((acc nil) (n 1) (ints nil))
284 ;; check and simplify the arguments
285 (dolist (a args)
286 (badargcheck a "bit_or" n)
287 (setq n (1+ n))
288 (push (simplifya a z) acc) )
290 ;; separate the arguments into a list of literal integers and the rest
291 ;; and remove duplicates bit_or(x,x,y) --> bit_or(x,y)
292 (setq args (sorted-remove-duplicates (sort acc '$orderlessp)))
293 (do ((a (car args)))
294 ((or (null args) (not (integerp a))))
295 (push a ints)
296 (setq args (cdr args))
297 (setq a (car args)) )
299 ;; apply logior to the list of literal integers and return if possible
300 (setq n (apply #'logior ints))
301 (if (null args) (return-from simp-bit-or n)) ;; bit_or(i,j) --> bitwise i OR j
302 (cond ((= n -1) (return-from simp-bit-or -1)) ;; bit_or(-1,x) --> -1
303 ((zerop n) (setq ints nil)) ;; bit_or(0,x) --> bit_or(x) ( --> x see below)
304 (t (setq ints (list n)))) ;; bit_or(i,j,x) --> bit_or(bit_or(i,j),x)
306 ;; if twos complement occurs bit_or(x,bit_not(x),y) --> -1
307 (setq acc nil)
308 (do ((a (car args)))
309 ((null (cdr args)) (push a acc))
310 (if (some #'(lambda (b) (equal t (meval `(($is) (($equal) (($bit_not simp) ,a) ,b))))) (cdr args))
311 (return-from simp-bit-or -1))
312 (push a acc)
313 (setq args (cdr args))
314 (setq a (car args)) )
316 ;; if there is an even or odd declared obj bit_or(1,de,y) --> bit_or(de+1,y) --> recurse
317 (if (and (= n 1) (some #'(lambda (b) ($featurep b '$even)) acc))
318 (progn
319 (do ((a (car acc) (car acc)) (bcc nil))
320 ((null acc) (setq acc (reverse bcc)))
321 (if ($featurep a '$even)
322 (progn
323 (setq acc (append (reverse bcc) (list (meval `((mplus) ,a 1))) (cdr acc)))
324 (setq n 0)
325 (setq ints nil)
326 (return-from simp-bit-or (meval `(($bit_or simp) ,@acc))) ))
327 (push a bcc)
328 (setq acc (cdr acc))) ))
329 ;; bit_or(1,do,y) --> bit_or(do,y)
330 (if (and (= n 1) (some #'(lambda (b) ($featurep b '$odd)) acc))
331 (setq ints nil))
333 ;; if one arg remains bit_or(x) --> x ;; di instead of x ?
334 (setq args (append ints (reverse acc)))
335 (if (= 1 (length args))
336 (return-from simp-bit-or (car args)))
338 ;; return unevaluated if no previous return-from occurred
339 `(($bit_or simp) ,@args)))
343 ;; bitwise LEFT SHIFT
345 (defprop $bit_lsh simp-bit-lsh operators)
347 (defun simp-bit-lsh (e tmp z)
348 (declare (ignore tmp))
349 (twoargcheck e)
350 (let ((a (simplifya (cadr e) z))
351 (count (simplifya (caddr e) z)))
352 (badargcheck a "bit_lsh" 1)
353 (badargcheck count "bit_lsh" 2)
354 (cond ((and (integerp a) (integerp count)) ;; bit_lsh(i,k) --> bitwise LEFT SHIFT i,k
355 (ash a count))
356 ((and (maxima-integerp count) (equal (meval `(($is) ((mgeqp) ,count 0))) t))
357 (meval `((mtimes) ((mexpt) 2 ,count) ,a))) ;; bit_lsh(x,dk) --> 2^dk*x, where dk>=0 ;; di instead of x ?
359 `(($bit_lsh simp) ,a ,count)) ))) ;; return unevaluated
363 ;; bitwise RIGHT SHIFT
365 (defprop $bit_rsh simp-bit-rsh operators)
367 (defun simp-bit-rsh (e tmp z)
368 (declare (ignore tmp))
369 (twoargcheck e)
370 (let ((a (simplifya (cadr e) z))
371 (count (simplifya (caddr e) z)))
372 (badargcheck a "bit_rsh" 1)
373 (badargcheck count "bit_rsh" 2)
374 (meval `(($bit_lsh) ,a (- ,count))))) ;; bit_rsh(x,y) --> bit_lsh(x,-y)
378 ;; ONE-BIT TEST
380 (defprop $bit_onep simp-bit-onep operators)
382 (defun simp-bit-onep (e tmp z)
383 (declare (ignore tmp))
384 (twoargcheck e)
385 (let ((a (simplifya (cadr e) z))
386 (index (simplifya (caddr e) z)))
387 (badargcheck a "bit_onep" 1)
388 (badargcheck index "bit_onep" 2)
389 (if (equal t (meval `(($is) ((mlessp) ,index 0)))) ;; additional check: error if index<0
390 (merror "second argument to `bit_onep' must be non-negative."))
391 (cond ((and (integerp a) (integerp index)) ;; bit_onep(i,k) --> ONE-BIT TEST i,k, k>=0
392 (logbitp index a))
393 ((eql 0 index)
394 (cond (($featurep a '$even) nil) ;; bit_onep(de,0) --> false
395 (($featurep a '$odd) t))) ;; bit_onep(do,0) --> true
396 ((and (maxima-integerp index) ;; bit_onep(x,dk) where 0<=x<2^dk, dk>=0 --> false
397 (equal t (meval `(($is) ((mgeqp) ,index 0))))
398 (equal t (meval `(($is) ((mgeqp) ,a 0))))
399 (equal t (meval `(($is) ((mlessp) ,a ((mexpt) 2 ,index))))))
400 nil)
401 ((and ;; bit_onep(di^dj,y) where di^dj = 2^y --> true
402 (listp a) (listp (car a)) (equal (caar a) 'mexpt)
403 ;; check if y = dj*log(di)/log(2) :
404 (maxima-integerp (cadr a))
405 (maxima-integerp (caddr a))
406 (equal t
407 (meval `(($is) (($equal)
408 ,index
409 ((mquotient) ((mtimes) ,(caddr a) ((%log) (($factor) ,(cadr a)))) ((%log) 2)) )))))
412 `(($bit_onep simp) ,a ,index)) ))) ;; return unevaluated
416 ;; BIT LENGTH
418 (defprop $bit_length simp-bit-length operators)
420 (defun simp-bit-length (a tmp z)
421 (declare (ignore tmp))
422 (oneargcheck a)
423 (setq a (simplifya (cadr a) z))
424 (badargcheck a "bit_length" nil)
425 (if (equal t (meval `(($is) ((mlessp) ,a 0)))) ;; additional check: error if a<0
426 (merror "argument to `bit_length' must be non-negative."))
427 (cond ((integerp a) ;; bit_length(i) --> BIT LENGTH i
428 (integer-length a))
429 ((and ;; bit_length(2^dk) --> dk+1, bit_length(4^dk) --> 2*dk+1, etc.
430 ;; where dk>=0
431 (listp a) (listp (car a)) (equal (caar a) 'mexpt)
432 (maxima-integerp (cadr a))
433 (maxima-integerp (caddr a)) (equal t (meval `(($is) ((mgeqp) ,(caddr a) 0))))
434 (let ((fl (get-factor-list (cadr a))) e)
435 (and (= 1 (length fl)) (= 2 (caar fl)))
436 (setq e (cadar fl))
437 (return-from simp-bit-length (meval `((mplus) ((mtimes) ,e ,(caddr a)) 1)) ))))
439 `(($bit_length simp) ,a)) )) ;; return unevaluated
442 (eval-when
443 (:compile-toplevel :execute)
444 (setq *read-base* old-ibase) )