; ArrowLISP integer math functions
; Copyright (C) 1998-2006 Nils M Holm. All rights reserved.
; See the file LICENSE of the ArrowLISP distribution
; for conditions of use.
; would use REQUIRE, but REQUIRE is in BASE
(cond ((defined 'base) :F)
(t (load base)))
(require '=nmath)
(define imath t)
(package imath)
(define (integer a)
(cond ((eq (car a) '+) (cdr a))
((eq (car a) '-) a)
((digit (car a)) a)
(t (bottom (list 'integer a)))))
(define (integer-p a)
(or (digit (car a))
(eq (car a) '+)
(eq (car a) '-)))
(define (i-normalize x)
(cond ((eq (car x) '+)
(n-normalize (cdr x)))
((eq (car x) '-)
(let ((d (n-normalize (cdr x))))
(cond ((equal d '(0)) d)
(t (cons '- d)))))
(t (n-normalize x))))
(define (i-zero x)
(let ((a (i-abs x)))
(n-zero a)))
(define (i-one x)
(let ((a (i-abs x)))
(and (n-one a) (neq (car x) '-))))
(define (i-negative x) (eq (car x) '-))
(define (i-abs x)
(cond ((i-negative x) (cdr x))
((eq (car x) '+) (cdr x))
(t x)))
(define (i-negate x)
(cond ((n-zero (i-abs x)) x)
((eq (car x) '-) (cdr x))
((eq (car x) '+) (cons '- (cdr x)))
(t (cons '- x))))
(define (i+ a b)
(cond ((and (not (i-negative a))
(not (i-negative b)))
(n+ (i-abs a) (i-abs b)))
((and (not (i-negative a))
(i-negative b))
(cond ((n> (i-abs a) (i-abs b))
(n- (natural a) (i-abs b)))
(t (i-negate (n- (i-abs b) (natural a))))))
((and (i-negative a)
(not (i-negative b)))
(cond ((n> (i-abs a) (i-abs b))
(i-negate (n- (i-abs a) (natural b))))
(t (n- (natural b) (i-abs a)))))
(t (i-negate (n+ (i-abs a) (i-abs b))))))
(define (i- a b)
(cond ((i-negative b)
(i+ a (i-abs b)))
((i-negative a)
(i+ a (i-negate b)))
((n< (i-abs a) (i-abs b))
(i-negate (n- (i-abs b) (i-abs a))))
(t (n- (i-abs a) (i-abs b)))))
(define (i< a b)
(cond ((i-negative a)
(cond ((not (i-negative b)) t)
(t (n< (i-abs b) (i-abs a)))))
((i-negative b) :F)
(t (n< (i-abs a) (i-abs b)))))
(define (i> a b) (i< b a))
(define (i<= a b) (eq (i> b a) :F))
(define (i>= a b) (eq (i< b a) :F))
(define (i= a b)
(equal (i-normalize a)
(i-normalize b)))
(define (i* a b)
(cond
((zero a) '#0)
((eq (i-negative a) (i-negative b))
(n* (i-abs a) (i-abs b)))
(t (i-negate (n* (i-abs a) (i-abs b))))))
(define (i-divide a b)
(letrec
((sign (lambda (x)
(cond ((eq (i-negative a) (i-negative b)) x)
(t (cons '- x)))))
(rsign (lambda (x)
(cond ((i-negative a) (cons '- x))
(t x))))
(idiv (lambda (a b)
(cond ((n-zero b) (bottom '(divide by zero)))
((n< (i-abs a) (i-abs b))
(list '#0 (rsign (i-abs a))))
(t (let ((q (n-divide (i-abs a) (i-abs b))))
(list (sign (car q))
(rsign (cadr q)))))))))
(idiv (integer a) (integer b))))
(define (i-quotient a b) (car (divide a b)))
(define (i-remainder a b) (cadr (divide a b)))
(define (modulo a b)
(let ((rem (remainder a b)))
(cond ((eq (i-negative a) (i-negative b))
rem)
(t (i+ b rem)))))
(define (i-expt x y)
(letrec
((_i-expt (lambda (x y)
(cond ((or (not (i-negative x))
(even y))
(n-expt (i-abs x) y))
(t (i-negate (n-expt (i-abs x) y)))))))
(_i-expt (integer x) (natural y))))
(define (i-max . a)
(apply min/max (cons i> a)))
(define (i-min . a)
(apply min/max (cons i< a)))
(define (i-sqrt x)
(cond ((i-negative x)
(bottom (list 'i-sqrt x)))
(t (n-sqrt x))))
(define (i-gcd a b)
(n-gcd (i-abs a) (i-abs b)))
(define (i-lcm a b)
(n-lcm (i-abs a) (i-abs b)))
(package)
(require '=iter)
(define * (arith-iterator integer i* '#1))
(define + (arith-iterator integer i+ '#0))
(define (- . x)
(cond ((null x)
(bottom '(too few arguments to integer -)))
((eq (cdr x) ()) (i-negate (car x)))
(t (reduce (lambda (a b)
(i- (integer a) (integer b)))
x '#0))))
(define < (arith-pred-iterator integer i<))
(define <= (arith-pred-iterator integer i<=))
(define = (arith-pred-iterator integer i=))
(define > (arith-pred-iterator integer i>))
(define >= (arith-pred-iterator integer i>=))
(define abs i-abs)
(define divide i-divide)
(define expt i-expt)
(define gcd (arith-iterator integer i-gcd '#0))
(define lcm (arith-iterator integer i-lcm '#0))
(define (max . a) (apply min/max (cons i> a)))
(define (min . a) (apply min/max (cons i< a)))
(define negate i-negate)
(define negative i-negative)
(define one i-one)
(define quotient i-quotient)
(define remainder i-remainder)
(define sqrt i-sqrt)
(define zero i-zero)
syntax highlighted by Code2HTML, v. 0.9.1