; A Simple Ripple-Carry Adder in ACL2 ; J Moore (include-book "arithmetic-5/top" :dir :system) (set-acl2s-random-testing-enabled nil) ; In this project I will represent binary numbers by ; lists of Ts and NILs. I will call such a list a ``Boolean ; vectors'' or ``bv'' for short. In a bv, I will put the least ; significant digit first. So the binary number 6, which might ; usually be written 110 will be the bv (NIL T T). ; First I will define the function that takes a bv ; and converts it to a natural number: (defun N (bv) (if (endp bv) 0 (+ (if (first bv) 1 0) (* 2 (N (rest bv)))))) ; For example, (N '(nil t t)) ; For testing purposes, it is convenient to have the inverse ; of N: (defun V (n) (if (zp n) nil (cons (oddp n) (V (floor n 2))))) ; So for example, (V 6) ; and (V 123456789) (N (V 12345689)) ; To add in binary we must be able to add 3 binary digits together ; and get the new least significant digit and a carry out. ; a + b + c = low-digit carry out ; nil nil nil nil nil ; nil nil t t nil ; nil t nil t nil ; nil t t nil t ; t nil nil t nil ; t nil t nil t ; t t nil nil t ; t t t t t ; The following definitions would be much more elegant if I used ; exclusive or, but I want to show how I can do everything with ; and, or, and not. ; Low-digit is T if exactly one of a, b, and c is T, or if all ; three are T. (defun low-digit (a b c) (or (and a (not b) (not c)) (and (not a) b (not c)) (and (not a) (not b) c) (and a b c))) ; Carry-out is T if two or more of a, b, and c are T. (defun carry-out (a b c) (or (and a b) (and a c) (and b c))) (defun adder (A B c) (if (and (endp A) (endp B)) (list c) (cons (low-digit (first A) (first B) c) (adder (rest A) (rest B) (carry-out (first A) (first B) c))))) (adder '(nil t t) '(t t nil) nil) (N (adder (V 6) (V 3) nil)) (N (adder (V 1234) (V 6789) nil)) (+ 1234 6789 0) (defthm adder-is-correct-lemma (implies (endp B) (equal (N (adder A B c)) (+ (N A) (if c 1 0))))) (defthm adder-is-correct (equal (N (adder A B c)) (+ (N A) (N B) (if c 1 0))))