home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ARM Club 3
/
TheARMClub_PDCD3.iso
/
hensa
/
maths
/
b116_1
/
jacal
/
sexp
< prev
next >
Wrap
Text File
|
1993-10-18
|
12KB
|
367 lines
;;; JACAL: Symbolic Mathematics System. -*-scheme-*-
;;; Copyright 1989, 1990, 1991, 1992, 1993 Aubrey Jaffer.
;;; See the file "COPYING" for terms applying to this program.
;;; our local environments
(define heqput! (alist-associator eq?))
(define heqrem! (alist-remover eq?))
(define hassq (predicate->asso eq?))
(define (list-of-procedure-defsyms)
(define proc-defs '())
(alist-for-each (lambda (k v)
(if (procedure? (var:def v))
(set! proc-defs (cons k proc-defs))))
var-tab)
proc-defs)
;(define heqput! (hash-associator eq?))
;(define heqrem! (hash-remover eq?))
;(define hassq (predicate->hash-asso eq?))
;(define (list-of-procedure-defsyms)
; (define proc-defs '())
; (hash-for-each
; (lambda (k v) (set! proc-defs (cons k proc-defs)))
; var-tab)
; proc-defs)
(define (defsym sym value)
(set! *symdefs* (heqput! *symdefs* sym value)) value)
(define (undefsym sym)
(set! *symdefs* (heqrem! *symdefs* sym))
(var->expl (sexp->var sym)))
(define (defbltn sym val)
(cond ((list? sym)
(for-each (lambda (v) (apply defbltn v val)) sym))
(else
(var:set-def! (sexp->var sym) val)
sym)))
;;; hdns here is a list of lexically bound symbols as in lambda or suchthat.
;;; so it is really a list of things not to look up.
(define (symdef-lookup sym hdns)
(cond ((null? hdns)
(let ((p (hassq sym *symdefs*)))
(if p (cdr p) (var->expl (sexp->var sym)))))
((eq? sym (car hdns)) (var->expl (sexp->var sym)))
((symbol? (car hdns)) (symdef-lookup sym (cdr hdns)))
((memq sym (car hdns)) (var->expl (sexp->var sym)))
(else (symdef-lookup sym (cdr hdns)))))
;;;now for the read-eval-print stuff
(define var-news '())
(define (math . batches)
(set-handlers!)
(for-each (lambda (file)
(batch (if (symbol? file) (symbol->string file) file)))
batches)
(tran:display 'type)
(write-sexp '(qed) *input-grammar*)
(tran:display 'to-return-to-)
(display base-language)
(tran:display 'type-)
(write-sexp '(help) *input-grammar*)
(tran:display 'for-help.)
(batch1)
(cleanup-handlers!)
base-language)
(define (batch file)
(let* ((save-page #f)
(swapmodes (lambda ()
(let ((tmp page-height))
(set! page-height save-page)
(set! save-page tmp)))))
(dynamic-wind swapmodes
(lambda () (with-input-from-file file batch1))
swapmodes)))
(define (batch1)
(do ((math:exit-saved math:exit)
(var-news-saved var-news)
(math:prompt #f))
((call-with-current-continuation
(lambda (math:exit-cnt)
(define obj #f)
(set! math:exit math:exit-cnt)
(newline) ;find unused var
(do () ((not (or (var-tab-lookup newlabelsym var-tab)
(hassq newlabelsym *symdefs*))))
(set! newlabelstr (sect:next-string newlabelstr))
(set! newlabelsym (string->symbol newlabelstr)))
(set! math:prompt (string-append newlabelstr " : "))
(let loop ()
(define echoing (not (eq? (get-grammar 'null) *echo-grammar*)))
(set! var-news '())
(cond (echoing)
((output-port? (current-input-port))
(let ((cip (current-input-port)))
(display math:prompt cip)
(force-output cip)
(lex:bump-column (string-length math:prompt))))
(else (display math:prompt)
(force-output)
(lex:bump-column (string-length math:prompt))))
(set! obj (read-sexp *input-grammar*))
(lex:bump-column 0)
(cond ((not obj) (loop))
((eof-object? obj) (math:exit #t))
((and (symbol? obj) (symdef-lookup obj '()))
(write-sexp (list 'define obj
(math->sexp (symdef-lookup obj '())
horner))
*output-grammar*)
(newline)
(loop))
(else
(set! linum 0)
(write-sexp obj *echo-grammar*)
(if (and (pair? obj) (eq? 'define (car obj)))
(let* ((var (cadr obj)) (val (sexp->math obj)))
(out-new-vars var-news)
(newline)
(cond ((novalue? val)
(sexp->math (list 'define var var))
(eval-error 'no-value-to-set (cadr obj)))
((eq? 'null (grammar-name *output-grammar*))
(set! % val))
(else
(set! % val)
(write-sexp (list 'define var
(math->sexp val horner))
*output-grammar*)
(newline))))
(let* ((var newlabelsym)
(val (sexp->math (list 'define var obj))))
(out-new-vars var-news)
(newline)
(cond ((novalue? val)
(sexp->math (list 'define var var))
(loop))
((eq? 'null (grammar-name *output-grammar*))
(set! % val))
(else
(set! % val)
(write-sexp (list 'define var
(math->sexp val horner))
*output-grammar*)
(newline))))))))
#f))
(set! math:exit math:exit-saved)
(set! var-news var-news-saved))))
(define (out-new-vars var-news)
(if (not (eq? 'null (grammar-name *output-grammar*)))
(for-each (lambda (x)
(newline)
(write-sexp (list 'define
(var:sexp x)
(math->sexp (vsubst $ x (extrule x))
horner))
*output-grammar*))
var-news)))
;;; $=fc($1) --> $=fc^^-1($1)
(define (fcinverse fc)
(extize (normalize (swapvars $1 $ (licit->impl fc)))))
;;; fc(fc(...fc($1)))
(define (fcexpt fc pow)
(if (negative? pow)
(fcexpt (fcinverse fc) (- pow))
(ipow-by-squaring fc pow cidentity app*)))
(define (rapply ob . arglist)
(cond ((null? arglist) ob)
((bunch? ob)
(apply rapply
(list-ref ob (+ -1 (plicit->integer (car arglist))))
(cdr arglist)))
((expl? ob) (apply deferop _rapply ob arglist))
(else (eval-error 'rapply 'wta ob))))
(define (sapply fun args)
(cond ((procedure? fun) (apply fun args))
((clambda? fun)
(capply fun args))
((rat:number? fun) (eval-error 'apply 'wta fun))
(else (apply deferop fun args))))
(define (app* fun . args) (sapply fun args))
(define (seval f hdns)
(cond ((number? f)
(if (inexact? f) (eval-error 'Inexact-number-to-eval:-))
(cond ((integer? f) f)
((rational? f) (make-rat (numerator f) (denominator f)))))
((vector? f) (map (lambda (x) (seval x hdns)) (vector->list f)))
((symbol? f) (symdef-lookup f hdns))
((boolean? f) f)
((null? f) f)
((not (pair? f)) (eval-error 'eval 'wta f))
((eq? 'lambda (car f))
(let ((vars (variables
(cond ((symbol? (cadr f)) (list (cadr f)))
((vector? (cadr f)) (vector->list (cadr f)))
((pair? (cadr f)) (cadr f))
(else (eval-error 'lambda 'bad-arglist f))))))
(clambda vars (seval (caddr f) (cons vars hdns)))))
((eqv? (car f) 'suchthat)
(suchthat (sexp->var (cadr f))
(seval (caddr f) (cons (cadr f) hdns))))
((eqv? (car f) 'define)
(cond ((symbol? (cadr f))
(if (eq? (cadr f) (caddr f))
(undefsym (cadr f))
(defsym (cadr f)
(normalize (seval (caddr f) (cons (cadr f) hdns))))))
((eqv? (caadr f) 'rapply)
(defsym (cadadr f)
(rlambda (cddadr f)
(normalize (seval (caddr f)
(cons (cdadr f) hdns))))))
(else ;must be capply
(defsym (caadr f)
(clambda (variables (cdadr f))
(normalize (seval (caddr f)
(cons (cadr f) hdns))))))))
(else
(let ((ff (seval (car f) hdns)))
(sapply (or (and (pair? ff)
(expl? ff)
(equal? (cdr ff) '(0 1))
(procedure? (var:def (car ff)))
(var:def (car ff)))
ff)
(map (lambda (x) (seval x hdns)) (cdr f)))))))
(define (sexp->math f) (seval f '()))
(define (bunch->sexp p horner)
;;; These routines convert LICITs or parts of LICITs to S-EXPRESSIONs
(define (cmprs:+ res)
(cond ((null? (cdr res)) (car res))
((and (pair? (cadr res)) (eq? 'negate (caadr res)))
(cmprs:+ (cons (list '- (car res) (cadadr res)) (cddr res))))
((and (pair? (car res)) (eq? '+ (caar res)))
(if (null? (cddr res)) (nconc (car res) (cdr res))
(cmprs:+ (cons (nconc (car res) (list (cadr res))) (cddr res)))))
((null? (cddr res)) (cons '+ res))
(else (cmprs:+ (cons (list '+ (car res) (cadr res)) (cddr res))))))
(define (cmprs:* mu mex)
(cond ((pair? mu)
(cond ((eq? '* (car mu)) (nconc mu (list mex)))
((eq? 'negate (car mu))
(list 'negate (cmprs:* (cadr mu) mex)))
(else (list '* mu mex))))
((and (number? mu) (negative? mu))
(if (eq? -1 mu)
(list 'negate mex)
(list 'negate (list '* (- mu) mex))))
(else (if (eq? 1 mu) mex (list '* mu mex)))))
(define (cmprs:^ var exp)
(cond ((one? exp) var)
((and (pair? var)
(eq? '^ (car var)))
(list '^
(cadr var)
(if (and (pair? (caddr var))
(eq? '/ (caaddr var))
(one? (cadr (caddr var))))
(list '/ exp (caddr (caddr var)))
(cmprs:* exp (caddr var)))))
(else (list '^ var exp))))
;POLY->SEXP converts a polynomial to SEXPRESSION.
(define (poly->sexp p)
(cond ((number? p) p)
(horner (coes->horner-sexp (var:sexp (car p)) 0 (cdr p)))
(else (cmprs:+ (coes->sexp (var:sexp (car p)) 0 (cdr p))))))
(define (coes->horner-sexp var exp colist)
(cond ((eqv? 0 (car colist)) (coes->horner-sexp var (+ 1 exp) (cdr colist)))
((null? (cdr colist))
(if (zero? exp) (poly->sexp (car colist))
(cmprs:* (poly->sexp (car colist)) (cmprs:^ var exp))))
((zero? exp)
(cmprs:+ (list (poly->sexp (car colist))
(coes->horner-sexp var 1 (cdr colist)))))
(else
(cmprs:*
(cmprs:+ (list (poly->sexp (car colist))
(coes->horner-sexp var 1 (cdr colist))))
(cmprs:^ var exp)))))
(define (coes->sexp var exp colist)
(cond ((null? colist) colist)
((eqv? 0 (car colist)) (coes->sexp var (+ 1 exp) (cdr colist)))
((zero? exp) (cons (poly->sexp (car colist))
(coes->sexp var (+ 1 exp) (cdr colist))))
((eqv? 1 (car colist))
(cons (cmprs:^ var exp) (coes->sexp var (+ 1 exp) (cdr colist))))
(else (cons (cmprs:* (poly->sexp (car colist)) (cmprs:^ var exp))
(coes->sexp var (+ 1 exp) (cdr colist))))))
;RAT->SEXP converts a rational polynomial to SEXPRESSION.
(define (rat->sexp n d)
(if (unit? d)
(poly->sexp (poly:* n d))
(list 'over (poly->sexp n) (poly->sexp d))))
(define (impl:radical? p) (one? (length (or (memv 0 (cddr p)) '()))))
;;;IMPOLY->SEXP converts an implicit polynomial to SEXPRESSION.
(define (impoly->sexp p)
(if (impl:radical? p)
(list '=
(if (null? (cdddr p))
(var:sexp (car p))
;;I cant exercise this clause:
(list '^ (var:sexp (car p)) (length (cddr p))))
(rat->sexp (cadr p) (car (last-pair p))))
(list '= 0 (poly->sexp p))))
;;;IRIMPL->SEXP converts an irreducible implicit expression to SEXPRESSION.
(define (irimpl->sexp p)
(let ((dgr (poly:degree p $)))
(cond ((zero? dgr) (math:warn 'not-canonical p) p)
((one? dgr) (rat->sexp (rat:num p) (rat:denom p)))
(else (list 'suchthat (var:sexp (car p)) (impoly->sexp p))))))
(define (ibunch->sexp p)
(cond ((bunch? p) (list->vector (map ibunch->sexp p))) ;inefficient
((symbol? p) p)
((expl? p) (poly->sexp p))
((impl? p)
(let ((dgr (poly:degree p $)))
(cond ((zero? dgr) (math:warn 'not-canonical p) p)
((one? dgr) (rat->sexp (rat:num p) (rat:denom p)))
(else
(let ((fcts (map irimpl->sexp (univ:split-all p))))
(if (null? (cdr fcts)) (car fcts)
(cons 'or fcts)))))))
((eqn? p) (list '= 0 (poly->sexp (eqn->poly p))))
(else (eval-error 'unknown 'type p))))
(ibunch->sexp p))
(define (get-lambda-list poly)
(do ((j (licits:max-lambda-position poly) (+ -1 j))
(ll '()
(cons (string->symbol (string-append "@" (number->string j))) ll)))
((< j 1) ll)))
;;;MATH->SEXP converts expressions or equations to SEXPRESSIONS.
(define (math->sexp p horner)
(if (clambda? p)
(list 'lambda (list->vector (get-lambda-list
(if (eqn? p) (eqn->poly p) p)))
(bunch->sexp p horner))
(bunch->sexp p horner)))
(define (deferedmath->sexp args)
(let ((form (map (lambda (arg) (bunch->sexp arg #t)) args)))
(if (some clambda? (cdr args))
(list 'lambda
(list->vector (get-lambda-list (cdr args)))
form)
form)))
;;; Copyright 1989, 1990, 1991, 1992, 1993 Aubrey Jaffer.