jacal-1b9/0000755001705200017500000000000010751510041010311 5ustar tbtbjacal-1b9/hist.scm0000644001705200017500000000417710667300650012006 0ustar tbtb;; JACAL: Symbolic Mathematics System. -*-scheme-*- ;; Copyright 1990, 1992, 1993 Aubrey Jaffer. ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or (at ;; your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; This section deals with the user session protocol. ;;; The user can specify a line number prototype or the default can be ;;; used. set prompt sets the prototype. ;;; Subsequent unnumbered lines are assigned labels identical to the ;;; prototype except that the last field (consecutive alphabetic or ;;; consecutive numeric characters) is a unique field of the same type ;;; as the field. ;;; Equations can be referenced by their line numbers by operators ;;; which use equations. Equations given as arguments to functions ;;; generate an error. If the line number of an expression is given ;;; as an argument to an operator, @ = expression is the equation ;;; actually used. ;;; JACAL maintains a data base of equations and line numbers. Each ;;; equation is associated with its line number. The line number of ;;; each expression is associated with = expression. ;;; Each equation in the data base expresses a fact relating variables ;;; to each other. Equations can be removed from the data base by the ;;; command dismiss();. ;;; When a symbol which is a line number is used in an expression or ;;; as an argument to a function, the database is searched for an ;;; equation referencing that symbol. One of those equations is used ;;; to eliminate variables or simplify the expression. jacal-1b9/hensel.scm0000644001705200017500000003776310667300650012324 0ustar tbtb;; "hensel.scm" Multivariate Hensel Lifting. -*-scheme-*- ;; Copyright 1994, 1995 Mike Thomas ;; Copyright 1996, 1997, 1998, 1999, 2002 Aubrey Jaffer ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or (at ;; your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. (require 'univariate-hensel) (require 'random) (require 'factor) (require 'combinatorics) (require 'common-list-functions) (require 'rev4-optional-procedures) ;;; Same but multivariate, uses poly:modularize in poly.scm and using ;;; sym:sym instead of modulo. (define (ff:mnorm modulus poly) (poly:modularize (symmetric:modulus modulus) poly)) ;;; m-th Taylor series coefficient in expansion about var = n (define (taylor-coefficient poly var n m) (poly:/ (poly:evaln (let loop ((i 1) (fn poly)) (if (> i m) fn (loop (+ 1 i) (poly:diff fn var)))) var n) (factorial m))) ;;; Substitute an updated leading coefficient into each member of u. ;;; The member of the correct leading coefficients in lcu corresponding ;;; to a factor in u, is reduced mod the ideal id. (define (lcsubst u lcu id pl) (let* ((save (map (lambda (x) (butlast x 1)) u)) (unsubs (map (lambda (x y) (append x (list y))) save lcu))) (map (lambda (x) (let loop ((i id)) (cond ((null? i) x) (else (set! x (ff:mnorm pl (poly:evaln x (caar i) (cadar i)))) (loop (cdr i)))))) unsubs))) ;;; Go through a polynomial and convert each zero degree polynomial ;;; coefficient to a number. (define (poly:0-degree-norm p) ;;;(ff:print p) (cond ((number? p) p) ((= (length p) 2) (poly:0-degree-norm (cadr p))) (else (let ((end-bit (map-no-end-0s poly:0-degree-norm (cdr p)))) (if (null? end-bit) 0 (cons (car p) end-bit)))))) ;;;; GCL Algorithm 6.4 (p. 272) ;;; ;;; a: A mutivariate polynomial a(x_1, ..., x_v) element Z[x_1, ..., x_v] ;;; which is primitive as a polynomial in the special variable x_1. ;;; ;;; I: a list of equations [x_2 = al_2, ..., x_v = al_v] ;;; representing the evaluation homomorphism used; ;;; lcoeff(a, x_1) /= 0 (mod I). ;;; ;;; p: prime integer which does not divide lcoeff(a mod I). ;;; ;;; l: a positive such that p^l/2 bounds the magnitudes of all ;;; integers appearing in a and in any of its factors to be computed. ;;; ;;; u: a list of n>1 univariate polynomials in Z_p^l[x_1] which are ;;; pairwise relatively prime in the Euclidean domain Z_p[x_1], ;;; such that a = u_1 * ... * u_n (mod ). ;;; ;;; lcu: a list of the n correct multivariate leading coefficients ;;; corresponding to the univariate factors u. ;;; MJT: Assumes that the leading coefficient of a given multivariate ;;; polynomial is the last one. (define (hen:multivariate-hensel a I p l u lcu) (let* ((nu-1 (length I)) (nu (+ nu-1 1)) (pl (expt p l)) (av (make-vector nu a)) ;Partly substituted targets (iv (make-vector nu '()))) ;Partial ideals for leading coefficients (do ((j (+ -2 nu) (+ -1 j))) ((negative? j)) (let ((xj (car (list-ref I j))) (alphaj (cadr (list-ref I j)))) (vector-set! iv j (list-tail I j)) (vector-set! av j (poly:evaln (vector-ref av (+ 1 j)) xj alphaj)))) (let* ((maxdeg (apply max (map (lambda (x) (poly:degree a (car x))) I))) (bu u) (n (length u))) (do ((j 0 (+ 1 j))) ((>= j nu-1)) (let* ((bu1 bu) (monomial 1) (e 1) (xj (car (list-ref I j))) (alphaj (cadr (list-ref I j))) (ij (list xj (- alphaj) 1))) (set! bu (lcsubst bu lcu (vector-ref iv (+ 1 j)) pl)) (set! e (poly:- (vector-ref av (+ 1 j)) (reduce poly:* bu))) (let loop1 ((k 1) (monomial ij)) (if (and (not (eqv? 0 e)) (<= k (poly:degree (vector-ref av (+ 1 j)) xj))) (let ((c (taylor-coefficient e xj alphaj k))) (if (not (poly:0? c)) (let* ((du1 (hen:multivariate-diophant bu1 (number->poly c (car (car bu1))) (butlast I (- nu-1 j)) maxdeg p l)) (du (map (lambda (x) (poly:0-degree-norm (poly:* x monomial))) du1))) (set! bu (map (lambda (x y) (ff:mnorm pl (poly:0-degree-norm (poly:+ x y)))) bu du)) (set! e (ff:mnorm pl (poly:0-degree-norm (poly:- (vector-ref av (+ 1 j)) (reduce poly:* bu))))))) (loop1 (+ 1 k) (poly:* monomial ij))))))) (if (equal? a (poly:0-degree-norm (reduce-init poly:* 1 bu))) bu #f)))) ;;;; GCL Algorithm 6.2 (p. 268) partly tested by MJT ;;; ;;; Solve in the domain Z_p^k[x_1, ..., x_v] the multiariate polynomial ;;; diophantine equation: ;;; S_1 * b_1 + ... + S_r * b_r = c (mod ). ;;; where, in terms of the given list of polynomials a_1, ..., a_r, ;;; the polynomials b_i, i = 1, ..., r, are defined by: ;;; b_i = a_1 * ... * a_i-1 * a_i+1 * ... a_r. ;;; The unique solution S_1, ..., S_r, will be computed such that ;;; deg(S_i, x_1) < deg(a_i, x_1). ;;; ;;; CONDITIONS: ;;; mod using symmetric representation. ;;; ;;; p must not divide lcoeff(a_i mod I), i = 1, ..., r; ;;; ;;; a_i mod , i = 1, ..., r, must be pairwise relatively prime ;;; in Z_p[x]; and ;;; ;;; degree(c, x_1) < sum(degree(a_i, x_1), i = 1, ..., r. ;;; ;;; INPUTS: ;;; a: A list of r > 1 polynomials in the domain Z_p^k[x_1, ..., x_v] ;;; ;;; c: A polynomial element of Z[x_1, ..., x_v] ;;; ;;; I: a list of equations [x_2 = al_2, ..., x_v = al_v] ;;; representing an evaluation homomorphism. ;;; Empty for univariate problems. ;;; ;;; d: nonnegative integer specifying the maximum total degree ;;; with respect to x_2, ..., x_v of the desired result. ;;; ;;; p: a prime integer. ;;; ;;; k: a positive integer specifying that the coefficient arithmetic ;;; is to be performed modulo p^k ;;; ;;; OUTPUT: Returns the list [S_1, ..., S_r] (define (hen:multivariate-diophant a c I d p k) (let* ((r (length a)) (nu-1 (length I)) (nu (+ nu-1 1)) (p^k (expt p k))) (if (> nu 1) (let* ((ap (reduce-init poly:* 1 a)) (b (map (lambda (x) (poly:/ ap x)) a)) (xnu (car (list-ref I (- nu-1 1)))) (alphanu (cadr (list-ref I (- nu-1 1)))) (anew (map (lambda (x) (poly:evaln x xnu alphanu)) a)) (cnew (poly:evaln c xnu alphanu)) (inew (del (list xnu alphanu) I '())) (sigma (hen:multivariate-diophant anew cnew inew d p k)) (e (ff:mnorm p^k (poly:- c (reduce-init poly:+ 0 (map poly:* sigma b))))) (monomial 1)) (let loop ((m 1)) (cond ((and (<= m d) (not (poly:0? e))) (set! monomial (poly:* monomial (poly:- (var->expl xnu) alphanu))) (let ((cm (taylor-coefficient e xnu alphanu m))) (if (not (poly:0? cm)) (let ((ds (hen:multivariate-diophant anew cm inew d p k))) (set! ds (map (lambda (x1) (poly:* x1 monomial)) ds)) (set! sigma (map poly:+ sigma ds)) (set! e (ff:mnorm p^k (poly:- e (reduce-init poly:+ 0 (map poly:* ds b))))) ))) (loop (+ 1 m))) (else (map (lambda (x) (ff:mnorm p^k x)) sigma))))) (let* ((x1 (car (car a))) (sigma (make-list r 0)) (c1 (number->poly c x1)) ;So we can deconstruct consistently (dc (poly:degree c1 x1))) (let loop ((m 1)) (if (<= (+ -1 m) dc) (let* ((cm (poly:leading-coeff (list-ref c1 m) x1)) ;;; IF cm = 0 then we don't need to do the diophantine solution. (ds (hen:univariate-diophant a x1 (+ -1 m) p k))) (check-hd1 a x1 (+ -1 m) p k ds) (set! ds (map (lambda (x) (poly:* x cm)) ds)) (set! sigma (map (lambda (x y) (number->poly (poly:+ x y) x1)) sigma ds)) (loop (+ 1 m))))) (map (lambda (x) (ff:unorm p^k x)) sigma))))) ;;; ppoly is primitive polynomial (define (map-svpf-factors ppoly spec-var) (map (lambda (factor-exp) (cons (poly:factorszpp (car factor-exp)) (cdr factor-exp))) (yuniv:square-free-factorization ppoly spec-var))) ;;; Factorise multivariate polynomial over Z (define (poly:factorz poly) (case (length (poly:vars poly)) ((0) (list (list poly 1))) ; number ((1) (prepend-integer-factor ; univariate (* (u:unitz poly) (univ:cont poly)) (let ((primz (u:primz poly))) (map (lambda (x) (list (u:factorsz (car x)) (cadr x))) (yuniv:square-free-factorization primz (car primz)))))) (else ; multivariate (cond (math:trace (math:print 'factoring 'spec-var= (car poly)) (math:write (poleqns->licits poly) *output-grammar*))) (let* ((spec-var (car poly)) (spec-var-poly (var->expl spec-var)) (psign (poly:unitz poly spec-var)) (pcont (unitcan (univ:cont poly))) (ppoly1 (poly:primz poly spec-var)) (spec-var-pf (svpf ppoly1)) (ppoly (poly:/ ppoly1 (poly:^ spec-var-poly spec-var-pf))) (ppolyfactors (cond ((zero? spec-var-pf) (map-svpf-factors ppoly spec-var)) ((number? ppoly) (list (list (list spec-var-poly) spec-var-pf))) (else (cons (list (list spec-var-poly) spec-var-pf) (map-svpf-factors ppoly spec-var))))) (facts (cond ((number? pcont) (prepend-integer-factor (* pcont psign) ppolyfactors)) (else (prepend-integer-factor psign (append (poly:factorz pcont) ppolyfactors)))))) (cond (math:trace (display-diag 'yielding-factors:) (newline-diag) (math:write facts *output-grammar*))) facts)))) (define (unlucky? maxdeg poly1 spec-var) (or (not (= maxdeg (poly:degree poly1 spec-var))) (not (eqv? 1 (poly:gcd (poly:diff poly1 spec-var) poly1))))) ;;; Make a random ideal for the list of variables ivars with the ;;; random numbers > 1 and <= r. Each variable must have a unique ;;; value to assist in sorting out leading coefficients. ;;; r > (length ivars) + (length nums) ;;; nums is a list of numbers which cannot appear in the ideal. ;;; The random number must be greater than one to enable the recognition of ;;; multiple factors in the leading coefficient. (define ideal:prngs (make-random-state "repeatable seed for making random ideals")) (define (make-random-ideal ivars nums r) (define (mri ivars sofar nums r) (if (null? ivars) sofar (let ((rn (let loop ((rn1 (+ 2 (random r ideal:prngs)))) (if (member rn1 nums) (loop (+ 2 (random r ideal:prngs))) rn1)))) (mri (cdr ivars) (cons rn sofar) (cons rn nums) r)))) (if (> (+ (length ivars) (length nums)) r) (math:error 'make-random-ideal "r too small." ivars nums r)) (map list ivars (mri ivars '() nums r))) ;;; generate the powers of x for a poly (define (power-list p v) (do ((idx (poly:degree p v) (+ -1 idx)) (lst '() (cons idx lst))) ((negative? idx) lst))) ;;; Evaluate simple univariate polynomials the naive way (define (u:evaln p n) (let ((d+1 (+ 1 (univ:deg p)))) (let loop ((i 2) (i-1 1) (acc (cadr p))) (if (> i d+1) acc (loop (+ 1 i) i (+ acc (* (list-ref p i) (expt n i-1)))))))) ;;; Substitute n into a univariate polynomial p, without assuming ;;; that p is simple numbers in the coefficients. (define (u:evalp p n) (let ((d+1 (+ 1 (univ:deg p)))) (let loop ((i 2) (i-1 1) (acc (cadr p))) (if (> i d+1) acc (loop (+ 1 i) i (poly:+ acc (poly:* (list-ref p i) (poly:^ n i-1)))))))) ;;; Evaluate a polynomial, p, substituting a number n for the variable var ;;; Do some normalisation along the way (define (poly:evaln p var n) ;;;(ff:print "p " p " var " var " n " n) (poly:0-degree-norm (cond ((number? p) p) ((univ:const? p)) ((equal? (car p) var) (if (poly:univariate? p) (u:evaln p n) (reduce poly:+ (map (lambda (x y) (if (number? x) (* x (expt n y)) (poly:* (poly:evaln x var n) (expt n y)))) (cdr p) (power-list p var))))) (else (cons (car p) (map (lambda (x) (if (number? x) x (poly:evaln x var n))) (cdr p))))))) ;;; evaluate a polynomial p mod the ideal i ;;; (An evaluation homomorphism) (define (poly:eval-ideal p i) (define pei (lambda (p i) (if (null? i) p (pei (poly:evaln p (caar i) (cadar i)) (cdr i))))) (pei p i)) ;;; Generate the list of correct leading coefficients ;;; ;;; uniqs - association list of a unique prime factor for each leading ;;; coefficient of a polynomial's factors, evaluated over some ideal and ;;; their corresponding unevaluated multivariate factors. ;;; ;;; imagelcs - factors of the leading coefficient of the univariate ;;; image of the polynomial, evaluated over the same ideal. (define (correct-lcs uniqs imagelcs lc) (define lun (length uniqs)) (map (lambda (imagelc) (define res 1) (let loop ((i 0)) (cond ((and (not (equal? 1 lc)) (< i lun)) (let* ((current (list-ref uniqs i)) (unique-prime (car current)) (fact (cadr current))) (let loop1 () (cond ((and (divides? unique-prime imagelc) (poly:/? lc fact)) (set! res (poly:* fact res)) (set! imagelc (quotient imagelc unique-prime)) (set! lc (poly:/ lc fact)) (loop1))) (loop (+ 1 i))))) (else res)))) imagelcs)) ;;; Strip a list of factors and powers of the powers (define (strip-powers l acc) (if (null? l) acc (strip-powers (cdr l) (append (caar l) acc)))) ;;; Factorise square-free primitive multivariate polynomial over Z (sorted) (define (poly:factorszpp ppoly) (if (number? ppoly) ppoly (let* ((vars (poly:vars ppoly)) (spec-var (car ppoly)) (maxdeg (poly:degree ppoly spec-var)) (ivars (del spec-var vars '())) (nivars (length ivars)) (lcpoly (poly:leading-coeff ppoly spec-var)) (lcfactors (if (number? lcpoly) (remove-duplicates (factor lcpoly)) (strip-powers (poly:factorz lcpoly) '()))) (lcnums (apply append (map (lambda (x) (if (number? x) (list x) '())) lcfactors))) (nlcnums (length lcnums)) (nlcfs (length lcfactors))) (let loop ((start 1)) (let* ((image ppoly) (iu (let loopi ((mr+1 (+ nivars nlcnums 2)) (random-ideal (make-random-ideal ivars lcnums (+ nivars nlcnums 3)))) (let* ((poly1 (poly:eval-ideal image random-ideal)) (elcfactors (map (lambda (x) (remove-duplicates (factor (poly:eval-ideal x random-ideal)))) lcfactors)) (us (uniques elcfactors))) (cond ((or (unlucky? maxdeg poly1 spec-var) (some null? us)) ;;(@print mr+1 (+ nivars nlcnums 100)) (if (> mr+1 (+ nivars nlcnums 100)) (math:error 'poly:factorszpp (- mr+1 (+ nivars nlcnums)) " tries on" lcnums) (loopi (+ mr+1 1) (make-random-ideal ivars lcnums mr+1)))) (else (set! image poly1) (list random-ideal (if (eqv? 1 lcpoly) (make-list nlcfs '(1 1)) (map list (map car us) lcfactors)))))))) (ideal (car iu)) (uniqs (cadr iu)) (p (let loopp ((cp 3)) (cond ((and (= maxdeg (ff:degree cp image)) (every (lambda (x) (eqv? 1 x)) (map cadr (ff:sff cp image)))) cp) ((> cp 1000) (math:error 'poly:factorszpp " tried all primes up to " cp)) (else (loopp (car (primes> (+ 1 cp) 1))))))) (image-factors (let* ((slpoly (u:unitz image)) (cpoly (univ:cont image)) (factors (poly:sort-factors (u:factorsz image)))) (if (and (= cpoly 1) (= slpoly 1)) factors (cons (list spec-var (* slpoly cpoly)) factors)))) (imagelcs (map (lambda (p) (univ:lc p)) image-factors)) (k (u:prime-power image p))) (if (= (length image-factors) 1) (list ppoly) (let* ((clcs (correct-lcs uniqs imagelcs lcpoly)) (res (hen:multivariate-hensel ppoly ideal p k image-factors clcs))) (if (not res) (if (> start 30) (math:error 'poly:factorszpp "too many tries." start) (loop (+ 1 start))) res)))))))) jacal-1b9/jacal.nsi0000644001705200017500000001732310751113535012113 0ustar tbtb; Install JACAL on Windows for current user ; Basic script generated by the HM NIS Edit Script Wizard. ; Augmented by Jerry van Dijk, march 2007 ; placed in the public domain ; *** version numbers *** !define PRODUCT_VERSION "1b9-1" ; ----------------[ NO CHANGES BELOW ]---------------- ; *** unless files are added or removed *** ; *** remember to edit both 'file' and 'delete' sections! ; *** registry settings *** !define KEY_VERSION "version" !define SCM_KEY "Software\Voluntocracy\scm" !define JACAL_KEY "Software\Voluntocracy\jacal" ; HM NIS Edit Wizard helper defines !define PRODUCT_NAME "JACAL" !define PRODUCT_COMPANY "Voluntocracy" !define PRODUCT_PUBLISHER "Aubrey Jaffer" !define PRODUCT_WEB_SITE "http://swissnet.ai.mit.edu/~jaffer/JACAL" !define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\jacal-${PRODUCT_VERSION}.exe" !define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" !define PRODUCT_UNINST_ROOT_KEY "HKLM" !define PRODUCT_STARTMENU_REGVAL "NSIS:StartMenuDir" ; MUI 1.67 compatible ------ !include "MUI.nsh" ; MUI Settings !define MUI_ABORTWARNING !define MUI_ICON "equal.ico" !define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico" ; Welcome page !insertmacro MUI_PAGE_WELCOME ; License page !insertmacro MUI_PAGE_LICENSE "COPYING" ; Directory page !insertmacro MUI_PAGE_DIRECTORY ; Start menu page var ICONS_GROUP !define MUI_STARTMENUPAGE_NODISABLE !define MUI_STARTMENUPAGE_DEFAULTFOLDER "jacal" !define MUI_STARTMENUPAGE_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}" !define MUI_STARTMENUPAGE_REGISTRY_KEY "${PRODUCT_UNINST_KEY}" !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${PRODUCT_STARTMENU_REGVAL}" !insertmacro MUI_PAGE_STARTMENU Application $ICONS_GROUP ; Instfiles page !insertmacro MUI_PAGE_INSTFILES ; Finish page !insertmacro MUI_PAGE_FINISH ; Uninstaller pages !insertmacro MUI_UNPAGE_INSTFILES ; Language files !insertmacro MUI_LANGUAGE "English" ; MUI end ------ Name "${PRODUCT_NAME} ${PRODUCT_VERSION}" OutFile "jacal-${PRODUCT_VERSION}.exe" InstallDir "$PROGRAMFILES\jacal" InstallDirRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_DIR_REGKEY}" "" ShowInstDetails show ShowUnInstDetails show Function .onInit ; Check that scm is installed ClearErrors ReadRegStr $0 ${PRODUCT_UNINST_ROOT_KEY} "${SCM_KEY}" "${KEY_VERSION}" IfErrors 0 +3 MessageBox MB_OK|MB_ICONSTOP "No SCM found. Please install SCM before installing JACAL." Abort FunctionEnd Section "MainSection" SEC01 SetOutPath "$INSTDIR" SetOverwrite try File "ANNOUNCE" File "builtin.scm" File "ChangeLog" File "combin.scm" File "COPYING" File "debug.scm" File "demo" SetOutPath "$INSTDIR\DOC" File "DOC\algdenom" File "DOC\eqalign.sty" File "DOC\grammar" File "DOC\history" File "DOC\lambda" File "DOC\ratint.pdf" File "DOC\ratint.tex" SetOutPath "$INSTDIR" File "elim.scm" File "English.scm" File "ext.scm" File "equal.ico" File "factors.scm" File "fdl.texi" File "ff.scm" File "func.scm" File "grammar.scm" File "HELP" File "hensel.scm" File "hist.scm" File "info.scm" File "jacal.html" File "jacal.nsi" File "jacal.spec" File "jacal.texi" File "jacalcat" File "Makefile" File "math.scm" File "modeinit.scm" File "norm.scm" File "poly.scm" File "README" File "rw.math" File "sexp.scm" File "sqfree.scm" File "tensor.scm" File "test.math" File "toploads.scm" File "types.scm" File "unparse.scm" File "uv-hensel.scm" File "vect.scm" File "version.txi" File "view.scm" ; Shortcuts !insertmacro MUI_STARTMENU_WRITE_BEGIN Application CreateDirectory "$SMPROGRAMS\$ICONS_GROUP" CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Manual.lnk" "$INSTDIR\jacal.html" CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\JACAL.lnk" "scm.exe" '-iql"$INSTDIR\math.scm" -ie"(math)"' "$INSTDIR\equal.ico" CreateShortCut "$DESKTOP\JACAL.lnk" "scm.exe" '-iql"$INSTDIR\math.scm" -ie"(math)"' "$INSTDIR\equal.ico" !insertmacro MUI_STARTMENU_WRITE_END ; Jaffer jacal registry settings WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${JACAL_KEY}" "${KEY_VERSION}" "${PRODUCT_VERSION}" SectionEnd Section -AdditionalIcons !insertmacro MUI_STARTMENU_WRITE_BEGIN Application WriteIniStr "$INSTDIR\${PRODUCT_NAME}.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}" CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Website.lnk" "$INSTDIR\${PRODUCT_NAME}.url" CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Uninstall.lnk" "$INSTDIR\uninst.exe" !insertmacro MUI_STARTMENU_WRITE_END SectionEnd Section -Post WriteUninstaller "$INSTDIR\uninst.exe" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}" SectionEnd Function un.onUninstSuccess HideWindow MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) was successfully removed from your computer." FunctionEnd Function un.onInit MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "Are you sure you want to completely remove $(^Name) and all of its components?" IDYES +2 Abort FunctionEnd Section Uninstall !insertmacro MUI_STARTMENU_GETFOLDER "Application" $ICONS_GROUP Delete "$INSTDIR\${PRODUCT_NAME}.url" Delete "$INSTDIR\uninst.exe" Delete "$INSTDIR\view.scm" Delete "$INSTDIR\version.txi" Delete "$INSTDIR\vect.scm" Delete "$INSTDIR\uv-hensel.scm" Delete "$INSTDIR\unparse.scm" Delete "$INSTDIR\types.scm" Delete "$INSTDIR\toploads.scm" Delete "$INSTDIR\test.math" Delete "$INSTDIR\tensor.scm" Delete "$INSTDIR\sqfree.scm" Delete "$INSTDIR\sexp.scm" Delete "$INSTDIR\rw.math" Delete "$INSTDIR\README" Delete "$INSTDIR\poly.scm" Delete "$INSTDIR\norm.scm" Delete "$INSTDIR\modeinit.scm" Delete "$INSTDIR\math.scm" Delete "$INSTDIR\Makefile" Delete "$INSTDIR\jacalcat" Delete "$INSTDIR\jacal.texi" Delete "$INSTDIR\jacal.spec" Delete "$INSTDIR\jacal.nsi" Delete "$INSTDIR\jacal.html" Delete "$INSTDIR\info.scm" Delete "$INSTDIR\hist.scm" Delete "$INSTDIR\hensel.scm" Delete "$INSTDIR\HELP" Delete "$INSTDIR\grammar.scm" Delete "$INSTDIR\func.scm" Delete "$INSTDIR\ff.scm" Delete "$INSTDIR\fdl.texi" Delete "$INSTDIR\factors.scm" Delete "$INSTDIR\ext.scm" Delete "$INSTDIR\equal.ico" Delete "$INSTDIR\English.scm" Delete "$INSTDIR\elim.scm" Delete "$INSTDIR\DOC\ratint.tex" Delete "$INSTDIR\DOC\ratint.pdf" Delete "$INSTDIR\DOC\lambda" Delete "$INSTDIR\DOC\history" Delete "$INSTDIR\DOC\grammar" Delete "$INSTDIR\DOC\eqalign.sty" Delete "$INSTDIR\DOC\algdenom" Delete "$INSTDIR\demo" Delete "$INSTDIR\debug.scm" Delete "$INSTDIR\COPYING" Delete "$INSTDIR\combin.scm" Delete "$INSTDIR\ChangeLog" Delete "$INSTDIR\builtin.scm" Delete "$INSTDIR\ANNOUNCE" Delete "$DESKTOP\JACAL.lnk" Delete "$SMPROGRAMS\$ICONS_GROUP\Uninstall.lnk" Delete "$SMPROGRAMS\$ICONS_GROUP\Website.lnk" Delete "$SMPROGRAMS\$ICONS_GROUP\JACAL.lnk" Delete "$SMPROGRAMS\$ICONS_GROUP\Manual.lnk" RMDir "$SMPROGRAMS\$ICONS_GROUP" RMDir "$INSTDIR\DOC" RMDir "$INSTDIR" ; remove Jaffer registry entries DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${JACAL_KEY}" DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" SetAutoClose true SectionEndjacal-1b9/view.scm0000644001705200017500000000475610667300650012014 0ustar tbtb;; JACAL: Symbolic Mathematics System. -*-scheme-*- ;; Copyright 1989, 1990, 1991, 1992, 1993, 1997 Aubrey Jaffer. ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or (at ;; your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; See Template.scm in the Scheme Library for how to set up ;;; vicinities and require. (require 'with-file) ;(slib:load (in-vicinity (program-vicinity) "scl")) ;Common Lisp/Scheme compatability definitions. ;(slib:load (in-vicinity (program-vicinity) "toploads")) (slib:load (in-vicinity (program-vicinity) "grammar")) (define page-height #f) (define page-width #f) (define *input-grammar* (get-grammar 'scheme)) ;grammar to use if none is loaded. (define *output-grammar* (get-grammar 'scheme)) ;grammar to use if none is loaded. (define *echo-grammar* (get-grammar 'null)) (slib:load (in-vicinity (library-vicinity) "prec")) ;;(prec:trace) (slib:load (in-vicinity (program-vicinity) "unparse")) (slib:load (in-vicinity (program-vicinity) "English")) (define *input-grammar* (get-grammar 'standard)) ;tex (define (view . file) (define obj #f) (define math:prompt ":") ((lambda (doit) (cond ((not (null? file)) (with-input-from-file (car file) doit)) (else (doit)))) (lambda () (define cip (current-input-port)) (let loop () (cond ((output-port? cip) (display math:prompt cip) (force-output cip) (tok:bump-column (string-length math:prompt) cip)) (else (display math:prompt) (force-output) (tok:bump-column (string-length math:prompt) cip))) (set! obj (read-sexp *input-grammar*)) (tok:bump-column 0 cip) (cond ((and (null? file) (not obj))) ((eof-object? obj)) ((not obj) (display "got #f") (newline)) (else (write-sexp obj *output-grammar*) (newline) (loop))))))) ;;(pretty-print (grammar-read-tab *input-grammar*)) (view) ;; scm -ip1 -lmath -e(batch"demo") jacal-1b9/ff.scm0000644001705200017500000004514610667300650011433 0ustar tbtb;; "ff.scm" Polynomial factorization. -*-scheme-*- ;; Copyright 1994, 1995 Mike Thomas ;; Copyright 1995, 1997, 1998, 1999, 2001, 2002 Aubrey Jaffer ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or (at ;; your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; AUTHOR ;;; Mike Thomas ;;; 46 Harold Street ;;; STAFFORD QLD 4053 ;;; AUSTRALIA ;;; ;;; Phone: Intl + 61 7 356 8494 ;;; Email: mjt@octavia.anu.edu.au ;;; SOURCES ;;; These algorithms are drawn from: ;;; ;;; (GCL) ;;; Algorithms for Computer Algebra ;;; by Keith O. Geddes, Stephen R. Czapor, George Labahn ;;; (October 1992) Kluwer Academic Pub; ISBN: 0-7923-9259-0 ;;; ;;; Computer Algebra: Systems and Algorithms for Algebraic Computation ;;; by Y. Siret (Editor), E. Tournier, J. H. Davenport, F. Tournier ;;; 2nd edition (June 1993) Academic Press; ISBN: 0-122-04232-8 ;;; ;;; The Art of Computer Programming : Seminumerical Algorithms (Vol 2) ;;; by Donald Ervin Knuth ;;; 2nd Ed (1981) Addison-Wesley Pub Co; ISBN: 0-201-03822-6 ;;; A new edition of this book is availble: ;;; 3rd Ed (November 1997) Addison-Wesley Pub Co; ISBN: 0-201-89684-2 ;;; DEVELOPMENT LANGUAGE ;;; SCM 4e1, 4e2 compiled with DICE v 2.07.54 ;;; DEVELOPMENT SYSTEM ;;; Amiga 1200, 2Mb Chip RAM, 4Mb Fast RAM, 50MHz 68030 CPU No FPU, ;;; Workbench 3.0 (until a power supply problem stuffed it that is.) ;;; DEPENDENCIES ;;; You need R4RS Scheme, SLIB and JACAL (latest versions). ;;; Multiargument *, + ;;; REPRESENTATIONS ;;; The modular homomorphism sym:sym maps the integers to a symmetric ;;; representation, following the numerous examples in GCL. This ;;; mapping does not seem to correspond with GCL's own definition of Z ;;; mod n using a simple remainder algorithm. ;;; The univariate polynomials expected and returned by the Scheme ;;; procedures are JACAL's list representation, not numbers by ;;; themselves. There is no attempt to cover sparse polynomials yet. ;;; An ideal is a list of lists, each one specifying a variable and ;;; it's value eg '((y 1) (z 2) (p -1)). ;;; DESIGN PHILOSOPHY ;;; 1. Fun; ;;; 2. Correct operation for univariate and multivariate polynomials ;;; over the rationals (Q), then maybe over algebraic number fields; ;;; 3. refine the algorithms for speed after they work correctly; ;;; 4. make the system workable even for smaller computers, based on the ;;; crude and discriminatory assumption that people who want to crack ;;; large problems can afford to buy or write larger systems; ;;; 5. and ideally, I want the system to handle investigation of the ;;; stability of systems of differential equations which requires ;;; algebraic solution of eigensystems, and for an attempt on the ;;; Risch integration algorithm. ;;; I have therefore initially used Linear Hensel Lifting and the small ;;; prime Berlekamp Algorithm. I make no attempt yet, among other ;;; possibilities, to optimise the factorisation process dynamically by ;;; checking several primes or restarting the algorithm on testing for ;;; true factors after the Berlekamp process. Later, perhaps. ;;; NAMING ;;; u: univariate polynomials, should be JACAL's univ: ;;; ff: polynomials over finite integer fields using the ;;; symmetric modular representation ;;; sym: symmetric representation of (modular) integers ;;; poly: Jacal polynomial types ;;; hen: Hensel lifting procedures ;;; ABBREVIATIONS ;;; Q: The Rational numbers ;;; Z: The integers ;;; ARGUMENT CODING CONVENTIONS ;;; ff: the modulus argument is the last in the argument list ;;; KNOWN BUGS ;;; -- factor((2*z+y-x)*(y^3*z-a*x^2)*(b*z^2+y)); ;;; factor((a*a*b*z+d)*(2*a*b*b*z+c)*((u+a)*z+1)); ;;; Hang my presently memory challenged computer during poly:sff ;;; probably because of lack of room ;;; -- Parfrac worketh not. Wherefore? Because I trieth too hard to ;;; be clevereth. This one can wait. ;;; -- The result is not always sorted or normalised. ;;; KNOWN MINOR PROBLEMS (FROM MY POINT OF VIEW) ;;; -- Output format sometimes gets misaligned. ;;; -- Speed is not great. See DESIGN PHILOSOPHY above. ;;; -- Factorization over Q needs to return monic polynomials if it is ;;; to produce complete unique unit normal factorisations. ;;; Factorisation over Z and Q would also need to factorise numeric ;;; content in this case. (require 'array) (require 'array-for-each) (require 'fluid-let) (require 'common-list-functions) (require 'modular) (define sym:invert (lambda (m a) (modular:invert (symmetric:modulus m) a))) (define sym:sym (lambda (m a) (modular:normalize (symmetric:modulus m) a))) (define (modulus->array-prototype p . fill) (apply (cond ((not (number? p)) vector) ((negative? p) (let ((len (integer-length (- p)))) (cond ((<= len 8) A:fixZ8b) ((<= len 16) A:fixZ16b) ((<= len 32) A:fixZ32b) (else vector)))) ((positive? p) (let ((len (integer-length (+ -1 p)))) (cond ((<= len 8) A:fixN8b) ((<= len 16) A:fixN16b) ((<= len 32) A:fixN32b) (else vector)))) (else vector)) fill)) (define (sym:array-prototype p . fill) (apply modulus->array-prototype (quotient p -2) fill)) ;;; Reduce univariate p mod n and remove leading zero coefficients (define (ff:unorm n p) (cons (car p) (cons (sym:sym n (cadr p)) (map-no-end-0s (lambda (x) (sym:sym n x)) (cddr p))))) ;;; Degree of (ff:unorm n p) (define (ff:degree n p) (- (length (ff:unorm n p)) 2)) (define (ff:lc n p) (sym:sym n (univ:lc p))) (define (ff:monic? n p) (and (not (univ:const? p)) (eqv? 1 (ff:lc n p)))) ;;; Printer for diagnostic information (define (ff:print . args) (define result #f) (for-each (lambda (x) (set! result x) (display-diag x) (display #\space)) args) (newline-diag) result) ;;;================================================================ ;;; Standard Euclidean algorithm for polynomial gcd over Z mod n (define ff:euclid-gcd (lambda (modulus x y) (set! x (ff:unorm modulus x)) (set! y (ff:unorm modulus y)) (fluid-let ((*modulus* (symmetric:modulus modulus))) (cond ((univ:zero? x) (univ:make-monic y)) ((univ:zero? y) (univ:make-monic x)) (else (let ((ans (univ:fgcd x y))) (if (number? ans) (list (car x) ans) ans))))))) ;;; ===================== Truncating Division ===================== (define ff:p/p->qr ;;(debug:check ff:p/p->qr-mjt (lambda (modulus x y) (set! x (ff:unorm modulus x)) (set! y (ff:unorm modulus y)) (if (< (length x) (length y)) (list (list (car x) 0) (ff:unorm modulus x)) (fluid-let ((*modulus* (symmetric:modulus modulus))) (map (lambda (ans) (if (number? ans) (list (car x) ans) ans)) (univ:fdiv x y))))) ;;'ff:p/p->qr-mjt ;;'univ:fdiv) ) (define (ff:p/p p a b) (let ((u (ff:unorm p a)) (v (ff:unorm p b))) (let ((m (univ:deg u)) (n (univ:deg v))) (cond ((univ:zero? v) (slib:error 'ff:p/p "Division by 0 is undefined.")) (else (car (ff:p/p->qr p u v))))))) ;;; ===================== Top-Level Factoring ===================== (define (u:sff a) (define ppoly (poly:primpart a)) (poly:sort-factors (yuniv:square-free-factorization ppoly (car ppoly)))) (define (ff:diff n p v) (if (equal? (car p) v) (do ((i (- (length p) 1) (+ -1 i)) (r '() (cons (sym:sym n (* (+ -1 i) (list-ref p i))) r))) ((< i 2) (cons v r))) (list v 0))) (define (ff:gfroot n p var) (let ((d (ff:degree n p))) (if (zero? (sym:sym n d)) (let* ((u (quotient d n)) (v (make-vector (+ 1 u) 0))) (vector-set! v u 1) (vector-set! v 0 1) (cons var (vector->list v))) (slib:error 'ff:gfroot "polynomial has no root." p)))) (define (ff:sff p a) (let* ((v (car a)) (b (ff:diff p a v)) (output '())) (cond ((univ:zero? b) (set! a (ff:gfroot p a v)) (set! output (append output (list (list (ff:sff p a) p))))) (else (let* ((c (ff:euclid-gcd p a b)) (w (ff:p/p p a c)) (y 0) (z 0)) (let loop ((i 1)) (cond ((not (univ:one? w v)) (set! y (ff:euclid-gcd p w c)) (set! z (ff:p/p p w y)) (if (not (univ:one? z v)) (set! output (append output (list (list z i))))) (set! w y) (set! c (ff:p/p p c y)) (loop (+ 1 i))))) (cond ((not (univ:one? c v)) (set! c (ff:gfroot p c v)) (set! output (append output (list (list (ff:sff p c) p))))))))) output)) (define (ff:q-matrix p a) (define n #f) (set! a (ff:unorm p a)) (set! n (univ:deg a)) (let ((n-1 (+ -1 n)) (q (make-array (A:fixZ32b 0) n n)) (r (make-array (A:fixZ32b 0) n)) (r1 (make-array (A:fixZ32b 0) n)) (b (list->vector a)) (u (* (+ -1 n) p))) (array-set! q 1 0 0) (array-set! r 1 0) (array-set! r1 1 0) (let loop ((i 1)) (cond ((> i u) q) (else (array-set! r (* (vector-ref b 1) (- 0 (array-ref r1 n-1))) 0) (let loop1 ((j 1)) (cond ((<= j n-1) (array-set! r (sym:sym p (- (array-ref r1 (+ -1 j)) (sym:sym p (* (vector-ref b (+ 1 j)) (array-ref r1 n-1))))) j) (loop1 (+ 1 j))))) (array-map! r1 identity r) (if (zero? (modular:normalize p i)) (array-map! (make-shared-array q (lambda (j) (list (quotient i p) j)) n) identity r)) ;;(ff:print i " r = " r " q = " q) (loop (+ 1 i))))))) ;;; Converts a list of vectors to a vector of polynomials. (define (basis->polys basis var) (list->vector (map (lambda (vr) (do ((idx (+ -1 (car (array-dimensions vr))) (+ -1 idx)) (lst '() (if (and (null? lst) (eqv? 0 (array-ref vr idx))) '() (cons (array-ref vr idx) lst)))) ((<= idx 0) (cons var (cons (array-ref vr 0) lst))))) basis))) ;;; MJT: Knuth's null-space-basis, slower but works. ;;; ;;; AJ: ff:null-space-basis does its calculations in symmetric modular ;;; form. But Knuth's example is vanilla mod 13. ff:null-space-basis ;;; should be reworked using *modulus*. ;;; ;;; The Art of Computer Programming : Seminumerical Algorithms (Vol 2) ;;; by Donald Ervin Knuth ;;; 2nd Ed (1981) Addison-Wesley Pub Co; ISBN: 0-201-03822-6 ;;; 4.6.2 Algorithm N (null-space-algorithm) ;;; ;;; P is prime modulus of coeffient field. ;;; Q-I is an N by N matrix of elements of Z mod P. ;;; Returns a list of {N - rank(Q-I)} basis vectors. (define (ff:null-space-basis p Q-I) (define n (car (array-dimensions Q-I))) (define prot (sym:array-prototype p)) (let ((m (make-array prot n n)) (c (make-vector n -1)) (ivec (array-indexes (make-array (A:fixN16b 1) n))) (basis '())) (array-map! ivec car ivec) (array:copy! m Q-I) (do ((k 0 (+ 1 k))) ((>= k n) (reverse basis)) (let ((j (do ((b 0 (+ 1 b))) ((or (>= b n) (and (negative? (vector-ref c b)) (not (zero? (array-ref m k b))))) b)))) (if (< j n) (let ((muinv (* -1 (sym:invert p (array-ref m k j)))) (mcolj (make-shared-array m (lambda (a) (list a j)) n))) (array-map! mcolj (lambda (x) (sym:sym p (* x muinv))) mcolj) (vector-set! c j k) (do ((i 0 (+ 1 i))) ((>= i n)) (if (not (= i j)) (let ((mcoli (make-shared-array m (lambda (a) (list a i)) n)) (mki (array-ref m k i))) (array-map! mcoli (lambda (x y z) (if (>= z k) (sym:sym p (+ x (* mki y))) x)) mcoli mcolj ivec))))) (let ((vr (make-array prot n)) (cl (vector->list c))) (array-map! vr (lambda (i) (let ((cl1 (memv i cl))) (cond ((= i k) 1) (cl1 (array-ref m k (- n (length cl1)))) (else 0)))) ivec) (set! basis (cons vr basis)))))))) ;;; -- > (u:factorz p7) ; ERROR: vector-ref: Argument out of range 2 ; ;Evaluation took 1934 mSec (601 in gc) 19181 cells work, 6439 bytes other ; > p7 ; ;Evaluation took 1 mSec (0 in gc) 2 cells work, 31 bytes other ; (x 1 -3 -1 -3 1 -3 1) ; > (math) ; type qed; to return to scheme, type help; for help. ; e5 : factoruz(1-3*x-x^2-3*x^3+x^4-3*x^5 +x^6); ; poly = (#(x x #f () #f ()) 1 -3 -1 -3 1 -3 1) ; e1 = (#(x x #f () #f ()) 1 -3 -1 -3 1 -3 1) ; Arithmetic Error; Last expression lost. ;;; This problem is caused by berlekamp expecting to find factors when ;;; there are none (ie the polynomial is irreducible). This problem ;;; comes from the ff:null-space-basis-gcl-bug procedure below. This ;;; is the only occurrence of this problem I am aware of. ;;; Fixed by using Knuth's null space basis algorithm above. ;;; Unfortunately, this one is faster. (define (ff:null-space-basis-gcl-bug p Q-I var) (let* ((n (car (array-dimensions Q-I))) (m (make-array '#(#f) n n))) (ff:print " Q-I = " Q-I) (array:copy! m Q-I) (do ((k 0 (+ 1 k))) ((>= k n)) (let ((i (do ((b k (+ 1 b))) ((or (>= b n) (not (zero? (array-ref m k b)))) b)))) (if (< i n) (let* ((u (array-ref m k i)) (uinv (sym:invert p u)) (mcoli (make-shared-array m (lambda (a) (list a i)) n)) (mcolk (make-shared-array m (lambda (a) (list a k)) n)) (temp (make-array '#(#f) n))) (array-map! mcoli (lambda (x) (sym:sym p (* x uinv))) mcoli) (array-map! temp identity mcoli) (array-map! mcoli identity mcolk) (array-map! mcolk identity temp) (do ((j 0 (+ 1 j))) ((>= j n)) (if (not (= j k)) (let ((mcolj (make-shared-array m (lambda (a) (list a j)) n)) (mkj (array-ref m k j))) (array-map! mcolj (lambda (x y) (sym:sym p (- x (sym:sym p (* mkj y))))) mcolj mcolk)))) ;;;(ff:print " m = " m) )))) (let ((mdiag (make-shared-array m (lambda (a) (list a a)) n))) (array-map! mdiag (lambda (x) (sym:sym p (+ -1 x))) mdiag)) ;;; (ff:print " After subtraction of 1 along the diagonal, m = " m) ;;; (array-map! m (lambda (x) (sym:sym p (* -1 x))) m) ;;; (ff:print " After multiplication of -1 along the diagonal, m = " m) (let (;;(i 0) (ret '())) (let loop1 ((j 0)) (if (< j n) (let ((zerow (make-vector n 0))) (let loop2 () (if (< j n) (let ((mrow (make-shared-array m (lambda (a) (list j a)) n))) (cond ((array-equal? mrow zerow) (set! j (+ 1 j)) (loop2)))))) (if (< j n) (let ((v (make-vector n 0)) (mrowj (make-shared-array m (lambda (a) (list j a)) n))) ;;(set! i (+ 1 i)) ;;; (ff:print " mrowj = " mrowj) (array:copy! v mrowj) ;;; (ff:print " v = " v) (set! ret (cons v ret)) (loop1 (+ 1 j))))))) ;;; (ff:print " ret = " ret) (map (lambda (x) (ff:unorm p (cons var (vector->list x)))) (reverse ret))))) ;;; return an ordered list of elements of Z mod n (symmetric) (define (ff:generate-field n) (define b (quotient (+ -1 n) 2)) (do ((idx (+ -1 n) (+ -1 idx)) (lst '() (cons (- idx b) lst))) ((negative? idx) lst))) ;;; Return a sorted list of factors of a mod p, where a is square free ;;; and p is a prime number. (define (ff:berlekamp p a) (let* ((q (ff:q-matrix p a)) (n (car (array-dimensions q))) (var (car a)) (qdiag (make-shared-array q (lambda (a) (list a a)) n))) (array-map! qdiag (lambda (x) (sym:sym p (+ -1 x))) qdiag) (fluid-let ((*modulus* (symmetric:modulus p))) (let* ((vs (basis->polys (ff:null-space-basis p q) var)) (factors (list a)) (ffp (ff:generate-field p)) (k (vector-length vs))) (do ((r 1 (+ 1 r))) ((not (< (length factors) k)) (poly:sort-factors factors)) (do ((us factors (if start factors (cdr us))) (start #f #f)) ((not (and (< (length factors) k) (not (null? us))))) (let ((u (car us))) (let loop3 ((ss ffp)) (cond ((and (not (null? ss)) (< (length factors) k)) ;;(print '!) (let ((g (ff:euclid-gcd ;poly:gcd p (poly:- (vector-ref vs r) (car ss)) ;(list var ) u))) (cond ((and (not (equal? g u)) (not (univ:one? g var))) (set! factors (delete u factors)) (set! u (ff:p/p p u g)) (set! factors (delete '() (append factors (list u) (list g)))) (set! start #t)) (else (loop3 (cdr ss))))))))))))))) ;;; Partial fraction expansion of a rational univariate polynomial ;;; The denominator, dr, must be square free. (define (u:partial-fraction-expand nr dr) (let* ((drfs1 (u:factorq dr)) (drfs (remove-exponents drfs1 '())) (p 3) (k 5) (ss (hen:diophantine drfs (list (car (car drfs)) 1) p k))) (let ((res (map (lambda (x y) (make-rat (poly:* nr x) y)) ss drfs))) (ff:print res) res))) (define (remove-exponents fs fs1) (cond ((null? fs) fs1) ((number? (caar fs)) (ff:print "n " (caar fs)) (remove-exponents (cdr fs) (fs1))) (else (ff:print "e " (caar fs)) (remove-exponents (cdr fs) (append (caar fs) fs1))))) (define (ff:check-arg e) (cond ((not (poly:univariate? e)) (bltn:error 'not-a-univariate-polynomial e)))) (define (ff:check-prime n) (cond ((not (prime? n)) (bltn:error 'not-a-prime-number n)))) (defbltn 'sff (lambda (poly) (let ((e (licit->polxpr poly))) (if (not (eqv? 1 (unitcan (univ:cont e)))) (bltn:error 'not-a-primitive-polynomial poly) (u:sff e))))) (defbltn 'usff (lambda (poly) (let ((e (licit->polxpr poly))) (ff:check-arg e) (cond ((not (equal? e (u:primz e))) ;this test should be replaced (bltn:error 'not-a-primitive-polynomial poly)) (else (u:sff e)))))) (defbltn 'ffsff (lambda (poly pn . k1) (let ((p (licit->polxpr poly)) (n (licit->polxpr pn)) (k (licit->polxpr (if (null? k1) 1 (car k1))))) (ff:check-arg p) (ff:check-prime n) (cond ((not (ff:monic? n p)) (bltn:error 'not-monic-mod-n p)) ((not (> k 0)) (bltn:error 'not-greater-than-zero k)) (else (ff:sff (expt n k) p)))))) (defbltn 'berl (lambda (poly pn) (let ((p (licit->polxpr poly)) (n (licit->polxpr pn))) (ff:check-arg p) (ff:check-prime n) (cond ((not (ff:monic? n p)) (bltn:error 'not-monic-mod-n p)) ((not (= (univ:deg p) (ff:degree n p))) (bltn:error 'not-same-degree-when-reduced-mod-n (ff:norm p n))) (else (ff:berlekamp n p)))))) (defbltn 'parfrac (lambda (poly) (let ((e1 (expr:normalize poly))) (u:partial-fraction-expand (num e1) (denom e1))))) jacal-1b9/debug.scm0000644001705200017500000000731610667300650012123 0ustar tbtb;;; JACAL: Symbolic Mathematics System. -*-scheme-*- ;;; Copyright 1989, 1990, 1991, 1992, 1993, 1995, 1996, 1997, 2002 Aubrey Jaffer. ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or (at ;; your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; The following are useful for debugging representational and other ;;; problems. ;;; (POLY:VALID? obj) returns #t if the variable ordering in obj is ;;; consistent with respect to var:>. ;;; SCM has (STACK-TRACE), which prints evaluation pending expressions. ;;; To print out an expression in the current output format, do: ;;; (write-sexp (cano->sexp exp #f) *output-grammar*) (force-output) ;;; (MATH:BREAK-WITH-OBJECT MSG OBJ) prints MSG, sets the jacal ;;; variable errobj to OBJ, and breaks to the jacal prompt. ;;; (MATH:CONTINUABLE-BREAK-WITH-OBJECT MSG OBJ) prints MSG, sets the ;;; jacal variable errobj to OBJ, saves its continuation and breaks to ;;; the jacal prompt. (require 'polynomial-factors) (require 'debug) (define math:break-continuation-stack '()) (define (math:break-with-object msg obj) (display-diag msg) (newline-diag) (display-diag " Offending object is now value of errobj.") (newline-diag) (defsym 'errobj obj) (math:exit #f)) (define (math:continuable-break-with-object msg obj) (display-diag msg) (newline-diag) (display-diag " Offending object is now value of errobj.") (newline-diag) (display-diag " To continue type continue(RETURN-VALUE);") (newline-diag) (defsym 'errobj obj) (call-with-current-continuation (lambda (cont) (set! math:break-continuation-stack (cons cont math:break-continuation-stack)) (math:exit #f)))) (define (qpn . args) (force-output) (for-each (lambda (x) (math:print x) (if (symbol? x) (display-diag #\space) (newline-diag))) args)) (define (print . args) (define result #f) (for-each (lambda (x) (set! result x) (math:print x) (display-diag #\space)) args) (newline-diag) result) (define (debug:check proc1 proc2 . opts) (lambda args (let ((result1 (apply proc1 args)) (result2 (apply proc2 args))) (cond ((not (equal? result1 result2)) (newline-diag) (display-diag "WARN:") (for-each (lambda (x) (display-diag #\space) (write-diag x)) opts) (display-diag " results not equal?") (newline-diag) (display-diag " args:") (for-each (lambda (x) (display-diag #\space) (math:print x)) args) (newline-diag) (display-diag (if (null? opts) "{1}" (car opts))) (display-diag " ==> ") (math:print result1) (newline-diag) (display-diag (if (or (null? opts) (null? (cdr opts))) "{1}" (cadr opts))) (display-diag " ==> ") (math:print result2) (newline-diag))) result1))) ;;; Wrap POLY:FACTOR< with check for well-ordering. (define poly:factor< (let ((factor< poly:factor<)) (lambda (x y) (define x License: GPL Vendor: Aubrey Jaffer Group: Sciences/Mathematics Provides: jacal BuildArch: noarch Requires: slib Summary: The JACAL Symbolic Math System Source: ftp://swiss.csail.mit.edu/pub/scm/jacal-%{version}.zip URL: http://swiss.csail.mit.edu/~jaffer/JACAL.html BuildRoot: %{_tmppath}/%{name}-%{version} Prefix: %{_prefix} %description JACAL is an interactive symbolic mathematics program. JACAL can manipulate and simplify equations, scalars, vectors, and matrices of single and multiple valued algebraic expressions containing numbers, variables, radicals, and algebraic differential, and holonomic functions. #%define __os_install_post /usr/lib/rpm/brp-compress %prep %setup -n jacal -c -T cd .. unzip ${RPM_SOURCE_DIR}/jacal-%{version}.zip %build gzip -f jacal.info %install mkdir -p ${RPM_BUILD_ROOT}%{_infodir}/ cp jacal.info.gz ${RPM_BUILD_ROOT}%{_infodir}/ make prefix=${RPM_BUILD_ROOT}%{prefix}/ \ mandir=${RPM_BUILD_ROOT}%{_mandir}/ \ infodir=${RPM_BUILD_ROOT}%{_infodir}/ \ pinstall echo "(use-modules (ice-9 slib))">${RPM_BUILD_ROOT}%{prefix}/lib/jacal/guile.scm echo "(slib:load \"%{prefix}/lib/jacal/math\")">>${RPM_BUILD_ROOT}%{prefix}/lib/jacal/guile.scm echo "(math)" >>${RPM_BUILD_ROOT}%{prefix}/lib/jacal/guile.scm echo "(slib:load \"%{prefix}/lib/jacal/math\")" >${RPM_BUILD_ROOT}%{prefix}/lib/jacal/go.scm echo "(math)" >>${RPM_BUILD_ROOT}%{prefix}/lib/jacal/go.scm mkdir -p ${RPM_BUILD_ROOT}%{prefix}/bin echo '#! /bin/sh' > ${RPM_BUILD_ROOT}%{prefix}/bin/jacal echo JACALDIR=%{prefix}/lib/jacal/>> ${RPM_BUILD_ROOT}%{prefix}/bin/jacal echo VERSION=%{version} >> ${RPM_BUILD_ROOT}%{prefix}/bin/jacal cat jacal.sh >> ${RPM_BUILD_ROOT}%{prefix}/bin/jacal chmod +x ${RPM_BUILD_ROOT}%{prefix}/bin/jacal %clean rm -rf $RPM_BUILD_ROOT %post /sbin/install-info %{_infodir}/jacal.info.* %{_infodir}/dir %files %defattr(-, root, root) %{prefix}/bin/jacal %dir %{prefix}/lib/jacal %{prefix}/lib/jacal/*.scm %{prefix}/lib/jacal/jacalcat %{prefix}/lib/jacal/COPYING %{prefix}/lib/jacal/HELP %{prefix}/lib/jacal/Makefile %{prefix}/man/man1/jacal.1.* %{_infodir}/jacal.info.* %doc ANNOUNCE ChangeLog README COPYING demo test.math rw.math DOC/algdenom DOC/grammar DOC/history DOC/lambda DOC/ratint.pdf %changelog * Thu Aug 30 2001 Bo Forslund - Make more use of macros. - Install COPYING and HELP file. jacal-1b9/unparse.scm0000644001705200017500000003461010667300650012507 0ustar tbtb;; JACAL: Symbolic Mathematics System. -*-scheme-*- ;; Copyright 1992, 1993 Aubrey Jaffer. ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or (at ;; your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; a LINE is a list of column positions and strings or characters ;;; which appear there on one horizontal line. ;;; a BOX is a list of pairs of line-numbers and LINEs. ;;; a PBOX consists of a BP (binding power) and a list of boxes. ;;; a TEMPLATE is an HBOX. An HBOX is a list of strings, symbols and ;;; VBOXes. A VBOX is a list of pairs of a row position and an HBOX ;;; or a list of a character. ;;; A number of the form #dNBBB in a template is replaced with the BOX ;;; for argument N. If the #dNBBB appears in a HBOX then it is glued ;;; horizontally to the other elements in the HBOX. If the #dNBBB ;;; appears in a VBOX then it is glued vertically to the other ;;; elements in the VBOX. BBB denotes the maximum binding power of ;;; the argument. If the binding power of the argument is less than ;;; BBB, parenthesis will be added according to TEMPLATE:PARENTHESIS. ;;; Characters in HBOXes are expanded horizontally to fill any empty ;;; space in their line. A list of a character VBOX is expanded ;;; vertically to fill any empty space in its containing HBOX. ;;; The symbol 'break will break the line if there is not enough ;;; horizontal room remaining. ;(require 'rev3-procedures) (require 'common-list-functions) ;;; TEXT-WIDTH (define text-width string-length) ;;; return the position of symbol #dNBBB (define (arg-pos num) (quotient num 1000)) (define (arg-bp num) (modulo num 1000)) (define make-template cons) (define template-bp car) (define template-hbox cdr) ;;; Utility routines for dealing with BOX ;;; BOX is a list of (line-number-referred-to-center . LINE) ;;; LINE is a list of POSITIONs and STRINGs. ;(require 'record) ;(define pbox-type (make-record-type "box" '(bp lines))) ;(define make-pbox (record-constructor pbox-type)) ;(define pbox-bp (record-accessor pbox-type 'bp)) ;(define pbox-lines (record-accessor pbox-type 'lines)) (define make-pbox cons) (define pbox-bp car) (define pbox-lines cdr) (define top-edge caar) (define left-edge cadar) (define (bottom-edge box) (caar (last-pair box))) (define (right-edge box) (define redge 0) (for-each (lambda (line) ;;; (define re 0) ;;; (for-each (lambda (x) ;;; (cond ((number? x) (set! re x)) ;;; ((string? x) ;;; (set! re (+ (text-width x) re))))) ;;; (cdr line)) ;;; (set! redge (max re redge)) (if (not (null? (cdr line))) (let ((end (last line 2))) (set! redge (max redge (+ (car end) (if (string? (cadr end)) (text-width (cadr end)) 0))))))) box) redge) (define (shift-numbers! lst inc) (cond ((null? lst)) (else (set-car! lst (+ inc (car lst))) (shift-numbers! (cddr lst) inc)))) ;;; routines for actually writing the 2d formated output to a port. ;;; These can be replaced with code which does cursor positioning. (define (flush-blanks box) (cond ((null? box) box) ((> (top-edge box) (+ 1 lte)) (newline) (set! lte (+ -1 (top-edge box))) (flush-blanks box)) ((null? (cdar box)) (newline) (set! lte (top-edge box)) (flush-blanks (cdr box))) (else box))) (define (chunk-height box) (let ((base lte)) (do ((b box (cdr b)) (lte base (top-edge b))) ((or (null? b) (null? (cdar b)) (not (= (+ 1 lte) (top-edge b)))) (if (zero? (- lte base)) 1 (- lte base))) (set! lte (top-edge b))))) (define (display-box box) (define h (get-page-height)) (set! box (flush-blanks box)) (set! lte (+ -1 (top-edge box))) (let loop ((box box)) (cond ((null? box) box) ((begin (set! box (flush-blanks box)) (< (+ linum (chunk-height box)) h)) (loop (display-chunk box))) ((or (zero? h) (zero? linum)) (loop (display-chunk box))) ((do-more) (set! linum 0) (loop (display-chunk box))) (else #f)))) (define (display-chunk box) (do ((b box (cdr b))) ((or (null? b) (not (= (+ 1 lte) (top-edge b))) (null? (cdar b))) ;;; (print (+ 1 lte) (and (not (null? b)) (top-edge b)) linum) b) (display-line 0 #\space (cdar b)) (if (not (null? (cdr b))) (newline) (force-output)) (set! lte (top-edge b)) (set! linum (+ 1 linum)) (and (null? (cdar b)) (not (zero? (get-page-height))) (not (do-more)) (set! b '(()))))) (define (display-line hpos fillchr line) (cond ((null? line) hpos) ((string? (cadr line)) (display (make-string (- (car line) hpos) fillchr)) (display (cadr line)) (display-line (+ (car line) (text-width (cadr line))) fillchr (cddr line))) ((char? (cadr line)) (display (make-string (- (car line) hpos) fillchr)) (display-line (car line) (cadr line) (cddr line))) (else (slib:error 'display-line line)))) ;;; Glue 2 boxes together horizontally, with the RIGHTBOX moved ;;; POSINC to the right (define (hglue-lines! leftbox posinc rightbox) (cond ((null? rightbox) leftbox) ((null? leftbox) '()) ((char? (car rightbox)) (cons (nconc (car leftbox) (list posinc (string (car rightbox)))) (hglue-lines! (cdr leftbox) posinc rightbox))) ((< (top-edge leftbox) (top-edge rightbox)) (cons (car leftbox) (hglue-lines! (cdr leftbox) posinc rightbox))) (else ;line up (if (not (zero? posinc)) (shift-numbers! (cdar rightbox) posinc)) (cons (nconc (car leftbox) (cdar rightbox)) (hglue-lines! (cdr leftbox) posinc (cdr rightbox)))))) (define (hglue boxes hroom) (let ((arights (list (cond ((null? boxes) 0) ((null? (car boxes)) 0) ((char? (car (car boxes))) 1) (else (right-edge (car boxes)))))) (right -1) (top 0) (bottom 0)) (do ((boxes boxes (cdr boxes)) (rights arights (begin (set-cdr! rights (if (null? (cdr boxes)) '() (list (cond ((null? (cadr boxes)) 0) ((char? (caadr boxes)) 1) (else (right-edge (cadr boxes))))))) (cdr rights))) (redge 0 (+ redge (car rights)))) ((or (null? boxes) (and (positive? right) (> redge hroom))) (if (<= redge hroom) (set! right -2))) (cond ((equal? (car boxes) '((0 0 break))) (set! right redge)) ((char? (caar boxes))) (else (set! bottom (max bottom (bottom-edge (car boxes)))) (set! top (min top (top-edge (car boxes))))))) (do ((boxes boxes (cdr boxes)) (rights arights (cdr rights)) (redge 0 (+ redge (car rights))) (leftbox (do ((i (+ -1 bottom) (+ -1 i)) (ans (list (list bottom)) (cons (list i) ans))) ((< i top) ans)) (cond ((equal? (car boxes) '((0 0 break))) (cond ((= (+ redge (car rights)) right) (set! arights #f) (vformat! '((0 #d0000) (2 #d1000)) (list (make-pbox 200 (list leftbox)) (make-pbox 200 (cdr boxes))) #f hroom)) (else leftbox))) (else (hglue-lines! leftbox redge (car boxes)))))) ((or (not arights) (null? boxes)) leftbox)))) ;;; Routines to format BOX from TEMPLATEs. ;;; HFORMAT returns a list of boxes which need to be HGLUEd together ;;; into a single box. (define (hformat hbox args tps hroom) (if (null? hbox) '() (let ((item (car hbox)) (hr (- hroom (quotient hroom 20)))) (cond ((number? item) (let ((argnum (arg-pos item))) (if (> (length args) argnum) (let ((arg (list-ref args argnum))) (if (<= (arg-bp item) (pbox-bp arg)) (nconc (pbox-lines arg) (hformat (cdr hbox) args tps hroom)) (nconc (hformat (template-hbox (cdr (assq 'template:parenthesis tps))) (list '() arg) tps hroom) (hformat (cdr hbox) args tps hroom)))) (hformat (cdr hbox) args tps hroom)))) ((pair? item) (cons (vformat! item args tps hr) (hformat (cdr hbox) args tps hroom))) ((vector? item) (let ((vt (vector-ref item 0)) (vl (cdr (vector->list item)))) (cond ((<= (length args) (arg-pos (find-if number? vl))) (hformat (cdr hbox) args tps hroom)) ((eq? 'rest vt) (nconc (hformat vl args tps hroom) (hformat hbox (cdr args) tps (- hroom hr)))) ((eq? 'optional vt) (nconc (hformat vl args tps hroom) (hformat (cdr hbox) args tps hroom))) (else (math:error 'hformat 'unknown-format item))))) (else (cons (list (list 0 0 item)) (hformat (cdr hbox) args tps hroom))))))) (define (vformat! vbox args tps hroom) (if (char? (car vbox)) vbox (let* ((boxes (map (lambda (hbox) (hglue (hformat (cdr hbox) args tps hroom) hroom)) vbox)) (rights (map right-edge boxes)) (mostright (apply max rights))) (for-each (lambda (box right) (for-each (lambda (line) (cond ((null? (cdr line))) ((and (char? (caddr line)) (null? (cdddr line))) ;;terminate rubber line. (nconc line (list mostright #\space))) (else ;center justify line. (let ((lst (cdr line)) (inc (quotient (- mostright right) 2))) (set-car! lst (+ inc (car lst))) (shift-numbers! (cddr lst) inc))))) box)) boxes rights) (vrenumber! vbox boxes) (apply nconc boxes)))) ;;; the trick here is to make line 0 of hbox 0 still be line 0. Push ;;; everything else up or down to make that happen. ;;; Here, vbox is used only for its hbox numbers. (define (vrenumber! vbox boxes) (cond ((null? vbox) 0) ((negative? (caar vbox)) (let ((topinc (+ (- (caar vbox) (if (null? (cdr vbox)) 0 (caadr vbox))) (- (vrenumber! (cdr vbox) (cdr boxes)) (bottom-edge (car boxes)))))) (or (zero? topinc) (for-each (lambda (line) (set-car! line (+ (car line) topinc))) (car boxes)))) (top-edge (car boxes))) (else (or (zero? (caar vbox)) (for-each ;space down if no hbox 0 (lambda (line) (set-car! line (+ (car line) (caar vbox)))) (car boxes))) (let ((topinc (bottom-edge (car boxes))) (lastnum (caar vbox))) (for-each (lambda (hbox box) (set! topinc (+ (- (car hbox) lastnum) (- topinc (top-edge box)))) (set! lastnum (car hbox)) (for-each (lambda (line) (set-car! line (+ (car line) topinc))) box) (set! topinc (bottom-edge box))) (cdr vbox) (cdr boxes))) (top-edge (car boxes))))) ;;; Driver for 2d output (define (print-using-grammar exp grm) (template-print exp (grammar-write-tab grm))) (define linum 0) (define lte 0) (define (template-print exp tps) (define owidth (get-page-width)) (if (zero? owidth) (set! owidth 99999)) ;essentially infinite (display-box (hglue (pbox-lines (unparse exp tps owidth)) owidth))) (define (unparse exp tps hroom) (cond ((symbol? exp) (make-pbox 200 (list (list (list 0 0 (symbol->string exp)))))) ((number? exp) (make-pbox 200 (list (list (list 0 0 (number->string exp)))))) ((list? exp) (let* ((p (assq (car exp) tps))) (unparse1 (if p (cdr p) (cdr (assq 'template:default tps))) exp tps hroom))) ((not (vector? exp)) (slib:error 'unparse 'not-s-expression exp)) ((zero? (vector-length exp)) ;this special case should be eliminated (make-pbox 200 (list (list (list 0 0 "[]"))))) ((and (vector? (vector-ref exp 0)) (assq 'template:matrix tps) (let ((len (vector-length (vector-ref exp 0)))) (every (lambda (r) (and (vector? r) (= (vector-length r) len))) (cdr (vector->list exp))))) (let ((hr (quotient hroom (vector-length exp))) (template (cdr (assq 'template:matrix tps)))) (make-pbox (template-bp template) (hformat (template-hbox template) (map (lambda (obj) (unparse1 (rubber-vbox (length obj)) obj tps hr)) ;transpose of exp (apply map list (map vector->list (vector->list exp)))) tps hroom)))) (else (unparse1 (cdr (assq 'template:bunch tps)) (vector->list exp) tps hroom)))) (define (unparse1 template exp tps hroom) (define hr (- hroom (quotient hroom 20))) (make-pbox (template-bp template) (hformat (template-hbox template) (map (lambda (exp) (unparse exp tps hr)) exp) tps hroom))) (define (rubber-vbox len) (make-template 200 (list (rubvbox (- 1 len) len)))) (define (rubvbox i len) (if (>= i len) '() (cons (list i (+ (* 1000 (quotient (+ i len) 2)) 10)) (rubvbox (+ 2 i) len)))) ;;;; Test code ;;; To test, load this and English.scm. Do (test2d tps:2d). (define (test2d tps) (for-each (lambda (b) (template-print b tps) (newline)) '( (+ (* 3 a b) (* 2 (^ a 2) b) c (* d e)) (sum (* (rapply a i) (^ x (+ -2 i))) i 0 inf) (= %gamma (limit (sum (- (over 1 n) (log m)) n 1 m) m inf)) (^ (- (over 1 (^ (+ y x) 4)) (over 3 (^ (+ y x) 3))) 2) (^ x (over (+ (^ a 2) 1) a)) (+ (- (over 2 (+ 2 x)) (over 2 (+ 1 x))) (over 1 (^ (+ 1 x) 2))) (over (* (+ (^ x 2) (* 2 x) 1) (+ -1 y)) (* 36 (+ 1 y))) (+ (* (^ %e (f x)) ((over (^ d 2) (^ dx 2)) (f x))) (* (^ %e (f x)) (^ ((over d dx) (f x)) 2))) (+ (integrate (f x) x a b) x) (integrate (^ e (^ x 2)) x) (limit (^ (f x) (g (+ 1 x))) x 0 minus) (+ (over y (^ (box x) 2)) x) (over (prod (^ (+ (^ x i) 1) (/ 5 2)) i 1 inf) (+ (^ x 2) 1)) (over 1 (+ 4 (over 1 (+ 3 (over 1 42))))) (over (* (factorial m) n (factorial (+ -1 n))) m) (- (* 16 (^ a 2)) (* 2 (u 0 1) (at ((over d dx) (u x y)) (= x 0) (= y 1)))) (+ (^ a (^ b c)) (^ (^ a b) c)) ))) (define (textest) (for-each (lambda (b) (template-print b tps:2d) (newline) (template-print b tps:tex) (newline)) '( (over (+ (^ a 2) c (* b x)) (+ 2 z)) (+ (^ (+ a b) (/ 1 2)) (^ e (/ 1 2))) (arctan (arctan a)) (over (arctan (over (- (/ (* 2 (^ b (/ 1 4)) x) (^ a (/ 1 4))) (sqrt 2)) (sqrt 2))) (* (^ 2 (/ 3 2)) (^ a (/ 3 4)) (^ b (/ 1 4)))) (over a (+ b c))))) (define (mtest tps) (for-each (lambda (b) (template-print b tps) (newline)) '( #((= x1 (negate (over 1 (sqrt 5)))) (= x2 (negate (over 2 (sqrt 5))))) #(#((over 1 a) 0) #((negate (over b a)) 1)) #(#((^ a 2) 0) #((+ (* a b) b) 1))))) jacal-1b9/jacal.texi0000644001705200017500000020121710750774423012300 0ustar tbtb\input texinfo @c -*-texinfo-*- @c %**start of header @setfilename jacal.info @settitle jacal @include version.txi @setchapternewpage on @c Choices for setchapternewpage are {on,off,odd}. @paragraphindent 2 @syncodeindex tp fn @syncodeindex cp fn @syncodeindex vr fn @c %**end of header @copying @noindent This manual is for JACAL (version @value{JACALVERSION}, @value{JACALDATE}), an interactive symbolic mathematics system. Copyright @copyright{} 1993-1999, 2002, 2006, 2007 Free Software Foundation, Inc. @quotation Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled ``GNU Free Documentation License.'' @end quotation @end copying @dircategory Mathematics @direntry * Jacal: (jacal). Interactive Symbolic Mathematics. @end direntry @iftex @finalout @c DL: lose the egregious vertical whitespace, esp. around examples @c but paras in @defun-like things don't have parindent @parskip 4pt plus 1pt @end iftex @titlepage @title JACAL @subtitle Symbolic Mathematics System @subtitle Version @value{JACALVERSION}, @value{JACALDATE} @author Aubrey Jaffer @page @vskip 0pt plus 1filll @insertcopying @end titlepage @contents @ifnottex @node Top, Overview, (dir), (dir) @top JACAL @c @noindent @c This manual documents the JACAL symbolic mathematics system. JACAL @c @value{JACALVERSION} was released @value{JACALDATE}. Current @c information about JACAL can be found on JACAL's @dfn{WWW} home page: @c @center @url{http://swiss.csail.mit.edu/~jaffer/JACAL} @insertcopying @menu * Overview:: Installing and Starting JACAL * Algebra:: Operators and Commands * Calculus:: Operators and Commands * Matrices and Tensors:: * Lambda Calculus:: Functions * Miscellaneous:: * Flags:: * Index:: @end menu @end ifnottex @node Overview, Algebra, Top, Top @chapter Overview @cindex Overview JACAL is a symbolic mathematics system for the simplification and manipulation of equations and single and multiple valued algebraic expressions constructed of numbers, variables, radicals, and algebraic functions, differential, and holonomic functions. In addition, vectors and matrices of the above objects are included. JACAL @value{JACALVERSION} was released @value{JACALDATE}. Current information about JACAL can be found on JACAL's @dfn{WWW} home page: @center @url{http://swiss.csail.mit.edu/~jaffer/JACAL} JACAL, part of the GNU project, is free software, and you are welcome to redistribute it under certain conditions; See the file COPYING with this program or type @code{(terms)();} to JACAL for details. For a list of the features that have changed since the last JACAL release, see the file @file{ANNOUNCE}. For a list of the features that have changed over time, see the file @file{ChangeLog}. @menu * Authors and Bibliography:: * Installation:: How to install JACAL on your system. * Running Jacal:: * Release Notes:: Useful information. * GNU Free Documentation License:: @end menu @node Authors and Bibliography, Installation, Overview, Overview @section Authors and Bibliography @cindex Authors @cindex Bibliography @table @b @item Aubrey Jaffer Most of JACAL @item Michael Thomas Polynomial Factoring. @item Jerry D. Hedden Tensors. @end table The maintainer can be reached as @samp{agj @@ alum.mit.edu}. @subheading Bibliography @cindex Bibliography @table @asis @item [ACP] @pindex ACP Donald Ervin Knuth.@* @cite{The Art of Computer Programming : Seminumerical Algorithms (Vol 2).}@* 2nd Ed (1981) Addison-Wesley Pub Co; ISBN: 0-201-03822-6 @item [GCL] @pindex GCL Keith O. Geddes, Stephen R. Czapor, George Labahn.@* @cite{Algorithms for Computer Algebra.}@* (October 1992) Kluwer Academic Pub; ISBN: 0-7923-9259-0 @item [Siret] @pindex Siret Y. Siret (Editor), E. Tournier, J. H. Davenport, F. Tournier.@* @cite{Computer Algebra: Systems and Algorithms for Algebraic Computation}@* 2nd edition (June 1993) Academic Press; ISBN: 0-122-04232-8 @item [R5RS] @pindex R5RS Richard Kelsey and William Clinger and Jonathan (Rees, editors)@* @uref{r5rs_toc, Revised(5) Report on the Algorithmic Language Scheme},@* @cite{Higher-Order and Symbolic Computation} Volume 11, Number 1 (1998), @w{pp.@: 7-105}, or@* @cite{ACM SIGPLAN Notices} 33(9), September 1998.@* @ifinfo @ref{Top, , Revised(5) Report on the Algorithmic Language Scheme, r5rs, Revised(5) Report on the Algorithmic Language Scheme}.@* @end ifinfo @item [SLIB] @pindex SLIB Todd R. Eigenschink and Aubrey Jaffer.@* @uref{slib_toc, SLIB; The Portable Scheme Library}@* @ifinfo @ref{Top, , SLIB; The Portable Scheme Library, slib, SLIB; The Portable Scheme Library}. @end ifinfo @end table @node Installation, Running Jacal, Authors and Bibliography, Overview @section Installation @ifset html @end ifset @cindex Scheme The JACAL program is written in the Algorithmic Language @dfn{Scheme}. So you must obtain and install a Scheme implementation in order to run it. The installation procedures given here use the SCM Scheme implementation. If your system has a Scheme (or Guile) implementation installed, then the @samp{scm} steps are unnecessary. JACAL also requires the SLIB Portable Scheme library which is available from @uref{http://swiss.csail.mit.edu/~jaffer/SLIB}. @deftp System i386 GNU/Linux with Redhat Package Manager (rpm) @example wget http://swiss.csail.mit.edu/ftpdir/scm/scm-5e5-1.i386.rpm wget http://swiss.csail.mit.edu/ftpdir/scm/slib-3b1-1.noarch.rpm wget http://swiss.csail.mit.edu/ftpdir/scm/jacal-1b9-1.noarch.rpm rpm -U scm-5e5-1.i386.rpm slib-3b1-1.noarch.rpm jacal-1b9-1.noarch.rpm rm scm-5e5-1.i386.rpm slib-3b1-1.noarch.rpm jacal-1b9-1.noarch.rpm @end example The command @samp{jacal} will start an interactive session. @end deftp @deftp System Unix @deftpx System GNU/Linux @example wget http://swiss.csail.mit.edu/ftpdir/scm/scm-5e5.zip wget http://swiss.csail.mit.edu/ftpdir/scm/slib-3b1.zip wget http://swiss.csail.mit.edu/ftpdir/scm/jacal-1b9.zip unzip -ao scm-5e5.zip unzip -ao slib-3b1.zip unzip -ao jacal-1b9.zip (cd slib; make install) (cd scm; make scm; make install) (cd jacal; make install) rm scm-5e5.zip slib-3b1.zip jacal-1b9.zip @end example The command @samp{jacal} will start an interactive session using ELK, Gambit, Guile, Larceny, MIT-Scheme, MzScheme, Scheme48, SCM, or SISC. Type @samp{jacal --help} for instructions. @end deftp @deftp System Apple @uref{http://www.io.com/~cobblers/scm/} has downloads and utilities for installing SCM and SLIB on Macintosh computers. @end deftp @deftp System x86 Microsoft Download and run @uref{http://swiss.csail.mit.edu/ftpdir/scm/SLIB-3b1-1.exe},@* @uref{http://swiss.csail.mit.edu/ftpdir/scm/SCM-5e5-1.exe}, and@* @uref{http://swiss.csail.mit.edu/ftpdir/scm/JACAL-1b9-1.exe}. @end deftp @subheading Compiling Jacal @cindex Compiling Jacal For Scheme implementations with compilers, it is worthwhile to compile SLIB files, and the JACAL files @file{types.scm} and @file{poly.scm}. @c SLIB has initialization files for most Scheme implementations. It @c is available from the same locations and vendors as JACAL. @c @xref{Installation, , Installation, slib, SLIB}. @c @ifinfo @c @xref{Installation, , , slib, SLIB}. @c @end ifinfo @c @iftex @c See @file{README} in SLIB for how to install SLIB. @c @end iftex @node Running Jacal, Release Notes, Installation, Overview @section Running Jacal @cindex Running Jacal If you successfully executed one of the installations of the previous section, then typing @samp{jacal} or clicking an icon will begin an interactive session. To manually start jacal, start your Scheme implementation with SLIB. This may involve setting up that implementation's initialization file or LOADing a @samp{.init} file from the @file{slib} directory. Then type: @example (slib:load "/usr/local/lib/jacal/math") @end example @noindent where @file{/usr/local/lib/jacal/} is a path to the JACAL directory. JACAL should then print: @example JACAL version @value{JACALVERSION}, Copyright 1989-1999, 2002 Aubrey Jaffer JACAL comes with ABSOLUTELY NO WARRANTY; for details type `(terms)'. This is free software, and you are welcome to redistribute it under certain conditions; type `(terms)' for details. ;;; Type (math) to begin. @end example @noindent Do as it says: @example (math) @result{} type qed; to return to scheme, type help; for help. e0 : @end example @noindent And you are ready to try the commands described in the rest of the manual. @subheading Demonstrating Jacal @cindex Demonstrating Jacal There are several demonstration files in the @file{jacal} directory. To run, use the batch command @ref{Miscellaneous, batch}. @table @samp @item batch("demo"); Demonstrates a variety of JACAL features. @item batch("test.math"); Tests each operator. @item batch("rw.math"); Demonstrates tensors and The Robertson-Walker Cosmology Model. @end table @subheading Recovery from Errors @cindex Recovery from Errors As JACAL is a complicated program there are bugs which will occasionally cause the program to stop with some sort of error reported by the underlying Scheme system. In interactive implementations (such as SCM) you can usually continue your session by typing @code{(math)}. The expression which was input to JACAL just before the error will be lost but you should be able to otherwise continue with your session. @subheading Stopping Jacal @cindex Stopping Jacal The command @code{quit();} will end your JACAL session. With non-interactive Scheme implementations the JACAL command @code{qed();} or typing the end-of-file character (@key{C-z} on MS-DOS and VMS, @key{C-d} on others) will end your JACAL session. The command @code{qed();} will return to the interactive Scheme session. Typing @code{(math)} will return to the JACAL session. From the interactive Scheme session @code{(exit)} or possibly an end-of-file character will terminate the session. @node Release Notes, GNU Free Documentation License, Running Jacal, Overview @section Release Notes @cindex Release Notes With the standard input grammar, the precedence of @samp{-} as a prefix behaves strangely. @code{a^-b*c} becomes @code{a^(-b*c)} while @code{@result{a^b*c} (a^b)*c}. Using @code{divide} to divide a polynomial by an integer does not work. The command @code{example} executes the example it gives. This can lead to unpredictable results if the variables and constants in the example have already been given values by the user. The function @code{minor} should be modified to accept lists for @var{row} and @var{col}. Resultant might be modified to compute the resultant of a system of polynomials with respect to a list of variables. @subheading Conventions @cindex Conventions Things that are labeled as Operators can occur in expressions output by Jacal. Things that are labeled as Commands act upon their arguments and do not generally occur in expressions output by Jacal. Things that are labeled as flags are @code{set} to control aspects of the Jacal environment. The examples throughout this text were produced using @code{SCM}. Jacal has several grammers it understands. The @code{standard} grammar is used in this manual. It is like simple @code{TeX} grammar and algol family computer languages. Identifier names are case sensitive and can be any number of characters long. @subheading Manifest @cindex Manifest @table @asis @item COPYING details the LACK OF WARRANTY for Jacal and the conditions for distributing Jacal. @item HELP is online introduction to using Jacal. @item ChangeLog documents changes to Jacal. @item jacal is a unix (sh) script to start an interactive jacal session. @item demo demonstrates batch file use. "batch(demo);" to use in jacal. @item rw.math is a batch file of Robertson-Walker model of General Relativity. @item test.math is a batch file which tests Jacal. @item jacal.texi is documentation on how to use jacal in TeXinfo format. @item DOC has files telling about how jacal works. @table @asis @item algdenom gives an algorithm for clearing radicals and other algebraic field extensions from denominators. @item grammar explains how to create new grammars. @item history gives a little history of jacal. @item lambda explains mid-level data formats. From a Dr. Dobbs article. @item ratint.tex article explaining jacal's eventual integration algorithm. @end table @item math.scm is the file you load into scheme in order to run jacal. @item toploads.scm contains comments describing the rest of the files. @item modeinit.scm has initializations for modes in Jacal. @item view.scm is a program for viewing TeX expressions. @end table @node GNU Free Documentation License, , Release Notes, Overview @section GNU Free Documentation License @include fdl.texi @node Algebra, Calculus, Overview, Top @chapter Algebra @cindex Algebra @menu * Algebraic Operators:: * Algebraic Commands:: * Rational Expression:: * Polynomials:: * Factoring:: @end menu @node Algebraic Operators, Algebraic Commands, Algebra, Algebra @section Algebraic Operators @cindex Algebraic Operators @deffn Operator + augend addend Addition of scalar quantities or componentwise addition of bunches is accomplished by means of the infix operator @code{+}. For example, @example @group e2 : a:[[1, 3, 5], [2, 4, 7]]; [1 3 5] e2: [ ] [2 4 7] e3 : b:[2, 4]; e3: [2, 4] e4 : a + b; [3 5 7 ] e4: [ ] [6 8 11] e5 : 3 + 2; e5: 5 e6 : c + b; e6: [2 + c, 4 + c] e7 : e1 + e5; 2 2 e7: 5 + (8 a + 12 a ) b @end group @end example @end deffn @deffn Operator - minuend subtrahend @deffnx Operator - subtrahend The symbol @code{-} is used to denote either the binary infix operator subtraction or the unary minus. @example @group e1 : -[1,2,3]; e1: [-1, -2, -3] e2 : 3-7; e2: -4 @end group @end example @end deffn @deffn Operator +/- minuend subtrahend @deffnx Operator -/+ minuend subtrahend @deffnx Operator +/- augend @deffnx Operator -/+ augend Jacal allows the use of @code{+/-} and @code{-/+} as ambiguous signs (unary plus-or-minus, unary minus-or-plus) and as ambiguous infix operators (binary plus-or-minus, binary minus-or-plus). The value @code{+/-} is also represented by the constant @code{%sqrt1}, while @code{-/+} is represented by @code{-%sqrt1}. @example @group e7 : u:+/-3; e7: 3 %sqrt1 e8 : u^2; e8: 9 e9 : +/-(u); e9: 3 e10 : u-/+3; e10: b-/+(3 %sqrt1, 3) @end group @end example @end deffn @deffn Operator * multiplicand1 multiplicand2 Multiplication of scalar expressions such as numbers, polynomials, rational functions and algebraic functions is denoted by the infix operator @code{*}. For example, @example @group e1 : (2 + 3 * a) * 4 * a * b^2; 2 2 e1: (8 a + 12 a ) b @end group @end example One can also use @code{*} as an infix operator on bunches. In that case, it operates componentwise, in an appropriate sense. If the bunches are square matrices, the operator @code{*} multiplies corresponding entries of the two factors. It does not perform matrix multiplication. To multiply matrices one instead uses the operator @code{.} (i.e., a period). More generally, any binary scalar operator other than @code{^} can be used on bunches and acts componentwise. @end deffn @deffn Operator / dividend divisor The symbol for division in Jacal is @code{/}. For example, the value returned by @code{6 / 2} is @code{3}. @example @group e3 : (x^2 - y^2) / (x - y); e3: x + y @end group @end example @end deffn @deffn Operator ^ expression exponent The infix operator @code{^} is used for exponentiation of scalar quantitites or for componentwise exponentiation of bunches. For example, @code{2^5} returns 32. Unlike the other scalar infix operators, one cannot use @code{^} for component-wise operations on bunches. Furthermore, one should not try to use @code{^} to raise a square matrix to a power. Instead, one should use @code{^^}. @example @group e7 : (1+x)^4; 2 3 4 e7: 1 + 4 x + 6 x + 4 x + x @end group @end example @end deffn @deffn Operator = expression1 expression2 In Jacal, the equals sign @code{=} is @emph{not} used for conditionals and it is @emph{not} used for assignments. To assign one value to another, use either @code{:} or @code{:=}. The operator @code{=} merely returns a value of the form @code{0 = @var{expression}}. The value returned by @code{a = b}, for example is @code{0 = a - b}. @example @group e6 : 1=2; e6: 0 = -1 @end group @end example @end deffn @deffn Operator || Z1 Z2 The infix operator @code{||} is from electrical engineering and represents the effective impedance of the parallel connection of components of impedances @var{Z1} and @var{Z2}: @example @group e1 : Z1 || Z2; Z1 Z2 e1: ------- Z1 + Z2 @end group @end example @end deffn @node Algebraic Commands, Rational Expression, Algebraic Operators, Algebra @section Algebraic Commands @cindex Algebraic Commands @deffn Command eliminate [eqn_1 eqn_2 @dots{}] [var_1 var_2 @dots{}] Here @var{eqn_i} is an equation for @var{i} = 1 @dots{} @var{n} and where @var{var_j} is a variable for @var{j} = 1 @dots{} @var{m}. @code{eliminate} returns a list of equations obtained by eliminating the variables @var{var_1}, @dots{}, @var{var_m} from the equations @var{eqn_1}, @dots{}, @var{eqn_n}. @example @group e39 : eliminate([x^2+y=0,x^3+y=0],[x]); 2 e39: 0 = - y - y e40 : eliminate([x+y+z=3,x^2+y^2+z^2=3,x^3+y^3+z^3=3],[x,y]); e40: 0 = 1 - z @end group @end example @end deffn @deffn Command suchthat var eqn The equation @var{eqn} must contain an occurence of variable @var{var}. @code{suchthat} returns an expression for all complex values of @var{var} satisfying @var{eqn}. @code{suchthat} is useful for extracting an expression from an equation. @example e0 : a*x+b*y+c = 0; e0: 0 = c + a x + b y e1 : suchthat(x, e0); - c - b y e1: --------- a @end example @deffnx Command suchthat var exp If an expression rather than an equation is given to @code{suchthat}, it is as though the equation @code{@var{exp}=0} was given. @example e2 : suchthat(x, e0); - c - b y e2: --------- a @end example @deffnx Operator | var exp_or_eqn An alternative infix notation is also available for @code{suchthat}. When used in combination with the @samp{@{ @}} notation for @code{or}, the set notation used by some textbooks results. If @var{var} in @var{eqn} has multiple roots, a named @dfn{field extension} will be introduced to represent any one of those roots. When multiple values are returned, the result (in @code{disp2d} and @code{standard} grammars) is wrapped with @samp{@{ @}}. @example e3 : x | a*x^2 + b*x + c; 2 ext3: @{:@@ | 0 = c + b :@@ + a :@@ @} e3: ext3 e4 : e3 ^ 2; - c - b ext3 e4: ------------ a @end example @end deffn @deffn Command extrule extsym Returns the rule defining named field extension @var{extsym}. @example e5 : extrule(ext3); 2 e5: 0 = c + b ext3 + a ext3 @end example @end deffn @deffn Command or expr_1 @dots{} @deffnx Command or eqn_1 @dots{} The function @code{or} takes as inputs one or more equations or values. If the inputs are equations, then @code{or} returns an equation which is equivalent to the assertion that at least one of the input equations holds. If the inputs to @code{or} are values instead of two equations, then the function @code{or} returns a multiple value. If the inputs to @code{or} consist of both equations and values, then @code{or} will return the multiple values. @example @group e1 : or(x=2,y=3); e1: 0 = -6 + 3 x + (2 - x) y e2 : or(2,3); 2 e2: @{:@@ | 0 = -6 + 5 :@@ - :@@ @} e3 : e2^2; 2 e3: @{:@@ | 0 = -36 + 13 :@@ - :@@ @} e4 : or(x=2,17); e4: 17 @end group @end example @samp{@{@var{eqn}, @dots{} @}} can be used as an alternate syntax for @code{or}: @example e5 : @{+1, -1@}; 2 e5: @{:@@ | 0 = -1 + :@@ @} @end example @end deffn @node Rational Expression, Polynomials, Algebraic Commands, Algebra @section Rational Expression @cindex Rational Expression @deffn Command num expr The function @code{num} takes a rational expression as input and returns a numerator of the expression. @example @group e25 : num((x^2+y^2)/(x^2-y^2)); 2 2 e25: - x - y e26 : num(7/4); e26: 7 e27 : num(7/(4/3)); e27: 21 @end group @end example @end deffn @deffn Operator denom rational-expression The Jacal command @code{denom} is used to obtain the denominator of a rational expression. @example @group e26 : denom(4/5); e26: 5 @end group @end example @end deffn @deffn Command listofvars expr The command @code{listofvars} takes as input a rational expression and returns a list of the variables that occur in that expression. @example @group e7 : listofvars(x^2+y^3); e7: [x, y] e8 : listofvars((x^2+y^3)/(2*x^7+y*x+z)); e8: [z, x, y] @end group @end example @end deffn @deffn Command imagpart z Returns the coefficient of @code{%i} in expression @var{z}; @end deffn @deffn Command realpart z Returns all but the coefficient of @code{%i} in expression @var{z}; @end deffn @deffn Command abs z @deffnx Command cabs z @code{| @var{z} |} Returns the square root of the sum of the squares of the @code{realpart} and the @code{imagpart} of @var{z}. @end deffn @node Polynomials, Factoring, Rational Expression, Algebra @section Polynomials @cindex Polynomials @deffn Operator degree poly var Returns the degree of polynomial or equation @var{poly} in variable @var{var}. @deffnx Operator degree poly Returns the total-degree, the degree of its highest degree monomial, of polynomial or equation @var{poly}. @example @group e26 : degree(a*x*x + b*y*x + c*y*y + d*x + e*y + f, y); e26: 2 e27 : degree(a*x*x + b*y*x + c*y*y + d*x + e*y + f); e27: 3 @end group @end example @end deffn @deffn Operator coeff poly var @deffnx Operator coeff poly var deg @deffnx Operator coeffs poly var The command @code{coeff} is used to determine the coefficient of a certain power of a variable in a given polynomial. Here @var{poly} is a polynomial and @var{var} is a variable. If the optional third argument is omitted, then Jacal returns the coefficient of the variable @var{var} in @var{poly}. Otherwise it returns the coefficient of @var{var^deg} in @var{poly}. The function @code{coeffs} returns a list of all of the coefficients. For example, @example @group e14 : coeff((x + 2)^4, x, 3); e14: 8 e15 : (x + 2)^4; 2 3 4 e15: 16 + 32 x + 24 x + 8 x + x e16 : coeff((x + 2)^4, x); e16: 32 e18 : coeffs((x + 2)^4, x); e18: [16, 32, 24, 8, 1] @end group @end example @end deffn @deffn Operator poly var vect @deffnx Operator poly var coeff1 @dots{} The function @code{poly} provides an inverse to the function @code{coeffs}, allowing one to recover a polynomial from its vector or list of coefficients. @example @group e15 : poly(y, [16, 32, 24, 8, 1]); 2 3 4 e15: 16 + 32 y + 24 y + 8 y + y e16 : poly(y, 16, 32, 24, 8, 1); 2 3 4 e16: 16 + 32 y + 24 y + 8 y + y @end group @end example @end deffn @deffn Operator poly eqn The function @code{poly} returns the expression equal to 0 in equation @var{eqn}. Be aware that the sign and scaling of the returned polynomial will not necessarily match those in the equation creating @var{eqn}. @example @group e17 : 2*a = 4*c; e17: 0 = - a + 2 c e18 : poly(e17); e18: - a + 2 c @end group @end example @end deffn @deffn Operator content poly var Returns a list of content and primitive part of a polynomial with respect to the variable. The content is the GCD of the coefficients of the polynomial in the variable. The primitive part is @var{poly} divided by the content. @example @group e24 : content(2*x*y+4*x^2*y^2,y); 2 e24: [2 x, y + 2 x y ] @end group @end example @end deffn @deffn Operator divide dividend divisor var @deffnx Operator divide dividend divisor The command @code{divide} treats @var{divident} and @var{divisor} as polynomials in the variable @var{var} and returns a pair @samp{[@var{quotient}, @var{remainder}]} such that @code{@var{dividend} = @var{divisor} * @var{quotient} + @var{remainder}}. If the third argument @var{var} is omitted Jacal will choose a variable on its own with respect to which it will do the division. In particular, of @var{dividend} and @var{divisor} are both numerical, one can safely omit the third argument. @example @group e5 : divide(x^2+y^2,x-7*y^2,x); 2 2 4 e5: [x + 7 y , y + 49 y ] e6 : divide(-7,3); e6: [-2, -1] e11 : divide(x^2+y^2+z^2,x+y+z); 2 2 e11: [- x - y + z, 2 x + 2 x y + 2 y ] e14 : divide(x^2+y^2+z^2,x+y+z,y); 2 2 e14: [- x + y - z, 2 x + 2 x z + 2 z ] e15 : divide(x^2+y^2+z^2,x+y+z,z); 2 2 e15: [- x - y + z, 2 x + 2 x y + 2 y ] @end group @end example @end deffn @deffn Command mod poly1 eqn var @deffnx Command mod poly1 poly2 var @deffnx Command mod poly1 poly2 Returns @var{poly1} reduced with respect to @var{poly2} (or @var{eqn}) and @var{var}. If @var{poly2} is univariate, the third argument is not needed. @deffnx Command mod poly1 n Returns @var{poly1} with all the coefficients taken modulo @var{n}. @deffnx Command mod poly1 Returns @var{poly1} with all the coefficients taken modulo the current modulus. If the modulus (@var{n} or the current modulus) is negative, then the results use symmetric representation. @example @group e19 : x^4+4 mod 3; 4 e19: 1 + x e20 : x^4+4 mod x^2=2; e20: 8 e22 : mod(x^3*a*7+x*8+34, -3); 3 e22: 1 - x + a x e23 : mod(5,2); e23: 1 e24 : mod(x^4+4,x^2=2,x); e24: 8 @end group @end example @end deffn @deffn Command gcd poly_1 poly_2 The Jacal function @code{gcd} takes as arguments two polynomials with integer coefficients and returns a greatest common divisor of the two polynomials. This includes the case where the polynomials are integers. @example @group e1 : gcd(x^4-y^4,x^6+y^6); 2 2 e1: x + y e2 : gcd(4,10); e2: 2 @end group @end example @end deffn @deffn Command discriminant poly var Here @var{poly} is a polynomial and @var{var} is a variable. This function returns the square of the product of the differences of the roots of the polynomial @var{poly} with respect to the variable @var{var}. @example @group e7 : discriminant(x^3 - 1, x); e7: -27 @end group @end example @end deffn @deffn Command resultant poly_1 poly_2 var The function @code{resultant} returns the resultant of the polynomials @var{poly_1} and @var{poly_2} with respect to the variable @var{var}. @example @group e2 : resultant(x^2 + a, x^3 + a, x); 2 3 e2: a + a @end group @end example @end deffn @deffn Command equatecoeffs z1 z2 var Returns the list of equations formed by equating each coefficient of variable @var{var}^n in @var{z1} to the corresponding coefficient of @var{var}^n in @var{z2}. @var{z1} and @var{z2} can be polynomials or ratios of polynomials. @end deffn @node Factoring, , Polynomials, Algebra @section Factoring @cindex Factoring @deffn Command factor int The Jacal command @code{factor} takes as input an integer and returns a list of the prime numbers that divide it, each occurring with the appropriate multiplicity in the list. If the number is negative, the list will begin with -1. The results of the @code{factor} command are shown in a special @dfn{factored} format, which appears as the product of the factors. @example @group e0 : factor(120); 3 e0: 2 3 5 e1 : factor(-120); 3 e1: -1 2 3 5 @end group @end example @deffnx Command factor polyratio Given a univariate ratio of polynomials @var{polyratio}, returns a matrix of factors and exponents. As above, the results are shown in factored form. @example e2 : factor((14*x^4-10/68*x^-5)/(5*x^2+1)); 9 -5 + 476 x e2: ------------------ 2 5 2 17 (1 + 5 x ) x e3 : (14*x^4-10/68*x^-5)/(5*x^2+1); 9 -5 + 476 x e3: -------------- 5 7 34 x + 170 x e4 : (476*x^9-5)/(34*(5*x^2+1)*x^5); 9 -5 + 476 x e4: -------------- 5 7 34 x + 170 x @end example @example e5 : factor(x*y); e5: y x e6 : factor((x+a)*(y^4-z)); 4 e6: -1 (a + x) (- y + z) e7 : factor((x+u*a^3)*(y^4-z)); 3 4 e7: -1 (a u + x) (- y + z) e8 : factor((x+u*a^3)^2*(y^4-z)/((x+1)*(u^2-v^2))); 4 3 2 (- y + z) (a u + x) e8: ------------------------- (1 + x) (- u + v) (u + v) e9 : factor(200*(-1*x+1+y)*(u-r^6)*(21*x+2-t^4)); 3 2 6 4 e9: 2 5 (- r + u) (1 - x + y) (2 - t + 21 x) e10 : factor(2*(a+u)*(-v+b)*(a*x+y)^2); 2 e10: -1 2 (a + u) (- b + v) (a x + y) e11 : factor(2*(a+u)*(-v+b)*(a*x+y)^2/((u^2-v^2)*(11*x+55))); 2 2 (a + u) (- b + v) (a x + y) e11: ------------------------------ 11 (5 + x) (- u + v) (u + v) e12 : factor(2*(a+u)*(-v+b)*(a*x+y)^2/((u^2-v^2)*x^4*(11*x+55))); 2 2 (a + u) (- b + v) (a x + y) e12: ------------------------------- 4 11 (5 + x) (- u + v) (u + v) x e13 : factor((c^3*u+b*a)*(b*b*a+v*p^2*q^2*c)); 3 2 2 2 e13: (a b + c u) (a b + c p q v) e14 : factor((2*z+y-x)*(y^3-a*x^2)*(b*z^2+y)); 2 2 3 e14: (- x + y + 2 z) (y + b z ) (- a x + y ) e15 : factor((a*a*b*z+d)*(2*a*b*b*z+c)); 2 2 e15: (d + a b z) (c + 2 a b z) e16 : factor((a*a*b*z+d)*(2*a*b*b*z+c)*((u+a)*x+1)); 2 2 e16: (1 + (a + u) x) (d + a b z) (c + 2 a b z) e17 : factor((c*z+a)*(a*z+b)*(b*z+c)); e17: (b + a z) (c + b z) (a + c z) e18 : factor((a*a*b*(x+w)*z+d)*(2*a*b*b*z+c)); 2 2 2 e18: (d + (a b w + a b x) z) (c + 2 a b z) e19 : factor(((x+w)^2*z-u*d)*(-2*a*b*z+c)); 2 2 e19: -1 (- c + 2 a b z) (- d u + (w + 2 w x + x ) z) e20 : factor((-200*%i*x-c)*(x-d-z^5)/(a*(b^3-(a+u)*z))); 5 -1 (c + 200 %i x) (d - x + z ) e20: ------------------------------ 3 a (- b + (a + u) z) @end example @end deffn @noindent The rest of this section documents commands from the factoring package. To use this package, execute the following command from the JACAL prompt: @code{require("ff");} @noindent Several of these commands return a matrix. The first column contains the factors and the second column contains the corresponding exponent. @deffn Command sff poly Given a primitive univariate polynomial @var{poly}, calculate the square free factorisation of @var{poly}. A @dfn{primitive} polynomial is one with no factors (other than units) common to all its coefficients. @end deffn @deffn Command ffsff poly p @deffnx Command ffsff poly p m Given a monic polynomial @var{poly}, a prime @var{p}, and a positive integer @var{m}, calculate the square free factorisation of @var{poly} in GF(p^m)[x]. If @var{m} is not supplied, @code{1} is assumed. @example e0 : ffsff(x^5+x^3+1, 53); [ 2 3 ] [16 - 22 x + 26 x + x 1] e0: [ ] [ -13 + x 2] @end example @end deffn @deffn Command berl poly n Given a square-free univariate polynomial @var{poly} and an integer power of a prime, @var{q}, returns (as a bunch) the irreducible factors of @var{poly}. @example e2 : berl(x^5+x^3+2, 53); 2 2 e2: [1 + x, 5 - 26 x + x , 11 + 25 x + x ] @end example @end deffn @deffn Command parfrac polyratio Returns the partial fraction expansion of a rational univariate polynomial @var{polyratio}. The denominator of @var{polyratio} must be square free. This code is still being developed. @end deffn @node Calculus, Matrices and Tensors, Algebra, Top @chapter Calculus @cindex Calculus @section Differential Operator @deffn Operator differential expr @deffnx Operator ' expr The Jacal command @code{differential} computes the derivative of the expression @var{expr} with respect to a generic derivation. It is generic in the sense that nothing is assumed about its effect on the individual variables. The derivation is denoted by a right quote. @example @group e6 : differential(x^2+y^3); 2 e6: 2 x x' + 3 y y' e7 : (x^2+y^3)'; 2 e7: 2 x x' + 3 y y' @end group @end example @end deffn @section Derivative Commands @deffn Command diff expr var1 @dots{} The Jacal command @code{diff} computes the derivative of the expression @var{expr} with respect to @var{var1}, @dots{}. @example @group e6 : diff(x^2+y^3,y); 2 e6: 3 y @end group @end example @end deffn @deffn Command partial expr var1 @dots{} The Jacal command @code{partial} computes the partial derivative of the expression @var{expr} with respect to @var{var1}, @dots{}. @example @group e6 : partial(x^2+@@1^3,1); 2 e6: 3 @@1 @end group @end example @end deffn @deffn Command PolyDiff poly var1 @dots{} The Jacal command @code{PolyDiff} computes the derivative of the expression @var{poly} with respect to @var{var1}, @dots{}. It is faster than @code{diff} but @var{poly} must be a polynomial. @end deffn @node Matrices and Tensors, Lambda Calculus, Calculus, Top @chapter Matrices and Tensors In JACAL, a matrix is just a @code{bunch} of equal length @code{bunch}s, and this is the structure that the matrix operations currently supported by JACAL (ncmult(), ^^, transpose(), etc.) expect. @menu * Generating Matrices:: * Matrix Parts:: * Matrix commands:: * Tensors:: * tmult:: Tensor Multiplication * contract:: Tensor Contraction * indexshift:: Shift an index within a tensor * indexswap:: Swaps two indices within a tensor @end menu @node Generating Matrices, Matrix Parts, Matrices and Tensors, Matrices and Tensors @section Generating Matrices @deffn Operator bunch elt_1 elt_2 @dots{} @code{[@var{elt_1}, @var{elt_2}, @dots{}]} To collect any number of Jacal objects into a bunch, simply enclose them in square brackets. For example, to make the bunch whose elements are @code{1}, @code{2}, @code{4}, type @code{[1, 2, 4]}. One can also nest bunches, for example, @code{[1, [[1, 3], [2, 5]], [1, 4]]}. Note however that the bunch whose only element is @code{[1, 2, 3]} is @code{[1 2 3]}. It is importance to notice that one has commas and the other doesn't. @example @group e3 : a:bunch(1, 2, 3); e3: [1, 2, 3] e4 : b:[a]; e4: [1 2 3] e5 : c:[b]; e5: [[1, 2, 3]] e6 : [[[1, 2, 3]]]; e6: [[1, 2, 3]] @end group @end example @end deffn @deffn Operator flatten bnch Removes bunch nesting from @var{bnch}, returning a single bunch of the constituent expressions and equations. @example @group e0 : flatten([a, [b, [c, d]], [5]]); e0: [a, b, c, d, 5] @end group @end example @end deffn @deffn Command ident n The command @code{ident} takes as argument a positive integer @var{n} and returns an @var{n}x@var{n} identity matrix. This is sometimes more convenient than obtaining this same matrix using the command @code{scalarmatrix}. @example @group e6 : ident(4); [1 0 0 0] [ ] [0 1 0 0] e6: [ ] [0 0 1 0] [ ] [0 0 0 1] @end group @end example @end deffn @deffn Command scalarmatrix size entry The command @code{scalarmatrix} takes as inputs a positive integer @var{size} and an algebraic expression @var{entry} and returns an @code{@var{n} * @var{n}} diagonal matrix whose diagonal entries are all equal to @var{entry}, where @code{@var{n} = @var{size}}. @example @group e1 : scalarmatrix(3, 6); [6 0 0] [ ] e1: [0 6 0] [ ] [0 0 6] @end group @end example @end deffn @deffn Command diagmatrix list The Jacal command @code{diagmatrix} takes as input a list of objects and returns the diagonal matrix having those objects as diagonal entries. In case one wants all of the diagonal entries to be equal, it is more convenient to use the command @code{scalarmatrix}. @example @group e3 : diagmatrix(12,3,a,s^2); [12 0 0 0 ] [ ] [0 3 0 0 ] e3: [ ] [0 0 a 0 ] [ ] [0 0 0 2] [ s ] e4 : diagmatrix([1,2],2); [[1, 2] 0] e4: [ ] [ 0 2] @end group @end example @end deffn @deffn Command sylvester poly_1 poly_2 var Here, @var{poly_1} and @var{poly_2} are polynomials and @var{var} is a variable. The function @code{sylvester} returns the matrix introduced by Sylvester (@cite{A Method of Determining By Mere Inspection the Derivatives from Two Equations of Any Degree, Phil.Mag. @code{16} (1840) pp. 132-135, Mathematical Papers, vol. I, pp. 54-57}) for computing the resultant of the two polynomials @var{poly_1} and @var{poly_2} with respect to the variable @var{var}. If one wants to compute the resultant itself, one can simply use the command @code{resultant} with the same syntax. @example @group e5 : sylvester(a0 + a1*x + a2*x^2 + a3*x^3, b0 + b1*x + b2*x^2, x); [a3 a2 a1 a0 0 ] [ ] [0 a3 a2 a1 a0] [ ] e5: [b2 b1 b0 0 0 ] [ ] [0 b2 b1 b0 0 ] [ ] [0 0 b2 b1 b0] @end group @end example @end deffn @deffn Command genmatrix function rows cols The function @code{genmatrix} takes as arguments a @var{function} of two variables and two positive integers, @var{rows} and @var{cols}. It returns a matrix with the indicated numbers of rows and columns in which the $(i,j)$th entry is obtained by evaluating @var{function} at $(i,j)$. The function may be defined in any of the ways available in Jacal, i.e previously by an explicit algebraic definition, by an explicit lambda expression or by an implicit lambda expression. @example @group e4 : @@1^2+@@2^2; 2 2 e4: lambda([@@1, @@2], @@1 + @@2 ) e5 : genmatrix(e4,3,5); [2 5 10 17 26] [ ] e5: [5 8 13 20 29] [ ] [10 13 18 25 34] @end group @end example @end deffn @node Matrix Parts, Matrix commands, Generating Matrices, Matrices and Tensors @section Matrix Parts @deffn Command row matrix i The command @code{row} returns the @var{i}th row of the matrix @var{matrix}, where @code{i = @var{int}}. If @var{int} is larger than the number of rows of @var{matrix}, then Jacal prints an error message. The corresponding command for columns of a matrix is @code{col}. @example @group e3 : u:[[1, 2, 3], [1, 5, 3]]; [1 2 3] e3: [ ] [1 5 3] e4 : row(u, 2); e4: [1, 5, 3] @end group @end example @end deffn @deffn Command col matrix integer The command @code{col} is used to extract a column of a matrix. Here, @var{matrix} is a matrix and @var{integer} is a positive integer. If that integer exceeds the number of columns, an error message such as @example @group ERROR: list-ref: Wrong type in arg1 () @end group @end example @noindent appears. Here is an example of correct use of the command @code{col}: @example @group e19 : a:[[1,2,4],[2,5,6]]; [1 2 4] e19: [ ] [2 5 6] e20 : col(a,2); [2] e20: [ ] [5] @end group @end example @end deffn @deffn Command minor matrix i j The command @code{minor} returns the submatrix of @var{matrix} obtained by deleting the @var{i}th row and the @var{j}th column. @example @group e21 : b:[[1,2,3],[3,1,5],[5,2,7]]; [1 2 3] [ ] e21: [3 1 5] [ ] [5 2 7] e22 : minor(b,3,1); [2 3] e22: [ ] [1 5] @end group @end example @end deffn @deffn Command cofactor matrix i j The command @code{cofactor} returns the determinant of the @var{i}, @var{j} @code{minor} of @var{matrix}. @end deffn @deffn Command rapply bunch int_1 int_2 @dots{} The function @code{rapply} is used to access elements of bunches. It can also access elements nested at lower levels in a bunch. In particular, it can also access matrix elements. In the above syntax, @var{bunch} is the bunch whose parts one wishes to access, and @var{n}, @var{int_1}, @var{int_2}, @dots{}, @var{int_n} are positive integers. It returns the @var{int_n}-th element of the @var{int_@{n-1@}}-th element of @dots{} of the @var{int_2}-th element of the @var{int_1}-th element of @var{bunch}. One can have @code{n = 0}. In that case, @code{rapply} simply returns the bunch. @example @group e2 : rapply([[1,2,3],[1,4,6],3],2,3); e2: 6 e6 : rapply([a,b],2); e6: b e7 : rapply([a,b]); e7: [a, b] @end group @end example @end deffn @node Matrix commands, Tensors, Matrix Parts, Matrices and Tensors @section Matrix commands @deffn Command . matrix1 matrix2 Matrix multiplication. @example @group e1 : a:[[1, 2, 3], [5, 2, 7]]; [1 2 3] e1: [ ] [5 2 7] e2 : b:[[3, 2], [6, 4]]; [3 2] e2: [ ] [6 4] e3 : b . a; [13 10 23] e3: [ ] [26 20 46] @end group @end example @end deffn @deffn Command ^^ matrix exponent The infix operator @code{^^} is used for raising a square matrix to an integral power. @example @group e8 : a:[[1, 0], [-1, 1]]; [1 0] e8: [ ] [-1 1] e9 : a^^3; [1 0] e9: [ ] [-3 1] @end group @end example Negative exponents raise the inverse matrix to a power. @example @group e8 : [[a, b], [c, d]]; [a b] e8: [ ] [c d] e9 : e8^^-1; [ d - b ] [----------- -----------] [- b c + a d - b c + a d] [ ] e9: [ - c a ] [----------- -----------] [- b c + a d - b c + a d] e10 : e8^^-2; [ 2 - a b - b d ] [ b c + d -------------------------] [------------------------- 2 2 2 2] [ 2 2 2 2 b c - 2 a b c d + a d ] [b c - 2 a b c d + a d ] [ 2 ] e10: [ - a c - c d a + b c ] [------------------------- -------------------------] [ 2 2 2 2 2 2 2 2] [b c - 2 a b c d + a d b c - 2 a b c d + a d ] @end group @group e11 : e8 . e9; [1 0] e11: [ ] [0 1] e12 : e9 . e8; [1 0] e12: [ ] [0 1] e13 : e10 . e8 . e8; [1 0] e13: [ ] [0 1] @end group @end example @end deffn @deffn Command dotproduct vector_1 vector_2 The Jacal function @code{dotproduct} returns the dot product of two row vectors of the same length. It will also give the dot product of two matrices of the same size by computing the sum of the dot products of the corresponding rows or, what is the same, the trace of one matrix times the transpose of the other one. @example @group e28 : a:[1,2,3]; b:[3,1,5]; e28: [1, 2, 3] e29 : e29: [3, 1, 5] e30 : dotproduct(a,b); e30: 20 @end group @end example @end deffn @deffn Command crossproduct vector_1 vector_2 The Jacal command @code{crossproduct} computes the cross product of two vectors. By definition, the two vectors must each have three components. @example @group e24: [2 x, y + 2 x y ] e25 : crossproduct([1,2,3],[4,2,5]); e25: [4, 7, -6] @end group @end example @end deffn @deffn Command determinant matrix The Jacal command @code{determinant} computes the determinant of a square matrix. Attempting to take the determinant of a non-square matrix will produce an error message. @example @group e1 : a:[[1,2],[6,7]]; [1 2] e1: [ ] [6 7] e2 : determinant(a); e2: -5 @end group @end example @end deffn @deffn Command transpose matrix Computes the transpose of @code{(@var{matrix})}. @end deffn @node Tensors, tmult, Matrix commands, Matrices and Tensors @section Tensors The @code{tensors} supported by JACAL are an extension of the matrix structure (i.e., a bunch of bunches of bunches ...) with the added stipulation that all @code{dimensions} of the tensor be the same length (e.g., 4x4x4). The number of dimensions (indices) in a tensor is its rank: A scalar is a tensor of rank 0; a vector is a rank 1 tensor; a matrix has rank 2; and so on. Further, just as matrix binary operations place restrictions on the matrices involved (e.g., the row/column length requirement for matrix multiplication), the tensor binary operations require that the dimensions of each tensor be of the same length. For example, you could not multiply a 3x3 tensor and a 4x4x4 tensor. JACAL's tensors do not support the construct of contravariant and covariant indices. Users must keep track of this information themselves, and perform the necessary operations with an appropriate metric so that the "index gymnastics" is performed correctly. Before using any of JACAL's tensor operations, execute the following command from the JACAL prompt: require("tensor"); This loads the file @file{tensor.scm} into JACAL, and makes the tensor operations available for use. JACAL currently supports four tensor operations: @code{tmult}, @code{contract}, @code{indexshift}, and @code{indexswap}. Each of these is described in detail below. @node tmult, contract, Tensors, Matrices and Tensors @section Tensor Multiplication @deffn Command tmult matrix_1 matrix_2 index_1 index_2 @code{tmult} takes a minimum of two arguments which are the tensors on which the multiplication operation is to be performed. With no additional arguments, @code{tmult} will produce the outer product of the two input tensors. The rank of the resulting tensor is the sum of the inputs' ranks, and the components of the result are formed from the pair-wise products of components of the inputs. For example, for the input tensors @code{x[a,b]} and @code{y[c]} @example @result{z:tmult(x,y);} z[a,b,c] = x[a,b]*y[c] @end example With an additional argument, @code{tmult} will produce the inner product of the two tensors on the specified index. For example, given @code{x[i,j]} and @code{y[k,l,m]} @example @group z:tmult(x,y,3); @result{} length ----- \ z[a,b,c] = > x[a,q] * y[b,c,q] / ----- q = 1 @end group @end example Note that in this case @var{x} only has 2 indices. All of JACAL's tensor operations modify index inputs to be between 1 and the rank of the tensor. Thus, in this example, the 3 is modified to 2 in the case of @var{x}. As another example, with @code{x[i,j,k]} and @code{y[l,m,n]} @example @group z:tmult(x,y,2); @result{} length ----- \ z[a,b,c,d] = > x[a,q,b] * y[c,q,d] / ----- q = 1 @end group @end example With four arguments, @code{tmult} produces an inner product of the two tensors on the specified indices. For example, for @code{x[i,j]} and @code{y[k,l,m]} @example @group z:tmult(x,y,1,3); @result{} length ----- \ z[a,b,c] = > x[q,a] * y[b,c,q] / ----- q = 1 @end group @end example Note that matrix multiplication is the special case of an inner product (of two "two dimensional matrices") on the second and first indices, respectively: @code{tmult(x,y,2,1) @equiv{} ncmult(x,y)} Finally, tmult handles the case of a scalar times a tensor, in which case each component of the tensor is multiplied by the scalar. @end deffn @node contract, indexshift, tmult, Matrices and Tensors @section Tensor contraction @deffn Command contract matrix index1 @dots{} The contraction operation produces a tensor of rank two less than a given tensor. It does this by performing a summation over two of the indices of the given tensor, as clarified in the examples below. @code{contract} takes at least one argument which is the tensor on which the contraction operation is to be performed. One or two additional arguments may be provided to specify the indices to be used in the summation. If no additional arguments are provided, the summation is performed over the first and second indices. With one additional argument, the summation is over the specified index and the one following it (e.g., if 3 is specified, the third and fourth indices are used). With two additional arguments, the summation is performed over the indices specified. The actual indices used will be constrained to be between 1 and the rank of the tensor. Examples: 1) For a square matrix (tensor of rank 2), @code{contract} returns a scalar that is the sum of the diagonal elements of the matrix. 2) Given @code{x[i,j,k,l]}, the command @example y:contract(x,2,4); @end example produces: @example @group length ----- \ y[a,b] = > x[a,q,b,q] / ----- q = 1 @end group @end example Special cases: If @code{contract} is given a scalar (rank 0 tensor) as input, it just returns the scalar. For a vector (tensor of rank 1), @code{contract} returns a scalar that is the sum of the elements of the vector. @end deffn @node indexshift, indexswap, contract, Matrices and Tensors @section Shifting of Tensor Indices @deffn Command indexshift matrix index1 @dots{} @code{indexshift} rearranges the indices of a tensor. It is one of two generalizations of the matrix transpose operation (cf. @code{indexswap}). @code{indexshift} takes at least one argument which is the tensor on which the index shifting is to be performed. One or two additional arguments may be provided to specify the index and the position to which it is to be shifted. If no additional arguments are provided, the first index of the tensor is shifted to the second position (equivalent the matrix transpose operation). If one additional argument is provided, it specifies the index to be shifted, and that index will be shifted "to the right" one position (e.g., if 3 is specified, the third index will be shifted to the forth position). If two additional arguments are provided, the first specifies the index and the second specifies the position to which it is to be shifted. The actual index shifted and its shifted position will be constrained to be between 1 and the rank of the tensor. For example, given @code{x[a,b,c,d]}, the command @code{y:indexshift(x,1,3);} produces a tensor @var{y} such that @code{y[a,b,c,d] @equiv{} x[b,c,a,d]}. In this example, the element that was in position @code{[a,b,c,d]} in @var{x} will be in position @code{[b,c,a,d]} in @var{y}. Special cases: If @code{indexshift} is given a scalar (rank 0 tensor) as input, it just returns the scalar. For a vector (tensor of rank 1), @code{indexshift} transposes the 1-by-n matrix (row vector) to an n-by-1 matrix (column vector). @end deffn @node indexswap, , indexshift, Matrices and Tensors @section Swapping of Tensor Indices @deffn Command indexswap tensor @dots{} @code{indexswap} rearranges the indices of a tensor. It is one of two generalizations of the matrix transpose operation (cf. @code{indexshift}). @code{indexswap} takes at least one argument which is the tensor on which index swapping is to be performed. One or two additional arguments may be provided to specify the indices to be swapped. If no additional arguments are provided, the first and second indices of the tensor are swapped (equivalent the matrix transpose operation). With one additional argument, the specified index is swapped with the one following it (e.g., if 2 is specified, the second and third indices will be swapped). If two additional arguments are provided, they specify the indices to be swapped. The actual indices used will be constrained to be between 1 and the rank of the tensor. For example, given x[a,b,c,d], the command @code{y:indexswap(x,2,4);} produces a tensor @var{y} such that y[a,b,c,d] = x[a,d,c,b]. In this example, the element that was in position [a,b,c,d] in @var{x} will be in position [a,d,c,b] in @var{y}. Special cases: If @code{indexswap} is given a scalar (rank 0 tensor) as input, it just returns the scalar. For a vector (tensor of rank 1), @code{indexswap} transposes the 1-by-n matrix (row vector) to an n-by-1 matrix (column vector). @end deffn @node Lambda Calculus, Miscellaneous, Matrices and Tensors, Top @chapter Lambda Calculus @section Create a lambda expression @deffn Operator lambda varlist expression Jacal has the ability to work with lambda expressions, via the command @code{lambda}. Furthermore, Jacal always converts user definitions of functions by any method into lambda expressions and converts the dummy variables of the function definition into symbols such as @var{1}, @var{2}, @dots{}. Jacal can manipulate lambda expressions by manipulating their function parts, as in @samp{e14} below. Jacal can also invert a function using the command @code{finv}. @example @group e12 : lambda([x],x^2); 2 e12: lambda([@@1], @@1 ) e13 : lambda([x,y,z],x*y*z); e13: lambda([@@1, @@2, @@3], @@1 @@2 @@3) e14 : e12+e13; 2 e14: lambda([@@1, @@2, @@3], @@1 + @@1 @@2 @@3) @end group @end example @end deffn @section Compute inverse function @deffn Command finv function @code{@var{function}^^-1} The command @code{finv} takes as input a function of one variable and returns the inverse of that function. The function may be defined in any of the ways permitted in Jacal, i.e. by an explicit algebraic definition, by an explicit lambda expression or by an implicit lamba expression. If @var{f} is the function, then typing @code{f^^-1} has the same effect as typing @code{finv(@var{f})}. @example @group e0 : w(t):=t+1; w(t): lambda([@@1], 1 + @@1) e0 : finv(w); e0: lambda([@@1], -1 + @@1) @end group @end example @end deffn @node Miscellaneous, Flags, Lambda Calculus, Top @chapter Miscellaneous @deffn Command % The symbol @code{%} represents the last expression obtained by Jacal. It can be used in formulas like any other constant or variable or expression. @example @group e21: 5 e22 : %; e22: 5 e23 : %^2; e23: 25 @end group @end example @end deffn @deffn Command batch filename The command @code{batch} is used to read in a file containing programs written in Jacal. Here, @var{filename} is a string in double quotes. The precise way in which one refers to a file is, of course, system dependent. @example @group batch("demo"); @end group @end example of the file demo in the JACAL directory will give a demonstration of JACAL's capabilities. @end deffn @deffn Command commands The command @code{commands} produces a list of all of the command available in Jacal. It is called as s function of no arguments. Explicitly: @example @group e21 : commands(); u-/+ u+/- transpose transcript differential terms system sylvester show set scalarmatrix row resultant rapply quit qed discriminant poly or num negate mod minor matrix load listofvars ident genmatrix gcd finv factor example eliminate dotproduct divide diff diagmatrix determinant describe denom crossproduct content commands col coeffs coeff bunch batch b+/- ^^ ^ = / - + * % @end group @end example @end deffn @deffn Command describe command The command @code{describe} is the heart of the online help facility of Jacal. Here, @var{command} is a string which is the name of a command and @code{describe} produces a brief description of the command and in many cases includes an example of its use. Together with the command @code{commands()}, which prints a list of all available Jacal commands, and the command @code{example}, which gives an example of the use of the command, one can in principle use Jacal without a manual after one has learned how to get started. @example @group e27 : describe(col); column. column of a matrix e27 : describe(resultant); resultant. The result of eliminating a variable between 2 equations (or polynomials). 27 : describe(+); Addition, plus. a + b @end group @end example @end deffn @deffn Command example command Here, @var{command} is a string which is the name of a Jacal command. @code{example} gives an example of the use of the command. See also @ref{Miscellaneous,describe}. @example @group e43 : example(+); a + b e43: a + b @end group @end example @end deffn @deffn Command load string The Jacal command @code{load} takes as input a string and reads in a @samp{Scheme} file whose name is obtained by appending the extension @file{.scm} to the string. If you want to read in a file of Jacal commands, do not use @code{load}. Instead use the command @code{batch}. To load in the file @file{foo.scm}, @example @group e9 : load("foo"); e9: foo @end group @end example @end deffn @deffn Command qed Exit from Jacal to Scheme. With interactive Scheme systems (such as SCM), It does not return you to the operating system. Instead it suspends Jacal and returns you to the underlying scheme. You can return to the Jacal session where you left off by simply typing @code{(math)}. If you do not wish to return to Jacal but really want to terminate the session and return to the operating system, then after typing @code{qed();}, type @code{(slib:exit)} or use @code{quit}. @deffnx Command quit Exit directly from Jacal to the operating system. You will not be able to continue your Jacal session. @example @group type qed(); to return to scheme e1 : qed(); scheme > (math) type qed(); to return to scheme e2 : quit(); unix> @end group @end example @end deffn @deffn Command system command One can issue commands to the operating system without leaving Jacal. To do this, one uses the command @code{system}. For example, in a UNIX operating system, the command @code{system("ls");} will print the directory. One way in which the command @code{system} might be especially useful is to edit files containing Jacal scripts without leaving Jacal, particularly in non-UNIX machines or on machines without GNU emacs. @example @group e0 : system("echo hi there"); hi there e0: 0 @end group @end example @end deffn @deffn Command terms Prints a copy of the GNU General Public License @example @group e1 : terms(); GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @end group @end example [ rest deleted for brevity] @end deffn @deffn Command transcript string The command @code{transcript} allows one to record a Jacal session. It is called with the syntax @code{transcript(@var{string});}, where @var{string} is the name of the file in which one wants to keep the transcript of the session. When one wishes to stop recording, one types @code{transcript();}. One is then free to use @code{transcript} again later in the session on another file. One can use it on the same file, but the file is overwritten. Presently, the command @code{transcript} does not echo commands to a file. @example @group e9 : a:[1,2,3]; e9: [1, 2, 3] e10 : transcript("foo"); e10: foo e11 : a; e11: [1, 2, 3] e12 : transcript(); e12 : system("cat foo"); e10: foo e11 : a; e11: [1, 2, 3] e12 : transcript(); e12: 0 @end group @end example @end deffn @deffn Command set flag value There are various flags that the Jacal user can control, namely the Jacal command line prompt, the priority for printing terms in Jacal output, the input grammar and the output grammar. For a discussion of the various grammars please @xref{Flags}. The command @code{show} is closely related, allowing one to see what the current settings are. @end deffn @deffn Command show flag The command @code{show} enables the Jacal user to examine the current setting of various flags as well as to list the flags that can be set by the user and to display other information. To change the settings of the flags, use the command @code{set}. To see all the information accessible through the @code{show} command, type @code{show all}. To see the available grammars, type @code{show grammars}. To see the current input grammar type @code{show ingrammar}. To see the current output grammar, type @code{show outgrammar}. To see the current priority for printing expressions, type @code{show priority}. @example @group e1 : show all; prompt priority outgrammar ingrammar grammars all e1 : show prompt; e1: e1 e3 : show priority; :@@ (differential :@@) @@3 @@2 @@1 %inftsl y x u-/+ u+/- transpose transcript differential terms t system sylvester showpriority show set scalarmatrix row resultant rapply quit qed prompt priority discriminant poly or num negate mod minor matrix load listofvars ident genmatrix gcd finv factor example eliminate e1 dotproduct divide diff diagmatrix determinant describe denom crossproduct content commands col coeffs coeff c bunch batch b-/+ b+/- b all a ^^ ^ = / - + * % %sqrt1 %i e3 : show outgrammar; e3: disp2d e4 : show ingrammar; e4: standard e5 : show grammars; e5: [disp2d, standard, schemepretty, scheme] @end group @end example @end deffn @node Flags, Index, Miscellaneous, Top @chapter Flags @defvr Flag prompt string If one changes the prompt, @var{string} is a string of alphanumeric characters without quotes. After this command is executed, subsequent commands will cause new prompts to be obtained from @var{string} by incrementing it. If the prompt ends in a letter, it will be treated as a digit in base 26 and incremented. If it ends in a string of digits, that string will be treated as a number in base 10 and incremented. The remaining characters in the string will play no role in this incrementation. @example @group e1 : set prompt az9Z; e1 : a+b; az9Z: a + b az9AA : a+b; az9AA: a + b az9AB : set prompt ok99; az9AB : a+b; ok99: a + b ok100 : a+b; ok100: a + b ok101 : @end group @end example @end defvr @defvr Flag ingrammar grammar @defvrx Flag outgrammar grammar The following examples show how one changes the input grammar or the output grammar. @example @group e1 : a:[[[1,2,3]]]; e1: [[1, 2, 3]] e2 : set outgrammar standard; e2 : a; e2: [[[1, 2, 3]]] e3 : set outgrammar scheme; e3 : a; (define e3 #(#(#(1 2 3)))) e4 : (1+x)^5; @end group @group (define e4 (+ 1 (* 5 x) (* 10 (^ x 2)) (* 10 (^ x 3)) (* 5 (^ x 4)) (^ x 5))) e6 : set ingrammar scheme; e6 : (+ e4 1); (define e6 (+ 2 (* 5 x) (* 10 (^ x 2)) (* 10 (^ x 3)) (* 5 (^ x 4)) (^ x 5))) e7 : (set ingrammar disp2d) e7 : diagmatrix(3,6); (define e7 #(#(3 0) #(0 6))) e8 : set outgrammar disp2d; e8 : e7; [3 0] e8: [ ] [0 6] e9 : set outgrammar standard; e9 : e7; e9: [[3, 0], [0, 6]] @end group @end example Note that in the above examples, it is possible to input and output expressions in scheme by setting the ingrammar and/or outgrammar to @code{scheme}. Doing so result in linear output (as with @code{standard grammar}) as opposed to a two dimensional display (as with @code{disp2d}). The analogue of @code{disp2d} for scheme output is scheme pretty-printing. To have such output, set the output grammar to @code{schemepretty}. @example @group e4 : set outgrammar schemepretty; e4 : (1+x)^5; (define e4 (+ 1 (* 5 x) (* 10 (^ x 2)) (* 10 (^ x 3)) (* 5 (^ x 4)) (^ x 5))) @end group @end example Jacal also allows for output to be automatically typeset in @TeX{}. This can be quite useful if one wants to use the results of one's computations in published articles. Continuing with the example of @code{(1+x)^5} above, we have: @example @group e5 : set outgrammar tex; e5 : e4; e5: 1 + 5 x + 10 x^@{2@} + 10 x^@{3@} + 5 x^@{4@} + x^@{5@} e6 : (1+1/x)^3/(1-1/y)^4; e6: @{\left(1 + 3 x + 3 x^@{2@} + x^@{3@}\right) y^@{4@}@}\over@{x^@{3@} - 4 x^@{3@} y + 6 x^@{3@} y^@{2@} - 4 x^@{3@} y^@{3@} + x^@{3@} y^@{4@}@} @end group @end example @ifinfo That looks much better when formatted by TeX in an article than the actual Jacal output in @code{disp2d} grammar. @end ifinfo @tex After being included in a document in math display mode, these two examples will appear in the following way. $$1 + 5 x + 10 x^{2} + 10 x^{3} + 5 x^{4} + x^{5}$$ $${\left(1 + 3 x + 3 x^{2} + x^{3}\right) y^{4}}\over{x^{3} - 4 x^{3} y + 6 x^{3} y^{2} - 4 x^{3} y^{3} + x^{3} y^{4}}$$ @end tex @end defvr @defvr Flag priority int The following examples show how to set the priority of printing terms. @example @group e10 : a; e10: [[[1, 2, 3]]] e11 : show priority a; ;;; not a simple variable: (((1 2 3) . ()) . ()) e12 : show priority b; e12: 128 e13 : show priority c; e13: 128 e14 : b+c; e14: b + c e15 : c+b; e15: b + c e16 : set priority b 200; e16 : b+c; @end group @end example @end defvr @node Index, , Flags, Top @unnumbered Index @printindex fn @bye jacal-1b9/elk.scm0000644001705200017500000000012510174611304011571 0ustar tbtb(load "/usr/local/lib/slib/elk.init") (slib:load "/usr/local/lib/jacal/math") (math) jacal-1b9/jacal.10000644001705200017500000000272410732647302011464 0ustar tbtb.\" dummy line .TH JACAL "Dec 20 2007" .UC 4 .SH NAME JACAL \- symbolic mathematics system .SH SYNOPSIS .B jacal [ scheme | scm | gsi | mzscheme | guile | scheme48 | larceny | scmlit | elk | sisc | kawa ] .br .sp 0.3 .SH DESCRIPTION JACAL is a symbolic mathematics system for the simplification and manipulation of equations and single and multiple valued algebraic expressions constructed of numbers, variables, radicals, and algebraic functions, differential, and holonomic functions. In addition, vectors and matrices of the above objects are included. .SH OPTIONS The optional argument to the .I jacal script is the Scheme implementation to run. Absent the argument, it searches for implementations in the above order. .SH ENVIRONMENT VARIABLES .TP .B SCHEME_LIBRARY_PATH is the SLIB Scheme library directory. .SH FILES .TP jacal.info .br Texinfo documentation of .I jacal. .TP demo .br batch("demo"); to demonstrate commands in .I jacal .TP rw.math .br batch("rw.math"); to demonstrate tensors in "The Robertson-Walker Cosmology Model". .TP test.math .br batch("test.math"); for regression suite. .SH AUTHORS Aubrey Jaffer (agj @ alum.mit.edu) .br Michael Thomas .br Jerry D. Hedden .SH SEE ALSO The JACAL home-page: .br http://swiss.csail.mit.edu/~jaffer/JACAL.html .TP The full documentation for jacal is maintained as a Texinfo manual. If the info and jacal programs are properly installed at your site, the command .br info jacal .TP should give you access to the complete manual. jacal-1b9/toploads.scm0000644001705200017500000001063410750526551012662 0ustar tbtb;; JACAL: Symbolic Mathematics System. -*-scheme-*- ;; Copyright 1989, 1990, 1991, 1992, 1993, 1995, 1997, 2002, 2008 Aubrey Jaffer. ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or (at ;; your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; If BYTE requires ARRAY, then it will redefine EQUAL?, which will ;;; screw up HASH-TABLE. So require BYTE first. (require 'byte) (require 'hash-table) (require-if 'compiling 'info) (require-if 'compiling 'precedence-parse) (define *jacal-version* "1b9") (define (jacal:dot) (display ".") (force-output)) (jacal:dot) (slib:load (in-vicinity (program-vicinity) "types")) (jacal:dot) ;Variables and type conversions. (define (math:exit b) (cleanup-handlers!) (slib:error "error in math system")) ;error handling when not running (math) [read-eval-print loop] ;(define *diagnostic-output* (current-output-port)) (slib:load (in-vicinity (program-vicinity) "grammar")) (jacal:dot) ;grammar, I/O, test, and error routines. ;;; Dynamic Variables -- These get set in "modeinit.scm" ;grammars to use if none is loaded. (define *input-grammar* (get-grammar 'scheme)) (define *output-grammar* (get-grammar 'scheme)) (define *echo-grammar* (get-grammar 'null)) (define tran:translations '()) (define Language #f) (define math:debug #f) (define math:phases #f) (define math:trace #f) (define linkradicals #f) (define horner #f) (define page-height #f) (define page-width #f) (define newextstr #f) (define newlabelstr #f) (define newlabelsym #f) (define % #f) (define *modulus* 0) ;(define *symdefs* '()) ;":" environment. (define *symdefs* (make-hash-table 37)) ;":" environment. (defmacro:load (in-vicinity (program-vicinity) "sexp")) (jacal:dot) ;read-eval-print loop. Conversion from ;sexpression to internal form and back. (slib:load (in-vicinity (program-vicinity) "poly")) (jacal:dot) ;Routines which operate on internal data type POLY. (slib:load (in-vicinity (program-vicinity) "elim")) (jacal:dot) ;Routines which eliminate variables. (slib:load (in-vicinity (program-vicinity) "vect")) (jacal:dot) ;Routines which operate on lists of POLY (mtrx). (slib:load (in-vicinity (program-vicinity) "norm")) (jacal:dot) ;Differentials; logical operations. (slib:load (in-vicinity (program-vicinity) "sqfree")) (jacal:dot) ;square-free. (slib:load (in-vicinity (program-vicinity) "builtin")) (jacal:dot) ;Routines defined for sexpressions. (define (info:describe obj) ;autoload for info (require 'info) (info:describe obj)) (define (info:example obj) ;autoload for info (require 'info) (info:example obj)) (define (definfo . args) ;autoload for info (require 'info) (apply definfo args)) (slib:load (in-vicinity (program-vicinity) "ext")) (jacal:dot) ;Field extension creation and simplification. (require 'precedence-parse) ;Fixup prec:warn (define (prec:warn . msgs) (do ((j (+ -1 tok:column) (+ -8 j))) ((> 8 j) (do ((i j (+ -1 i))) ((>= 0 i)) (display-diag #\space))) (display-diag slib:tab)) (display-diag "^ ") (for-each (lambda (x) (tran:translate x) (display-diag #\space)) msgs) (newline-diag)) (jacal:dot) ;General parser (slib:load (in-vicinity (program-vicinity) "unparse")) (jacal:dot) ;infix printer. (catalog:read jacal-vicinity "jacalcat") ;;; These routines test the core mathematical routines; ;;; Beware if they produce warnings or errors. (poly:test) ;Test for routines in "poly" (elim:test) ;Test for routines in "bunch" ;(factor:test) ;(mtrx:test) ;;(slib:load (in-vicinity (program-vicinity) "debug")) (newline) (display "JACAL version ") (display *jacal-version*) (display ", Copyright 1989-2005 Aubrey Jaffer JACAL comes with ABSOLUTELY NO WARRANTY; for details type `(terms)'. This is free software, and you are welcome to redistribute it under certain conditions; type `(terms)' for details. ") (display ";;; Type (math) to begin.") (newline) (force-output) jacal-1b9/types.scm0000644001705200017500000004103010667300650012170 0ustar tbtb;; JACAL: Symbolic Mathematics System. -*-scheme-*- ;; Copyright 1989, 1990, 1991, 1992, 1993, 1995, 1997 Aubrey Jaffer. ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or (at ;; your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. (require 'object->string) (require 'hash-table) (require 'rev4-optional-procedures) (require 'common-list-functions) ;;; Scheme doesn't allow for definition of new types which are ;;; distinct from existing types. So we will carefully use BUNCH ;;; instead of LIST in order to distinguish the types. ;;; This requires that boolean?, pair?, symbol?, number?, ;;; string?, vector? and procedure? be disjoint as outlined in: ;;; Jonathan Rees and William Clinger, editors. The Revised^3 ;;; Report on the algorithmic language Scheme, ACM SIGPLAN Notices ;;; 21(12), ACM, December 1986. ;;; If the types are not disjoint you WILL lose. ;;; The following types are mutually exclusive: ;;; SEXP, VARIABLE, EXPL, IMPL, EQLT, BUNCH ;;; INTEGERs are EXPL ;;; An EXPR is an EXPL or IMPL ;;; A LICIT is an EXPL, IMPL, or EQLT. ;;; VARIBLEs can only occur as part of EXPRS and EQLTS. ;;; SYMBOLs can only occur in SEXP. ;;; BUNCHES can contain SYMBOLs, LICITs, and BUNCHEs. ;;; An EXPL, IMPL, or EQLT, or BUNCH of these can be a ;;; lambda expression. ;;; A VAR is a vector which consists of: ;;; 0 var:sexp - s-expression ;lambda vars have leading "@" ;;; 1 var:pri - string ;ordering priority ;first char is priority override ;last char is differential order ;;; 2 var:def - poleq ;ext defining equation ;;; or - integer ;simple lambda position ;;; or - procedure ; ;;; 3 var:depends - list of vars ;vars used in var:def ;;; 4 var:shadow - var ;shadow copies of this lambda var or #f ;;;; THE REST ARE FOR FUNCTIONS ONLY ;;; 5 func-arglist ;list of (function and) argument values. ;;; 6 func-parity - list of atoms ;EVEN, ODD, 0, or #F ;;; 7 func-syms - list of lists ;of positions of arguments ;;; 8 func-anti-syms - list of lists ;of positions of arguments ;;; 9 func-dists - list of lists ;of functions which distribute ;;; 10 func-anti-dists - list of lists ;of functions which anti-distribute ;;; 11 func-idems - list ;of positions of arguments ; perserved in idempotency (define make-var vector) (define poly:var? vector?) (define (var:sexp v) (vector-ref v 0)) (define (var:pri v) (char->integer (string-ref (vector-ref v 1) 0))) (define (var:set-pri! v i) (string-set! (vector-ref v 1) 0 (integer->char i))) (define (var:def v) (vector-ref v 2)) (define (var:set-def! v i) (vector-set! v 2 i) v) (define (var:depends v) (vector-ref v 3)) (define (var:set-depends! v i) (vector-set! v 3 i) v) (define (func-arglist f) (vector-ref f 5)) (define (func-set-arglist f i) (vector-set! f 5 i)) (define func? func-arglist) (define (func-parity f) (vector-ref f 6)) (define (func-set-parity! f v) (vector-set! f 6 v)) (define (func-syms f) (vector-ref f 9)) (define (func-set-syms! f v) (vector-set! f 9 v)) (define (func-anti-syms f) (vector-ref f 10)) (define (func-set-anti-syms! f v) (vector-set! f 10 v)) (define (func-dists f) (vector-ref f 11)) (define (func-set-dists! f v) (vector-set! f 11 v)) (define (func-anti-dists f) (vector-ref f 12)) (define (func-set-anti-dists! f v) (vector-set! f 12 v)) (define (func-idems f) (vector-ref f 13)) (define (func-set-idems! f v) (vector-set! f 13 v)) (define (copy-vector v) (define iv (make-vector (vector-length v))) (do ((i (+ -1 (vector-length iv)) (+ -1 i))) ((negative? i) iv) (vector-set! iv i (vector-ref v i)))) ;;; The shadowed variables are kept in a list in the var:shadow slot ;;; in the var. This list has the bumped and shadowed transformations ;;; of the var for each arglist-length less than or equal ;;; (var:max-lambda-position var). ;;; For simple lambda variables (@1, @2, ...) the last shadowed ;;; variable is identical to the original except that its shadow slot ;;; is #f. (define (var:shadow v arglist-length) (if (not (vector-ref v 4)) (vector-set! v 4 (make-list (var:max-lambda-position v) #f))) (let ((shadpair (memshad arglist-length (vector-ref v 4)))) (if (not (car shadpair)) (set-car! shadpair (cond ((< arglist-length (var:min-lambda-position v)) (var:lambda-bump v (- arglist-length))) (else (make-shadow v arglist-length))))) (car shadpair))) (define (memshad arglist-length shadlist) (cond ((= 1 arglist-length) shadlist) ((null? (cdr shadlist)) shadlist) (else (memshad (+ -1 arglist-length) (cdr shadlist))))) (define (make-shadow v arglist-length) (let ((nv (copy-vector v))) (vector-set! nv 4 #f) (vector-set! nv 0 (if (symbol? (var:sexp nv)) ;got here because can't bump (string->symbol (string-append (symbol->string (var:sexp nv)) ":")) (do-sexp-symbols (lambda (s) (define st (symbol->string s)) (if (and (char=? #\@ (string-ref st 0)) (> (string-length st) 1)) (let ((i (string->number (substring st 1 (string-length st))))) (if (> i arglist-length) (var:sexp (lambda-var (- i arglist-length) 0)) (string->symbol (string-append st ":")))) s)) (var:sexp v)))) ;; Now avoid priority conflicts with minimum increment. (let* ((s (string-copy (vector-ref v 1))) (si (+ -1 (string-length s)))) (string-set! s si (integer->char (+ 1 (char->integer (string-ref s si))))) (vector-set! nv 1 s)) (var:set-depends! nv (map (lambda (var) (if (simple-lambdavar? var) (var:shadow var arglist-length) var)) (var:depends v))) (if (var:def v) (var:set-def! nv (licits:do-vars (lambda (var) (if (lambdavardep? var) (if (eq? var v) nv (var:shadow var arglist-length)) var)) (var:def v)))) (if (>= (vector-length v) 5) (func-set-arglist nv (licits:do-vars (lambda (var) (if (lambdavardep? var) (var:shadow var arglist-length) var)) (func-arglist v)))) nv)) (define (var:> v2 v1) (string>? (vector-ref v2 1) (vector-ref v1 1))) ;(define var-tab '()) ;(define var-tab-lookup (predicate->asso equal?)) ;(define var-tab-define (alist-associator equal?)) ;(define var-tab-for-each alist-for-each) (define var-tab (make-hash-table 43)) (define var-tab-lookup (predicate->hash-asso equal?)) (define var-tab-define (hash-associator equal?)) (define var-tab-for-each hash-for-each) (define (list-of-vars) (define vars '()) (var-tab-for-each (lambda (k v) (set! vars (cons v vars))) var-tab) vars) (define (sexp->new-var v) (let ((base v) (diffs 0) (lambda? (and (pair? v) (eq? 'lambda (car v))))) (do () ((not (and (pair? base) (eq? 'differential (car base))))) (set! base (cadr base)) (set! diffs (+ 2 diffs))) ;leave space for shadow priority. (let* ((s (object->string base)) (sl (string-length s)) (arglist (if (pair? v) (map sexp->math (if lambda? (caddr v) v)) '()))) (if lambda? (make-var (caddr v) (string-append (case (string-ref s 0) ((#\@) lambda-var-pri-str) (else lambda-var-pri-str)) s (string (integer->char diffs))) (and (char=? #\@ (string-ref s 0)) (not (= sl 1)) (not (char=? #\^ (string-ref s 1))) (string->number (substring s 1 sl))) (var:build-depends arglist) #f arglist #f #f #f #f #f #f ; function properties ) (make-var v (string-append (case (string-ref s 0) ((#\@) lambda-var-pri-str) (else median-pri-str)) s (string (integer->char diffs))) (and (char=? #\@ (string-ref s 0)) (not (= sl 1)) (not (char=? #\^ (string-ref s 1))) (string->number (substring s 1 sl))) (var:build-depends arglist) #f arglist ))))) (define (sexp->var sexp) (let ((vcell (var-tab-lookup sexp var-tab))) (if vcell (cdr vcell) (let ((val (sexp->new-var sexp))) (set! var-tab (var-tab-define var-tab sexp val)) val)))) (define (string->var s) (sexp->var (string->symbol s))) (define (var:build-depends args) (let ((deps '())) (for-each (lambda (e) (poly:for-each-var (lambda (v) (cond (($var? v)) ((symbol? (var:sexp v)) (set! deps (adjoin v deps))) (else (set! deps (adjoin v (union (var:depends v) deps)))))) e)) args) deps)) (define (deferop . args) (var->expl (sexp->var (deferedmath->sexp args)))) (define lambda-var-pri (+ -5 char-code-limit)) (define lambda-var-pri-str (string (integer->char lambda-var-pri))) (define median-pri-str (string (integer->char (quotient char-code-limit 2)))) (define (var->string v) (let ((sexp (var:sexp v))) (if (symbol? sexp) (symbol->string sexp) (math:error 'expected-simple-symbol sexp)))) (define (make-rad-var radicand exponent-reciprocal) (let ((e (univ:monomial -1 exponent-reciprocal $))) (set-car! (cdr e) radicand) (let ((v (defext (sexp->var (list '^ (bunch->sexp radicand #t) (list '/ 1 exponent-reciprocal))) e))) (func-set-arglist v (list _^ radicand (make-rat 1 exponent-reciprocal))) (set! radical-defs (cons (extrule v) radical-defs)) v))) (define (var:nodiffs v) (do ((base (vector-ref v 0) (cadr base))) ((not (and (pair? base) (eq? 'differential (car base)))) (if (eq? base (vector-ref v 0)) v (sexp->var base))))) (define (var:differential? v) (not (zero? (var:diff-depth v)))) (define (var:diff-depth v) (let ((s (vector-ref v 1))) (quotient (char->integer (string-ref s (+ -1 (string-length s)))) 2))) (define (var:differential v) (sexp->var (list 'differential (var:sexp v)))) (define (var:undiff v) (sexp->var (cadr (var:sexp v)))) (define (radicalvar? v) (let ((ve (var:sexp v))) (and (pair? ve) (eq? '^ (car ve))))) (define (lambdavar? v) (= lambda-var-pri (var:pri v))) (define (simple-lambdavar? v) (number? (lambda-position v))) (define (simple-shadowed-lambdavar? v) (and (number? (lambda-position v)) (not (vector-ref v 4)))) (define (lambdavarext? v) (< lambda-var-pri (var:pri v) $-pri)) (define (lambdavardep? v) (< (+ -1 lambda-var-pri) (var:pri v) $-pri)) (define ($var? v) (char=? #\: (string-ref (vector-ref v 1) 1))) (define (lambda-var i diff-depth) (if (zero? diff-depth) (let ((v (sexp->var (string->symbol (string-append "@" (number->string i)))))) (var:set-def! v i) (or (vector-ref v 4) ;so simple-shadowed-lambdavar? works (vector-set! v 4 (make-list i #f))) v) (var:differential (lambda-var i (+ -1 diff-depth))))) ;;; This sometimes is called with shadowed variables (:@4) (define lambda-position var:def) ;;; currently unused ;; (define (var:sexp-string v) ;; (var->string (var:nodiffs v))) ;; (define (var:sexp-apply proc var) ;; (if (var:differential? var) ;; (var:differential (var:sexp-apply proc (var:undiff var))) ;; (apply proc var '()))) (define (extrule e) (let ((vd (var:def e))) (and (pair? vd) vd))) (define (potent-extrule e) (let ((vd (var:def e))) (and (pair? vd) (not (eqv? 0 (cadr vd))) vd))) (define (defext var impl) (let ((deps (var:depends var))) (set! deps (if (null? deps) (remove var (var:build-depends (list impl))) (remove (car _^) deps))) (var:set-depends! var deps) (var:set-pri! var (if (null? deps) 10 ;must be a constant. (+ 1 (apply max (map var:pri deps))))) (var:set-def! var (vsubst var $ impl)) var)) ;;; IMPL is a data type consisting of a poly with major variable ;;; $. The value of the IMPL is negative of the poly solved for $. ;;; Using this representation, if poly is square-free and has no ;;; content (gcd (coefficients) = 1), we can express any ;;; algebraic function or number uniquely, even those with no standard ;;; representation (order > 4 roots). (define (expr? p) (or (number? p) (and (pair? p) (poly:var? (car p))))) (define (impl? p) (and (pair? p) (poly:var? (car p)) ($? (car p)))) (define (rat:number? p) (or (number? p) (and (impl? p) (= 3 (length p)) (number? (cadr p)) (number? (caddr p))))) (define (expr:0? p) (or (eqv? 0 p) (and (impl? p) (eqv? 0 (rat:num p))))) (define (expl? p) (or (number? p) (and (pair? p) (poly:var? (car p)) (not ($? (car p)))))) ;;; Rational impl? (define (rat? p) (and (impl? p) (= 3 (length p)))) (define (make-rat num denom) (list $ num (poly:negate denom))) (define (rat:num p) (poly:negate (cadr p))) (define (rat:denom p) (caddr p)) (define (rat:unit-denom? p) (unit? (caddr p))) (define (bunch? p) (or (null? p) (and (pair? p) (not (poly:var? (car p))) (not (eqv? $= (car p)))))) (define $= "=") (define (eqn? p) (and (pair? p) (eqv? $= (car p)))) (define (eqns? p) (if (bunch? p) (some eqns? p) (eqn? p))) (define (licit? p) (or (number? p) (and (pair? p) (or (poly:var? (car p)) (eqv? $= (car p)))))) (define eqn->poly cdr) (define (poly->eqn p) (cons $= p)) (define (polys->eqns p) (if (bunch? p) (map polys->eqns p) (poly->eqn p))) (define (var->expl v) (list v 0 1)) (define (expl->impl p) (make-rat p 1)) (define (var->impl v) (make-rat (var->expl v) 1)) ;;; Two paradigms for doing algebra on equations and expressions: ;;; Polynomials as expressions and Polynomials as equations. ;;; Polynomials are used as expressions in GCD. ;;; Polynomials are used as equations in ELIMINATE. ;;; licit-> polxpr poleqn ;;; eqn expl expl ;;; expl expl impl ;;; impl expl(?) impl ;;; After the operation is done, we need to convert back. For ;;; Polynomials as expressions, the result is already expl. For ;;; polynomials as equations: ;;; poleqn->licit ;;; expl eqn ;;; impl expr (define (licit->poleqn p) (cond ((symbol? p) (var->impl (sexp->var p))) ((eqn? p) (eqn->poly p)) ((impl? p) p) ((expl? p) (expl->impl p)) (else (math:error 'cannot-be-coerced-to-poly-eqn:- p)))) (define (licits->poleqns p) (if (bunch? p) (map licits->poleqns p) (licit->poleqn p))) (define (poleqn->licit p) (cond ((impl? p) (expr:norm p)) ((expl? p) (poly->eqn p)) (else (math:error 'not-a-polynomial-equation p)))) (define (poleqns->licits p) (if (bunch? p) (map poleqns->licits p) (poleqn->licit p))) (define (licit->polxpr p) (cond ((symbol? p) (var->expl (sexp->var p))) ((eqn? p) (eqn->poly p)) ((expl? p) p) ((and (impl? p) (poly:/? (rat:num p) (rat:denom p)))) (else (math:error 'cannot-be-coerced-to-expl:- p)))) (define (licit->impl p) (cond ((symbol? p) (var->impl (sexp->var p))) ((eqn? p) (math:error 'value-expected-equation-found:- p)) ((impl? p) p) ((expl? p) (expl->impl p)) (else (math:error 'cannot-be-coerced-to-implicit:- p)))) (define (licits->impls p) (if (bunch? p) (map licits->impls p) (licit->impl p))) (define (expr p) (cond ((symbol? p) (var->expl (sexp->var p))) ((expr? p) p) (else (math:error 'cannot-be-coerced-to-expr:- p)))) (define (exprs p) (if (bunch? p) (map exprs p) (expr p))) (define (expl:var? p) (and (pair? p) (expl? p) (equal? (cdr p) '(0 1)))) (define (expl->var p) (cond ((symbol? p) (sexp->var p)) ; ((poly:var? p) p) ((expl:var? p) (car p)) (else (math:error 'not-a-simple-variable:- p)))) (define (variables p) (cond ((symbol? p) (list (sexp->var p))) ; ((poly:var? p) (list p)) ((expl:var? p) (list (car p))) ((list? p) (map expl->var p)) (else (math:error 'not-a-simple-variable:- p)))) (define (plicit->integer p) (cond ((integer? p) p) ((not (rat:number? p)) (math:error 'not-an-integer- p)) ((rat:unit-denom? p) (* (rat:denom p) (rat:num p) -1)) (else (math:error 'not-an-integer- p)))) (define (unit? x) (member x '(1 -1))) (define (expr:norm p) (if (and (rat? p) (rat:unit-denom? p)) (poly:* (rat:num p) (rat:denom p)) p)) (define (expr:norm-or-unitcan p) (if (and (rat? p) (rat:unit-denom? p)) (poly:* (rat:num p) (rat:denom p)) (unitcan p))) ;;; These two functions return type expl (define (num p) (cond ((impl? p) (rat:num p)) ((expl? p) p) (else (math:error 'cannot-extract-numerator- p)))) (define (denom p) (cond ((rat? p) (rat:denom p)) ((expl? p) 1) (else (math:error 'cannot-extract-denominator- p)))) (define (sexp? e) (cond ((number? e) #t) ((symbol? e) #t) ((pair? e) (symbol? (car e))) ((vector? e) #t) (else #f))) ;;; A useful companion for ZERO? (define (one? n) (eqv? 1 n)) jacal-1b9/README0000644001705200017500000000473210751434546011216 0ustar tbtbThis directory contains the distribution of jacal-1b9. Jacal is a symbolic mathematics system written in the programming language Scheme. http://swiss.csail.mit.edu/~jaffer/JACAL.html File: jacal.info, Node: Installation, Next: Running Jacal, Prev: Authors and Bibliography, Up: Overview 1.2 Installation ================ The JACAL program is written in the Algorithmic Language "Scheme". So you must obtain and install a Scheme implementation in order to run it. The installation procedures given here use the SCM Scheme implementation. If your system has a Scheme (or Guile) implementation installed, then the `scm' steps are unnecessary. JACAL also requires the SLIB Portable Scheme library which is available from `http://swiss.csail.mit.edu/~jaffer/SLIB'. -- System: i386 GNU/Linux with Redhat Package Manager (rpm) wget http://swiss.csail.mit.edu/ftpdir/scm/scm-5e5-1.i386.rpm wget http://swiss.csail.mit.edu/ftpdir/scm/slib-3b1-1.noarch.rpm wget http://swiss.csail.mit.edu/ftpdir/scm/jacal-1b9-1.noarch.rpm rpm -U scm-5e5-1.i386.rpm slib-3b1-1.noarch.rpm jacal-1b9-1.noarch.rpm rm scm-5e5-1.i386.rpm slib-3b1-1.noarch.rpm jacal-1b9-1.noarch.rpm The command `jacal' will start an interactive session. -- System: Unix -- System: GNU/Linux wget http://swiss.csail.mit.edu/ftpdir/scm/scm-5e5.zip wget http://swiss.csail.mit.edu/ftpdir/scm/slib-3b1.zip wget http://swiss.csail.mit.edu/ftpdir/scm/jacal-1b9.zip unzip -ao scm-5e5.zip unzip -ao slib-3b1.zip unzip -ao jacal-1b9.zip (cd slib; make install) (cd scm; make scm; make install) (cd jacal; make install) rm scm-5e5.zip slib-3b1.zip jacal-1b9.zip The command `jacal' will start an interactive session using ELK, Gambit, Guile, Larceny, MIT-Scheme, MzScheme, Scheme48, SCM, or SISC. Type `jacal --help' for instructions. -- System: Apple `http://www.io.com/~cobblers/scm/' has downloads and utilities for installing SCM and SLIB on Macintosh computers. -- System: x86 Microsoft Download and run `http://swiss.csail.mit.edu/ftpdir/scm/SLIB-3b1-1.exe', `http://swiss.csail.mit.edu/ftpdir/scm/SCM-5e5-1.exe', and `http://swiss.csail.mit.edu/ftpdir/scm/JACAL-1b9-1.exe'. Compiling Jacal --------------- For Scheme implementations with compilers, it is worthwhile to compile SLIB files, and the JACAL files `types.scm' and `poly.scm'. jacal-1b9/demo0000644001705200017500000000264406334764212011203 0ustar tbtbset echogrammar standard; /* Running demo, a test batch file. Entering a simple formula: */a-b; /* generating a simple radical */ rad:%^(1/2); /* Now that the simple radical has been defined, it will split any radicals of which it is a factor */ rad2:(a^2-b^2)^(1/2); /* The total differential is: */ %'; /* The derivative with respect to b is: */ diff(rad2,b); /* lets try generating a 3rd order field extension */ foo3:{a|a^3+a*x+y}; /* does the original formula extinguish the extension? */ verify(%^3+%*x+y,0); /* now, lets see what the derivative in terms of the field extension is */ foo3'; /* The derivative with respect to x is: */ diff(foo3,x); /* Non-commutative partials example from Tom M. Apostol, Mathematical Analysis, Addison-Wesley Publishing Co., 1957 */ Af(x,y) : x*y*(x^2-y^2)/(x^2+y^2); Df1 : partial(Af,1); Df2 : partial(Af,2); verify(-y,Df1(0,y)); verify(x,Df2(x,0)); verify(partial(Df1(0,@2),@2),-1); verify(partial(Df2(@1,0),@1),1); verify([[1,0],[-2,1]],[[1,0],[-1,1]]^^2); mp:[2*x-(a-1)*y=5*b,a*x+b*y+c=0]; coefmatrix(mp,[x,y]); d2:augcoefmatrix(mp,[x,y]); /* echelon(d2); triangularize(d2);*/ rank(d2); amatrix:[[3,1],[2,4]]; charpoly(amatrix,lam); /* variables can be eliminated from expressions and equations, even involving radicals and functions. */ eliminate([a^2/c+a^(1/2)+f(a,b,c),a=b/c],a); verify(%,(b^2 + f(b/c, b, c) * c^3 + c^2 * b^(1/2) * c^(1/2))/c^3); /* done */ set echogrammar null; jacal-1b9/Makefile0000644001705200017500000002437310751434543011776 0ustar tbtb# Makefile for JACAL: Symbolic Mathematics System. # Copyright (C) 1990 - 2005 Aubrey Jaffer. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or (at # your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. SHELL = /bin/sh intro: @echo @echo "Welcome to JACAL. To install, unpack this directory" @echo "where it will eventually reside. You will also need" @echo "to install SLIB and have a Scheme Implementation" @echo "(both of which are available from the same vendor or" @echo "site as JACAL)." @echo @echo "Read \"README\" and \"jacal.info\" (or \"jacal.texi\")" @echo "to learn how to run and use JACAL." @echo VERSION = 1b9 RELEASE = 1 rpm_prefix=$(HOME)/rpmbuild/ prefix = /usr/local/ exec_prefix = $(prefix) # directory where `make install' will put executable. bindir = $(exec_prefix)bin/ jacallibdir = $(exec_prefix)lib/jacal/ # directory where `make install' will put manual page. man1dir = $(prefix)man/man1/ infodir = $(prefix)info/ S48IMAGE = $(jacallibdir)scheme48.image PREVDOCS = prevdocs/ jacal-$(VERSION).info: version.txi jacal.texi -mv jacal.info jacaltmp.info makeinfo jacal.texi --no-split -o jacal.info mv jacal.info jacal-$(VERSION).info -mv jacaltmp.info jacal.info jacal.info: jacal-$(VERSION).info if [ -f $(PREVDOCS)jacal.info ];\ then infobar $(PREVDOCS)jacal.info jacal-$(VERSION).info jacal.info;\ else cp jacal-$(VERSION).info jacal.info;fi info: installinfo installinfo: $(DESTDIR)$(infodir)jacal.info $(DESTDIR)$(infodir)jacal.info: jacal.info mkdir -p $(DESTDIR)$(infodir) cp -p jacal.info $(DESTDIR)$(infodir)jacal.info -install-info $(DESTDIR)$(infodir)jacal.info $(DESTDIR)$(infodir)dir -rm $(DESTDIR)$(infodir)jacal.info.gz infoz: installinfoz installinfoz: $(DESTDIR)$(infodir)jacal.info.gz $(DESTDIR)$(infodir)jacal.info.gz: $(DESTDIR)$(infodir)jacal.info gzip -f $(DESTDIR)$(infodir)jacal.info pinstall: jacal.1 mkdir -p $(DESTDIR)$(man1dir) -cp jacal.1 $(DESTDIR)$(man1dir) mkdir -p $(DESTDIR)$(jacallibdir) -cp $(sfiles) $(cfiles) $(gfiles) jacalcat Makefile COPYING HELP $(DESTDIR)$(jacallibdir) install: pinstall echo ";;(use-modules (ice-9 slib))" > $(DESTDIR)$(jacallibdir)go.scm echo "(slib:load \"$(jacallibdir)math\")" > $(DESTDIR)$(jacallibdir)go.scm echo "(math)" >> $(DESTDIR)$(jacallibdir)go.scm mkdir -p $(DESTDIR)$(bindir) echo '#! /bin/sh' > $(DESTDIR)$(bindir)jacal grep -h ^SCHEME_LIBRARY_PATH= `which slib` >> $(DESTDIR)$(bindir)jacal echo export SCHEME_LIBRARY_PATH >> $(DESTDIR)$(bindir)jacal echo JACALDIR=$(DESTDIR)$(jacallibdir) >> $(DESTDIR)$(bindir)jacal echo VERSION=$(VERSION) >> $(DESTDIR)$(bindir)jacal cat jacal.sh >> $(DESTDIR)$(bindir)jacal chmod +x $(DESTDIR)$(bindir)jacal uninstall: -rm $(DESTDIR)$(bindir)jacal -rm $(DESTDIR)$(man1dir)jacal.1 htmldir=../public_html/ dvi: jacal.dvi jacal.dvi: version.txi jacal.texi texi2dvi -b -c jacal.texi xdvi: jacal.dvi xdvi jacal.dvi pdfs: $(htmldir)jacal.pdf $(htmldir)ratint.pdf pdf: $(htmldir)jacal.pdf $(htmldir)jacal.pdf: version.txi jacal.texi texi2pdf -b -c jacal.texi mv jacal.pdf $(htmldir) xpdf: $(htmldir)jacal.pdf xpdf $(htmldir)jacal.pdf TEXI2HTML = /usr/local/bin/texi2html -split -verbose jacal_toc.html: version.txi jacal.texi ${TEXI2HTML} jacal.texi html: $(htmldir)jacal_toc.html $(htmldir)jacal_toc.html: jacal_toc.html Makefile -rm -f jacal_stoc.html if [ -f $(PREVDOCS)jacal_toc.html ]; \ then hitch $(PREVDOCS)jacal_\*.html jacal_\*.html $(htmldir); \ else cp jacal_*.html $(htmldir);fi DOCdir=DOC/ dvis: jacal.dvi $(DOCdir)ratint.dvi $(DOCdir)ratint.aux: $(DOCdir)ratint.tex $(DOCdir)eqalign.sty cd $(DOCdir); latex ratint.tex $(DOCdir)ratint.dvi: $(DOCdir)ratint.tex $(DOCdir)eqalign.sty \ $(DOCdir)ratint.aux cd $(DOCdir); latex ratint.tex $(htmldir)ratint.pdf: $(DOCdir)ratint.tex $(DOCdir)eqalign.sty # $(DOCdir)ratint.aux cd $(DOCdir); pdflatex ratint.tex mv -f $(DOCdir)ratint.pdf $(htmldir) jacal.doc: jacal.1 nroff -man $< | ul -tunknown >$@ jacal.html: jacal.texi makeinfo --html --no-split --no-warn --force jacal.texi ## to build a windows installer ## make sure makeinfo and NSIS are available on the commandline w32install: jacal.html makensis jacal.nsi #### Stuff for maintaining JACAL below #### ver = $(VERSION) version.txi: Makefile echo @set JACALVERSION $(ver) > version.txi echo @set JACALDATE `date +"%B %Y"` >> version.txi cfiles = math.scm modeinit.scm debug.scm view.scm toploads.scm sfiles = types.scm func.scm poly.scm elim.scm \ vect.scm ext.scm norm.scm sqfree.scm hist.scm sexp.scm \ grammar.scm unparse.scm builtin.scm info.scm \ tensor.scm combin.scm ff.scm factors.scm uv-hensel.scm hensel.scm gfiles = English.scm mfiles = ANNOUNCE COPYING HELP Makefile jacalcat jacal.texi version.txi \ fdl.texi jacal.1 \ demo test.math rw.math jacal.spec jacal.sh elk.scm jacal.nsi allfiles = README ChangeLog $(mfiles) $(sfiles) $(cfiles) $(gfiles) \ jacal.info jacal.doc #dfiles Document internals of Jacal. dfiles = algdenom grammar history lambda ratint.tex eqalign.sty # Common Lisp not currently supported. lfiles = scl.lisp math.lisp compilem.lisp tagfiles = $(sfiles) $(cfiles) $(gfiles) $(mfiles) jacal48: (echo ",batch on"; \ echo "(require 'fluid-let)"; \ echo "(slib:load \"$(jacallibdir)math\")"; \ echo "(require 'hensel)"; \ echo ",collect"; \ echo ",batch off"; \ echo ",dump $(S48IMAGE) \"(jacal $(VERSION))\""; \ echo ",exit") | slib48 -h 5100000 unjacal48: rm -f $(S48IMAGE) lint: $(cfiles) $(sfiles) $(gfiles) sclint $(cfiles) $(sfiles) $(gfiles) docs: $(DESTDIR)$(infodir)jacal.info.gz $(htmldir)jacal_toc.html \ $(DOCdir)ratint.dvi $(htmldir)jacal.pdf jacal.doc xdvi jacal.dvi makedev = make -f $(HOME)/makefile.dev CHPAT=$(HOME)/bin/chpat RSYNC=rsync -bav UPLOADEE=swissnet_upload dest = $(HOME)/dist/ DOSCM = /c/Voluntocracy/dist/ temp/jacal: $(allfiles) $(htmldir)ratint.pdf -rm -rf temp mkdir -p temp/jacal ln $(allfiles) temp/jacal mkdir -p temp/jacal/DOC ln $(htmldir)ratint.pdf temp/jacal/DOC cd DOC; ln $(dfiles) ../temp/jacal/DOC infotemp/jacal: jacal.info -rm -rf infotemp mkdir -p infotemp/jacal ln jacal.info jacal.info-* infotemp/jacal #For change-barred HTML. prevdocs: $(PREVDOCS)jacal_toc.html $(PREVDOCS)jacal.info $(PREVDOCS)jacal_toc.html: $(PREVDOCS)jacal.info: Makefile cd $(PREVDOCS); unzip -a $(dest)jacal*.zip rm $(PREVDOCS)jacal/jacal*.info cd $(PREVDOCS)jacal; make jacal.info; make jacal_toc.html cd $(PREVDOCS); mv -f jacal/jacal*.info ./ cd $(PREVDOCS); mv -f jacal/*.html ./ rm -rf $(PREVDOCS)jacal -rm -f jacal-$(VERSION).info distinfo: $(dest)jacal.info.zip $(dest)jacal.info.zip: infotemp/jacal $(makedev) TEMP=infotemp/ DEST=$(dest) PROD=jacal ver=.info zip rm -rf infotemp README: jacal-$(VERSION).info Makefile echo "This directory contains the distribution of jacal-$(VERSION). Jacal is a" > README echo "symbolic mathematics system written in the programming language Scheme." >> README echo "" >> README echo " http://swiss.csail.mit.edu/~jaffer/JACAL.html" >> README echo "" >> README info -f jacal-$(VERSION).info -n 'Installation' -o - >> README release: dist README pdfs # rpm cvs tag -F jacal-$(VERSION) cp ANNOUNCE $(htmldir)JACAL_ANNOUNCE.txt $(RSYNC) $(htmldir)JACAL.html $(htmldir)JACAL_ANNOUNCE.txt $(UPLOADEE):public_html/ $(RSYNC) $(dest)README $(dest)jacal-$(VERSION).zip \ $(dest)jacal-$(VERSION)-$(RELEASE).noarch.rpm \ $(htmldir)ratint.pdf \ $(dest)jacal-$(VERSION)-$(RELEASE).src.rpm $(UPLOADEE):dist/ # upload $(dest)README $(dest)jacal-$(VERSION).zip ftp.gnu.org:gnu/jacal/ upzip: $(HOME)/pub/jacal.zip $(RSYNC) $(HOME)/pub/jacal.zip $(UPLOADEE):pub/ dist: $(dest)jacal-$(VERSION).zip $(dest)jacal-$(VERSION).zip: temp/jacal $(makedev) DEST=$(dest) PROD=jacal ver=-$(VERSION) zip rpm: pubzip # $(dest)jacal-$(VERSION)-$(RELEASE).noarch.rpm: $(dest)jacal-$(VERSION).zip cp -f $(HOME)/pub/jacal.zip $(rpm_prefix)SOURCES/jacal-$(VERSION).zip rpmbuild -ba --clean jacal.spec rm $(rpm_prefix)SOURCES/jacal-$(VERSION).zip mv $(rpm_prefix)RPMS/noarch/jacal-$(VERSION)-$(RELEASE).noarch.rpm \ $(rpm_prefix)SRPMS/jacal-$(VERSION)-$(RELEASE).src.rpm $(dest) shar: jacal.shar jacal.shar: temp/jacal $(makedev) PROD=jacal shar dclshar: jacal.com com: jacal.com jacal.com: temp/jacal $(makedev) PROD=jacal com zip: jacal.zip jacal.zip: temp/jacal $(makedev) PROD=jacal zip doszip: $(DOSCM)jacal-$(VERSION).zip $(DOSCM)jacal-$(VERSION).zip: temp/jacal jacal.html equal.ico $(makedev) DEST=$(DOSCM) PROD=jacal ver=-$(VERSION) zip -cd ..; zip -9ur $(DOSCM)jacal-$(VERSION).zip \ jacal/jacal.html jacal/equal.ico zip -d $(DOSCM)jacal-$(VERSION).zip jacal/jacal.info pubzip: temp/jacal $(makedev) DEST=$(HOME)/pub/ PROD=jacal zip diffs: pubdiffs pubdiffs: temp/jacal $(makedev) DEST=$(HOME)/pub/ PROD=jacal pubdiffs distdiffs: temp/jacal $(makedev) DEST=$(dest) PROD=jacal ver=$(ver) distdiffs CITERS = ANNOUNCE ../scm/ANNOUNCE $(htmldir)README.html ../dist/README \ $(DOSCM)unzipall.bat $(DOSCM)buildall CITES = toploads.scm Makefile jacal.spec jacal.texi jacal.nsi \ $(htmldir)JACAL.html updates: $(CHPAT) jacal-$(VERSION) jacal-$(ver) $(CITERS) $(CHPAT) $(VERSION) $(ver) $(CITES) make README new: updates echo `date -I` \ Aubrey Jaffer \ \<`whoami`@`hostname`\>> change echo>> change echo \ \* toploads.scm \(*jacal-version*\): Bumped from $(VERSION) to $(ver).>>change echo>> change cat ChangeLog >> change mv -f change ChangeLog cvs commit -m '(*jacal-version*): Bumped from $(VERSION) to $(ver).' cvs tag -F jacal-$(ver) tags: $(tagfiles) etags $(tagfiles) clean: -rm -f *~ *.bak *.orig *.rej core a.out *.o \#* -rm -rf *temp distclean: realclean realclean: -rm -f *~ *.bak *.orig *.rej TAGS core a.out *.o \#* -rm -f jacal.info* -rm -rf *temp jacal.html JACAL-*.exe realempty: temp/jacal -rm -f $(allfiles) cd DOC; rm -f $(dfiles) ratint.pdf jacal-1b9/factors.scm0000644001705200017500000001061310667300650012470 0ustar tbtb;; "factors.scm" Polynomial factors. -*-scheme-*- ;; Copyright 1994, 1995 Mike Thomas ;; Copyright 1995, 1997, 1998, 1999, 2001, 2002 Aubrey Jaffer ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or (at ;; your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. (require 'finite-fields) (require 'fluid-let) (require 'sort) (require 'common-list-functions) ;;; NUMCONT is the integer numeric content. (define (prepend-integer-factor numcont factors) (cond ((one? numcont) factors) (*sort-int-factors* (append (int:factors numcont) factors)) (else (cons (list (list numcont) 1) factors)))) (define (negate-factors-exps fact-exps) (reverse (map (lambda (fact-exp) (list (car fact-exp) (- (cadr fact-exp)))) fact-exps))) ;;; Special Var Power Factors (of polynomial) (define (svpf poly) (let loop ((p (cdr poly)) (n 0)) (if (eqv? 0 (car p)) (if (null? (cdr p)) (+ 1 n) (loop (cdr p) (+ 1 n))) n))) ;;;==================== Sort polynomial factors ==================== (define (poly:factor< x y) (define (lnumber? x) (cond ((number? x) #t) ((list? x) (and (= 1 (length x)) (number? (car x)))) (else #f))) (cond ((and (number? x) (number? y)) (< x y)) ((and (lnumber? x) (lnumber? y)) (< (car x) (car y))) ((lnumber? x) #t) ((lnumber? y) #f) ((null? x) #t) ((null? y) #f) ((and (symbol? x) (symbol? y)) (stringstring x) (symbol->string y))) ((vector? (car x)) (cond ((string (length x) (length y)) #f) ((< (length x) (length y)) #t) ((and (list? x) (list? y)) (cond ((poly:factor< (univ:lc x) (univ:lc y)) #t) ((poly:factor< (univ:lc y) (univ:lc x)) #f) (else (poly:factor< (butlast x 1) (butlast y 1))))) ((list? x) (poly:factor< (but-last x 1) y)) ((list? y) (poly:factor< x (but-last y 1))) (else (slib:error "poly:factor<: unknown type" x y)))) (define (poly:sort-factors fs) (sort! fs poly:factor<)) (define (poly:sort-merge-factors fs) (define factors-list (poly:sort-factors fs)) (define (doit facts exp factors-list) (cond ((null? factors-list) (list (list (poly:sort-factors facts) exp))) ((equal? exp (cadar factors-list)) (doit (append facts (caar factors-list)) exp (cdr factors-list))) (else (cons (list (poly:sort-factors facts) exp) (doit (caar factors-list) (cadar factors-list) (cdr factors-list)))))) (doit (caar factors-list) (cadar factors-list) (cdr factors-list))) ;;; ================================================================ ;;; FACTORS-LIST is a list of lists of a list of factors and exponent. ;;; FACT-EXPS is a list of lists of factor and exponent. (define (factors->sexp factors-list) (apply sexp:* (map (lambda (fact-exp) (sexp:^ (if (number? (car fact-exp)) (int:factor (car fact-exp)) (cano->sexp (car fact-exp) #f)) (cadr fact-exp))) (poly:sort-factors (factors-list->fact-exps factors-list))))) (define *sort-int-factors* #f) ;;; Factorise over the Rationals (Q) ;;; return an sexp product of sorted factors of the polynomial POLY ;;; over the integers (Z) (define (rat:factor->sexp poly) (fluid-let ((*sort-int-factors* #f)) (cond ((rat? poly) (let ((nu (num poly)) (de (denom poly))) (sexp:over (if (number? nu) (int:factor nu) (factors->sexp (poly:factorz nu))) (if (number? de) (int:factor de) (factors->sexp (poly:factorz de)))))) (else (factors->sexp (poly:factorz poly)))))) (define (rat:factors poly) (fluid-let ((*sort-int-factors* #t)) (poly:sort-merge-factors (cond ((rat? poly) (append (poly:factorz (num poly)) (negate-factors-exps (poly:factorz (denom poly))))) (else (poly:factorz poly)))))) jacal-1b9/vect.scm0000644001705200017500000001671310667300650011777 0ustar tbtb;; JACAL: Symbolic Mathematics System. -*-scheme-*- ;; Copyright 1989, 1990, 1991, 1992, 1993 Aubrey Jaffer. ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or (at ;; your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. (require 'rev4-optional-procedures) (require 'common-list-functions) (define (bunch:norm x) (if (null? (cdr x)) (car x) x)) (define (copymatrix m) (if (matrix? m) (map copy-list m) (math:error 'not-a-matrix:- m))) (define (row? a) (and (bunch? a) (notevery bunch? a))) (define (matrix? a) (and (bunch? a) (not (null? a)) (bunch? (car a)) (let ((len (length (car a)))) (and (every (lambda (r) (and (bunch? r) (= (length r) len))) (cdr a)) len)))) (define (matrix . lst) (if (matrix? lst) lst (matrix lst))) (define (butnth n lst) (cond ((null? lst) (math:error 'coordinate-out-of-range:- n " " lst)) ((zero? n) (cdr lst)) (else (cons (car lst) (butnth (+ -1 n) (cdr lst)))))) (define (mtrx:minor m i j) (butnth (+ -1 i) (map (lambda (x) (butnth (+ -1 j) x)) m))) (define (transpose m) (cond ((matrix? m) (bunch:norm (apply map list m))) ((bunch? m) (map list m)) (else m))) (define (mtrx:square? m) (if (not (matrix? m)) #f (let ((rows (length m))) (every (lambda (r) (= (length r) rows)) m)))) (define (mtrx:genmatrix fun i2 j2 i1 j1) (do ((i i2 (+ -1 i)) (mat '() (cons (do ((j j2 (+ -1 j)) (row '() (cons (app* fun i j) row))) ((< j j1) row)) mat))) ((< i i1) (bunch:norm mat)))) ;;;Create a matrix of indeterminates (define (nmatrix var . rst) (apply genmatrix (lambda subs (apply rapply var subs)) rst)) (define (dotproduct a b) (let ((cols (matrix? a)) (colbs (matrix? b))) (cond ((or (and cols (bunch? b)) (and colbs (bunch? a))) (if (not (and (eqv? cols colbs) (eqv? (length a) (length b)))) (math:error 'dotproduct-of-unequal-size-matrices:- a " " b)) (reduce (lambda (x y) (app* $1+$2 x y)) (reduce (lambda (x y) (app* $1+$2 x y)) (map (lambda (x y) (app* $1*$2 x y)) a b)))) ((and (row? a) (row? b)) (reduce (lambda (x y) (app* $1+$2 x y)) (map (lambda (x y) (app* $1*$2 x y)) a b))) ((bunch? a) (map (lambda (x) (app* $1*$2 x b)) a)) ((bunch? b) (map (lambda (x) (app* $1*$2 a x)) b)) (else (app* $1*$2 a b))))) (define (ncmult a b) (let ((cols (matrix? a)) (colbs (matrix? b))) (cond ((or (and cols (bunch? b)) (and colbs (bunch? a))) (if (not colbs) (set! b (list b))) (if (not (= (or cols (length a)) (length b))) (math:error 'matrix-product-of-unequal-size-matrices:- a " " b)) (or cols (set! a (matrix a))) (bunch:norm (map (lambda (arow) (apply map (lambda bcol (dotproduct bcol arow)) b)) a))) (else (deferop _ncmult a b))))) (define (mtrx:expt a pow) (cond ((zero? pow) 1) ((one? pow) a) ((negative? pow) (mtrx:expt (mtrx:inverse a) (- pow))) (else (ipow-by-squaring a (+ -1 pow) a ncmult)))) (define (crossproduct a b) (if (and (row? a) (row? b)) (cond ((not (= (length a) (length b))) (math:error 'crossproduct 'unequal-length-vectors a b)) ((= 2 (length a)) (app* $1-$2 (app* $1*$2 (car a) (cadr b)) (app* $1*$2 (car b) (cadr a)))) ((= 3 (length a)) (list (app* $1-$2 (app* $1*$2 (cadr a) (caddr b)) (app* $1*$2 (cadr b) (caddr a))) (app* $1-$2 (app* $1*$2 (caddr a) (car b)) (app* $1*$2 (caddr b) (car a))) (app* $1-$2 (app* $1*$2 (car a) (cadr b)) (app* $1*$2 (car b) (cadr a))))) (else (math:error 'crossproduct 'funny-length-vectors a b))) (dotproduct a b))) (define (mtrx:scalarmatrix n x) (do ((i 1 (+ 1 i)) (rows (list (nconc (make-list (+ -1 n) 0) (list x))) (cons (append (cdar rows) (list 0)) rows))) ((>= i n) rows))) (define (mtrx:diagmatrix diag) (set! diag (reverse diag)) (do ((i (+ -1 (length diag)) (+ -1 i)) (j 0 (+ 1 j)) (diag diag (cdr diag)) (rows '() (cons (nconc (make-list i 0) (list (car diag)) (make-list j 0)) rows))) ((null? diag) rows))) (define (determinant m) (if (not (mtrx:square? m)) (math:error 'determinant-of-non-square-matrix m)) (letrec ((sign 1) (ds (lambda (m) (cond ((null? m) '()) ((not (expr:0? (caar m))) (set! sign (if (negative? sign) (app* _-$1 (caar m)) (caar m))) (map (lambda (ro) (cond ((expr:0? (car ro)) (cdr ro)) (else (app* $1-$2*$3 (cdr ro) (cdar m) (app* $1/$2 (car ro) (caar m)))))) (cdr m))) ((null? (cdr m)) #f) (else (set! sign (- sign)) (let ((submat (ds (cdr m)))) (if (not submat) #f (cons (cdar m) submat)))))))) (cond ((null? (cdr m)) (caar m)) ((null? (cddr m)) (crossproduct (car m) (cadr m))) (else (let ((subdet (ds m))) (if (not subdet) 0 (app* $1*$2 sign (determinant subdet)))))))) (define (charpoly m var) (determinant (app* $1-$2 m (mtrx:scalarmatrix (length m) var)))) (define (cofactor m i j) (let ((det (determinant (mtrx:minor m i j)))) (if (odd? (+ i j)) (app* _-$1 det) det))) (define (mtrx:inverse ra) (app* $1/$2 (mtrx:genmatrix (lambda (i j) (cofactor ra j i)) (length ra) (length ra) 1 1) (determinant ra))) (define (coefmatrix eqns vars) (map (lambda (eq) (map (lambda (var) (let ((c (coeff eq var 1))) (set! eq (coeff eq var 0)) c)) vars)) eqns)) (define (augcoefmatrix eqns vars) (map (lambda (eq) (nconc (map (lambda (var) (let ((value (coeff eq var 1))) (set! eq (coeff eq var 0)) value)) vars) (list eq))) eqns)) ;;; This algorithm taken from: ;;; Knuth, D. E., ;;; The Art Of Computer Programming, Vol. 2: Seminumerical Algorithms, ;;; Addison Wesley, Reading, MA 1969. ;;; pp 425-426 (define (rank m) (let* ((cols (matrix? m)) (n (length m)) (c (make-list n -1)) (r 0)) (cond ((null? cols) (set! m (list m)) (set! n 1)) ((> cols n) (set! m (copymatrix m))) (else (set! m (transpose m)) (set! n cols))) (do ((k 0 (+ 1 k))) ((>= k n) (- n r)) (let* ((l #f) (j (do ((j 0 (+ 1 j))) ((or l (>= j n)) l) (if (and (< (list-ref c j) 0) (not (poly:0? (list-ref (list-ref m k) j)))) (set! l j)))) (rowj (and j (list-ref m j)))) (cond (j (set! rowj (app* _-$1/$2 rowj (list-ref rowj k))) (set-car! (list-tail m j) rowj) (do ((restrows m (cdr restrows))) ((null? restrows)) (if (not (eq? (car restrows) rowj)) (set-car! restrows (app* $1*$2+$3 rowj (list-ref (car restrows) k) (car restrows))))) (set-car! (list-tail c j) k)) (else (set! r (+ 1 r)))))))) ;;; Copyright 1989, 1990, 1991, 1992, 1993 Aubrey Jaffer. jacal-1b9/func.scm0000644001705200017500000000565110667300650011770 0ustar tbtb;; JACAL: Symbolic Mathematics System. -*-scheme-*- ;; Copyright 1990, 1992, 1993, 1997 Aubrey Jaffer. ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or (at ;; your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;;; This section deals with functions which are non-algebraic or ;;; unspecified. These functions are canonicalized with regard to ;;; symmetric, antisymmetric, even, odd, distributive and anti-distributive ;;; properties on a per argument basis. This does not canonicalize ;;; functions because there are many other functional properties. What is ;;; possible in this area? What other properties are important to include? ;;; f(x,y,z) = f(y,x,z) f is symmetric in arguments 1 and 2. ;;; f(x,y,z) = -f(y,x,z) f is anti-symmetric in arguments 1 and 2. ;;; f(x,y) = f(-x,y) f is even in argument 1. ;;; f(x,y) = -f(-x,y) f is odd in argument 1. ;;; f(g(x,y),z) = g(f(x,z),y) f and g distribute over argument 1. ;;; f(g(x,y),z) = -g(f(x,z),y) f and g anti-distribute over argument 1. ;;; f(f(x,z),z) = f(x,z) f idempotent over argument 1. ;;; When one of the functions in a distributive pair is '+' (and '-') the ;;; system knows that constant factors can be pulled out. When one of the ;;; functions in a distributive pair is '*' the system knows that it applies ;;; to '/' and exponentiated terms also. ;;; Normalization procedure: ;;; First, apply distributive rules to pairs (to sets?) of distributive ;;; functions in such a was as to push the lower priority function to the ;;; bottom (smallest terms). '+' followed by '*' and exponentiation are the ;;; highest priority functions. ;;; Colapse any idempotent cases. ;;; Starting with the innermost terms conditionally negate arguments in ;;; order to make the highest order term of the argument positive (negating ;;; the function if odd). ;;; Finally, sort sets of symmetric arguments by highest order term ranking. (require 'sort) (require 'common-list-functions) (defbltn 'symmetrical (lambda (func . symmetry-lists) (let* ((f (expl->var func)) (osls (and f (or (func-syms f) '())))) (for-each (lambda (sl) (cond ((or (not (every number? sl)) (has-duplicates? sl)) (bltn:error 'symmetrical sl)) (else (set sl (sort sl <)) (cond ((member sl osls) (bltn:warn 'symmetrical 'already-knew sl)) (func-set-syms! f v))) )))))) jacal-1b9/elim.scm0000644001705200017500000002371410667300650011763 0ustar tbtb;; JACAL: Symbolic Mathematics System. -*-scheme-*- ;; Copyright 1989, 1990, 1991, 1992, 1993 Aubrey Jaffer. ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or (at ;; your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. (require 'common-list-functions) ;;;; Variable elimination (define (poly:elim poleqns vars) (cond (math:trace (display-diag 'eliminating:) (newline-diag) (math:write (map var->expl vars) *output-grammar*) (display-diag 'from:) (newline-diag) (math:write (poleqns->licits poleqns) *output-grammar*))) (do ((vs vars (cdr vs)) (polys poleqns) (poly #f)) ((null? vs) (cond (math:trace (display-diag 'yielding:) (newline-diag) (math:write polys *output-grammar*))) polys) (do ((var (car vs)) (pl polys (if (null? pl) (math:error 'not-enough-equations poleqns vars) (cdr pl))) (npl '() (cons (car pl) npl))) ((poly:find-var? (car pl) var) (set! poly (poly:promote var (car pl))) (do ((pls (cdr pl) (cdr pls))) ((null? pls) (set! polys npl)) (if (bunch? (car pls)) (math:error 'elim-bunch? (car pls))) (set! npl (cons (poly:elim2 poly (car pls) var) npl)))) (if (bunch? (car pl)) (math:error 'elim-bunch? (car pl)))))) ;(define (poly:restest p1 p2 var) ; (let ((v1 (poly:resultant p1 p2 var)) ; (v2 (poly:elim2 p1 p2 var))) ; (cond ((not (equal? v1 v2)) ; (display-diag " restest:") (newline-diag) ; (math:write (poleqns->licits p1) *output-grammar*) ; (newline) ; (math:write (poleqns->licits p2) *output-grammar*) ; (display-diag " ==>") (newline-diag) ; (math:write (poleqns->licits v1) *output-grammar*) ; (display-diag "different from:") (newline-diag) ; (math:write (poleqns->licits v2) *output-grammar*))) ; v2)) (define (intersection? l1 l2) (cond ((null? l1) #f) ((null? l2) #f) ((memq (car l1) l2) #t) (else (intersection? (cdr l1) l2)))) ;; (sort! ?? (lambda (x y) (< (ext:depth x) (ext:depth y)))) ;(define (ext:depth v) ; (let ((vds (var:depends v))) ; (if vds (+ 1 (apply max (map ext:depth vds))) ; 1))) ;;;EVS are all the extension vars used in extensions which are ;;; not being eliminated. ;;;IEVS are those EVS which involve VARS. ;;; sort them so nested extensions are done last. (define (ext:elim poleqns vars) (let* ((eqs (remove-if impl? poleqns)) (exps (remove-if-not impl? poleqns))) (if (> (length exps) 1) (math:error 'eliminating-from-more-than-one-expression? exps)) (let* ((aes (map chainables poleqns)) (evs (set-difference (reduce union aes) vars)) (ievs (remove-if-not (lambda (ev) (intersection? (var:depends ev) vars)) evs))) (cond ((not (null? ievs)) ;;tievs are the new extensions after any VARS are eliminated (do ((ievs ievs (cdr ievs))) ((null? ievs)) (let* ((iev (car ievs)) (tiev (var:elim iev (remove-if (lambda (x) (poly:find-var? x iev)) eqs) vars))) (set! eqs (cons (univ:norm0 iev (if (expl? tiev) (list tiev -1) (cdr tiev))) eqs)) (set! vars (cons iev vars)))))) (poly:elim (append eqs exps) vars)))) (define (var:elim var eqs ovars) (let* ((vars (var:depends var))) (cond ((null? vars) (math:warn 'free-var-to-var:elim var ovars)) ((radicalvar? var) (^ (find-if impl? (poly:elim (cons (expl->impl (cadr (func-arglist var))) eqs) ovars)) (caddr (func-arglist var)))) ((pair? (var:sexp var)) (apply deferop (map (lambda (e) (normalize (find-if impl? (ext:elim (cons (licit->impl e) eqs) ovars)))) (func-arglist var)))) (else (math:error 'elimination-type-not-handled var))))) ;;; This tries to solve the equations no matter what is involved. ;;; It will eliminate variables in vectors of equations. (define (eliminate eqns vars) (bunch:norm (if (some bunch? eqns) (let ((len #f)) (for-each (lambda (eqn) (cond ((not (bunch? eqn))) ((not len) (set! len (length eqn))) ((eqv? (length eqn) len)) (else (math:error 'bunches-to-eliminate-not-same-length len eqns)))) eqns) (apply map (lambda arglist (eliminate arglist vars)) (map (lambda (eqn) (if (bunch? eqn) eqn (make-list len eqn))) eqns))) (ext:elim eqns vars)))) (define (elim:test) (define a (sexp->var 'a)) (define x (sexp->var 'x)) (define y (sexp->var 'y)) (test (list (list a 0 0 124 81 11 3 45)) poly:elim (list (list y (list x (list a 0 0 2) (list a 0 1)) 1) (list y (list x (list a 5 1) 0 -1) 0 1) (list y (list x (list a -1 3) 5) -1)) (list x y))) (define (bunch:map proc b) (cond ((bunch? b) (map (lambda (x) (bunch:map proc x)) b)) (else (proc b)))) (define (licits:for-each proc b) (cond ((bunch? b) (for-each (lambda (x) (licits:for-each proc x)) b)) ((eqn? b) (proc (eqn->poly b))) (else (proc b)))) (define (licits:map proc b) (cond ((bunch? b) (map (lambda (x) (licits:map proc x)) b)) ((eqn? b) (poleqn->licit (proc (eqn->poly b)))) (else (proc b)))) (define (implicits:map proc b) (cond ((bunch? b) (map (lambda (x) (implicits:map proc x)) b)) ((eqn? b) (poleqns->licits (proc (eqn->poly b)))) ((expl? b) (proc (expl->impl b))) (else (proc b)))) ;;; replaces each var in poly with (proc var). ;;; Used for substitutions in clambda and capply. (define (poly:do-vars proc poly) (if (number? poly) poly (univ:demote (cons (proc (car poly)) (map (lambda (b) (poly:do-vars proc b)) (cdr poly)))))) (define (licits:do-vars proc licit) (licits:map (lambda (poly) (poly:do-vars proc poly)) licit)) ;;;; Canonical Lambda ;;;; This needs to handle algebraic extensions as well. (define (clambda symlist body) (let ((num-new-vars (length (remove-if lambdavar? symlist)))) (licits:do-vars (lambda (var) (let ((pos (position (var:nodiffs var) symlist))) (cond (pos (lambda-var (+ 1 pos) (var:diff-depth var))) ((lambdavar? var) (var:lambda-bump var num-new-vars)) ((lambdavarext? var) (bump-lambda-ext)) (else var)))) body))) (define (clambda? cexp) (cond ((number? cexp) #f) ((bunch? cexp) (some clambda? cexp)) ((expr? cexp) (poly:find-var-if? cexp lambdavardep?)) ((eqn? cexp) (poly:find-var-if? (eqn->poly cexp) lambdavardep?)) (else #f))) ;;;In order to keep the lambda application hygenic (in case a function ;;;of a function is called), we need to substitute occurences of ;;;lambda variables in the body with shadowed versions of the ;;;variables before we eliminate them. See: ;;; Technical Report No. 194 ;;; Hygenic Macro Expansion ;;; E.E.Kohlbecker, D.P.Friedman, M.Fellinson, and B.Duba ;;; Indiana University ;;; May, 1986 ;;; The bumped-only case is different from the some-bumped ;;; some-shadowed case in that it returns a publicly available (not ;;; shadowed) var. This is called from var:shadow in "types.scm". (define (var:lambda-bump var delta) (if (simple-lambdavar? var) (lambda-var (+ (lambda-position var) delta) (var:diff-depth var)) (sexp->var (do-sexp-symbols (lambda (s) (define st (symbol->string s)) (if (and (char=? #\@ (string-ref st 0)) (> (string-length st) 1)) (var:sexp (lambda-var (+ delta (string->number (substring st 1 (string-length st)))) 0)) s)) (var:sexp var))))) (define (do-sexp-symbols proc sexp) (cond ((symbol? sexp) (proc sexp)) ((pair? sexp) (map (lambda (s) (do-sexp-symbols proc s)) sexp)) (else sexp))) ;;; currently capply puts the structure of the clambda inside the ;;; structure of the arguments. (define (capply body larglist) (let* ((arglist (licits->impls larglist)) (arglist-length (length arglist)) (svlist '()) (sbody (licits:do-vars (lambda (var) (cond ((lambdavardep? var) (set! var (var:shadow var arglist-length)) (set! svlist (union (remove-if-not simple-shadowed-lambdavar? (cons var (var:depends var))) svlist)) var) (else var))) body)) (dargs (diffargs svlist arglist))) (implicits:map (lambda (p) (eliminate (cons p dargs) svlist)) sbody))) (define (diffargs vlist args) (map (lambda (var) (bunch:map (lambda (e) (univ:demote (cons var (cdr (licit->impl e))))) (diffarg var args))) vlist)) (define (diffarg var args) (cond ((var:differential? var) (total-differential (diffarg (var:undiff var) args))) (else (list-ref args (- (lambda-position var) 1))))) (define (licits:for-each-var proc polys) (licits:for-each (lambda (poly) (poly:for-each-var proc poly)) polys)) (define (licits:max-lambda-position polys) (let ((maxpos 0) (deps '())) (licits:for-each-var (lambda (v) (cond ((lambdavardep? v) (set! maxpos (max maxpos (var:max-lambda-position v))) (set! deps (adjoin v deps))))) polys) (for-each (lambda (v) (for-each (lambda (x) (if (lambdavardep? x) (set! maxpos (max maxpos (var:max-lambda-position x))))) (var:depends v))) deps) maxpos)) (define (var:max-lambda-position var) (let ((maxpos 0)) (for-each (lambda (x) (if (lambdavar? x) (set! maxpos (max maxpos (or (lambda-position x) maxpos))))) (cons var (var:depends var))) maxpos)) (define (var:min-lambda-position var) (let ((minpos 9999)) (for-each (lambda (x) (if (lambdavar? x) (set! minpos (min minpos (or (lambda-position x) minpos))))) (cons var (var:depends var))) (if (= minpos 9999) (math:error 'var:min-lambda-position var)) minpos)) jacal-1b9/jacalcat0000644001705200017500000000043307762447162012023 0ustar tbtb;;; "jacalcat": SLIB catalog additions for JACAL. -*-scheme-*- ( (finite-fields defmacro "ff") (polynomial-factors defmacro "factors") (combinatorics . "combin") (univariate-hensel defmacro "uv-hensel") (hensel . "hensel") (debug-jacal . "debug") (info . "info") ) jacal-1b9/English.scm0000644001705200017500000004430410731547107012426 0ustar tbtb;; JACAL: Symbolic Mathematics System. -*-scheme-*- ;; Copyright (C) 1989, 1990, 1991, 1992, 1993, 1995, 1997 Aubrey Jaffer. ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or (at ;; your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. (require 'fluid-let) (define tran:translations '((last-expression-lost . "; Last expression lost.") (bad-arglist . "bad arglist ") (column-of-non-matrix?:-- . "Column of non-matrix?: ") (coordinate-out-of-range:-- . "Coordinate out of range: ") (funny-length-vectors . "funny length vectors ") (unequal-length-vectors . "unequal length vectors ") (did-not-verify: . "Did not verify:") (error . "ERROR") (expt-of-equation?:-- . "Expt of equation?: ") (inexact-number-to-eval:- . "Inexact number to eval: ") (non-rational-radicand:-- . "Non-rational radicand: ") (not-a-number . "Not a Number") (not-a-matrix:-- . "Not a matrix: ") (row-of-non-matrix?:-- . "Row of non-matrix?: ") (application . "application ") (argument . " argument ") (arguments . " arguments ") (bad-info-entry . "bad info entry") (bunch . "bunch") (can-not-be-read . "can not be read") (can-not-be-set . "can not be set") (cannot-be-coerced-to-expl:-- . "cannot be coerced to expl:") (cannot-be-coerced-to-expr:-- . "cannot be coerced to expr: ") (cannot-be-coerced-to-implicit:-- . "cannot be coerced to implicit: ") (cannot-be-coerced-to-poly-eqn:-- . "cannot be coerced to poly eqn: ") (cannot-extract-denominator- . "cannot extract denominator ") (cannot-extract-numerator- . "cannot extract numerator ") (cannot-read-null-grammar . "cannot read null grammar") (cannot-suchthat-a-vector . "cannot suchthat a vector") (cc-of . "cc of ") (column-vector . "column vector") (could-not-clear-denominator-of:- . "could not clear denominator of: ") (delimiter-expected--ignoring-rest . "delimiter expected-ignoring rest") (determinant-of-non-square-matrix . "determinant of non-square matrix") (differential- . "differential ") (does-not-appear-in- . " does not appear in ") (does-not-divide- . " does not divide ") (does-not-udivide- . " does not udivide ") (dotproduct-of-unequal-size-matrices:-- . "dotproduct of unequal size matrices: ") (elim-bunch?- . "elim bunch?") (eliminating-from-more-than-one-expression?- . "eliminating from more than one expression?") (eliminating: . "eliminating:") (elimination-type-not-handled . "elimination type not handled") (equation . "equation") (expected-boolean . "expected boolean") (expected-boolean-or-number . "expected boolean or number") (expected-simple-symbol . "expected simple symbol") (expression-missing . "expression missing") (extra-delimiter . "extra delimiter") (extra-separator . "extra separator") (false . "false") (file-not-found . "file not found") (flag . "flag") (for-help. . " for help.") (free-var-to-var:elim . "free var to var:elim") (from: . " from:") (function-of- . " function of ") (grammar . "grammar") (implicit-expression . "implicit expression") (is-not-defined . "is not defined") (matrix . "matrix") (matrix-product-of-unequal-size-matrices:-- . "matrix product of unequal size matrices: ") (mismatched-delimiter . "mismatched delimiter") (more . "--more--") (nested-labels? . "nested labels? ") (no-example-for . "no example for ") (no-value-to-set . "no value to set") (no-variables? . "no variables?") (non-integer-power?-- . "non-integer power? ") (normalize-symbol?- . "normalize symbol? ") (normalizing: . "normalizing:") (not-a-function? . "not a function?") (not-a-polynomial-equation . "not a polynomial equation") (not-a-polynomial? . "not a polynomial?") (not-a-simple-variable:- . "not a simple variable: ") (not-an-integer- . "not an integer ") (not-an-operator . "not an operator") (not-canonical . "not canonical ") (not-enough-equations . "not enough equations") (not-known . "not known") (not-s-expression . " not s-expression") (number . "number") (of- . " of ") (off . "off") (on . "on") (or- . " or ") (partial-with-respect-to? . "partial with respect to?") (polynomial . "polynomial") (q-to-quit-space-for-more:- . " q to quit, space for more: ") (radical . "radical") (rational-expression . "rational expression") (redefined-from- . " redefined from ") (redefined-to- . " redefined to ") (row-vector . "row vector") (to- . " to ") (to-return-to- . " to return to ") (trouble-with . "trouble with ") (true . "true") (type . "type ") (type- . ", type ") (unknown . "unknown") (value-expected-equation-found:-- . "value expected, equation found: ") (variable . "variable ") (wna . ": Wrong number of args ") (wta . ": Wrong type ") (yielding: . "yielding:"))) ;;;; Here are the templates for 2 dimensional output (define tps:2d '( (template:default 140 #d0140 "(" #d1010 #(rest ", " #d2010) ")") (template:bunch 140 "[" #d0010 #(rest ", " break #d1010) "]") (template:matrix 140 (#\[) #d0010 #(rest " " #d1010) (#\])) (template:parenthesis 200 "(" #d1010 ")") (- 100 #d1100 " - " break #d2101 #(rest " - " break #d3101)) (negate 100 "- " #d1100) (+ 100 #d1100 #(rest " + " break #d2101)) (* 120 #d1120 #(rest " " #d2121)) (/ 120 #d1120 "/" #d2121) (over 120 ((-1 #d1040) (0 #\-) (1 #d2040))) (^ 140 #d1141 ((-1 #d2100))) (= 80 #d1080 " = " break #d2080 #(rest " = " break #d3080)) (differential 170 #d1170 "'") (partial 130 " " ((-1 "%") (0 #\-) (1 "%" #d2140)) " " #d1140) (suchthat 40 "{" #d1190 " | " #d2040 "}") (define 200 #d1120 ": " ((0 #d2010))) (rapply 200 #d1200 ((1 #d2030 #(rest "," #d3010)))) (abs 200 (#\|) #d1010 (#\|)) (box 200 ((-1 #\") (0 (#\") #d1010 (#\")) (1 #\"))) (factorial 160 #d1160 "!") (integrate 120 ((-3 #(optional #d4090)) (-2 "/ ") (-1 "! ") (0 "! ") (1 "! ") (2 "/ ") (3 #(optional #d3090))) #d1090 "d" #d2120) (limit 90 ((0 "limit ") (1 #d2090 "->" #d3090)) #d1090) (sum 90 ((-3 #(optional #d4090)) (-2 "====") (-1 "\\ ") (0 " > ") (1 "/ ") (2 "====") (3 #(optional #d2090 #(optional" = " #d3090)))) #d1090) (prod 90 ((-3 " " #(optional #d4090)) (-2 "/===/") (-1 " ! ! ") (0 " ! ! ") (1 " ! ! ") (2 #(optional #d2090 #(optional" = " #d3090)))) #d1090) (at 90 #d1090 ((-2 "!") (-1 "!") (0 "!") (1 "!") (2 "!")) ((2 #d2010 #(rest ", " #d3010)))) (help 100 "help;") (qed 100 "qed;") (% 200 "%") (ncmult 110 #d1109 " . " #d2109) (^^ 210 #d1211 "^^" #d2210) )) (define tps:c '( (template:default 140 #d0140 "(" #d1010 #(rest ", " #d2010) ")") (template:bunch 140 "{" #d0010 #(rest ", " #d1010) "}") (template:parenthesis 200 "(" #d1010 ")") (= 80 #d1080 " == " break #d2080 #(rest "==" break #d3080)) (- 100 #d1100 " - " break #d2101 #(rest " - " break #d3101)) (+ 100 #d1100 #(rest " + " break #d2101)) (* 120 #d1120 #(rest " * " #d2121)) (negate 90 "- " #d1090) (/ 120 #d1120 "/" #d2121) (over 120 #d1120 "/" #d2121) (^ 140 "pow(" #d1141 ", " #d2100 ")") (rapply 200 #d1200 "[" #d2030 #(rest "," #d3010) "]") (box 200 ((-1 #\") (0 (#\") #d1010 (#\")) (1 #\"))) (define 200 #d1120 " = " #d2010) (set 20 "set " #d1120 " " #d2010) (show 20 "show " #d1120) )) (define tps:std '( (template:default 140 #d0140 "(" #d1010 #(rest ", " #d2010) ")") (template:bunch 140 "[" #d0010 #(rest ", " break #d1010) "]") (template:parenthesis 200 "(" #d1010 ")") (= 80 #d1080 " = " break #d2080 #(rest " = " break #d3080)) (- 100 #d1100 " - " break #d2101 #(rest " - " break #d3101)) (+ 100 #d1100 #(rest " + " break #d2101)) (* 120 #d1120 #(rest " * " #d2121)) (negate 90 "- " #d1090) (/ 120 #d1120 "/" #d2121) (over 120 #d1120 "/" #d2121) (^ 140 #d1141 "^" #d2140) (differential 170 #d1170 "'") (suchthat 40 "{" #d1190 " | " #d2040 "}") (rapply 200 #d1200 "[" #d2030 #(rest "," #d3010) "]") (box 200 ((-1 #\") (0 (#\") #d1010 (#\")) (1 #\"))) (define 200 #d1120 ": " #d2010) (set 20 "set " #d1120 " " #d2010) (show 20 "show " #d1120) (factorial 160 #d1160 "!") (help 100 "help;") (qed 100 "qed;") (% 200 "%") (ncmult 110 #d1109 " . " #d2109) (^^ 210 #d1211 "^^" #d2210) )) (define tps:tex '( (template:top 0 "$" #d1000 "$") (template:default 140 #d0140 "\\left(" #d1010 #(rest ", " #d2010) "\\right)") (template:bunch 140 "\\left[" #d0010 #(rest ", " break #d1010) "\\right]") ;;; (template:matrix 140 "\\left({\matrix{" #d0010 #(rest "&" #d1010) ;;; (#\\)(#\c)(#\r) "}}\\right)") (template:parenthesis 200 "\\left(" #d1010 "\\right)") (= 80 #d1080 " = " break #d2080 #(rest " = " break #d3080)) (- 100 #d1100 " - " break #d2101 #(rest " - " break #d3101)) (+ 100 #d1100 #(rest " + " break #d2101)) (* 120 #d1120 #(rest "\\," #d2121)) (negate 90 "- " #d1100) (/ 120 #d1120 "/{" break #d2121 "}") (over 120 "{" #d1040 "}\\over{" break #d2041 "}") (^ 140 #d1141 "^{" #d2100 "}") (differential 170 "{" #d1170 "}'") (suchthat 40 "\\left\\{ " #d1190 " | " break #d2040 "\\right\\}") (rapply 200 #d1200 "\\left[" #d2030 #(rest "," break #d3010) "\\right]") (abs 200 "\\left|" #d1010 "\\right|") ;;; (box 200 ((-1 #\") ;;; (0 (#\") #d1010 (#\")) ;;; (1 #\"))) (define 200 #d1120 ": " #d2010) (set 20 "set " #d1120 " " #d2010) (show 20 "show " #d1120) (factorial 160 #d1160 "!") (help 100 "help;") (qed 100 "qed;") (% 200 "%") )) ;;;;The parse tables. ;;; Definitions accumulate in top-level variable *SYN-DEFS*. ;;;Syntax definitions for STANDARD GRAMMAR ;;; Begin by Ignoring whitespace characters. (set! *syn-defs* *syn-ignore-whitespace*) ;;; Character classes (prec:define-grammar (tok:char-group 70 #\^ list->string)) (prec:define-grammar (tok:char-group 49 #\* list->string)) (prec:define-grammar (tok:char-group 50 #\/ list->string)) (prec:define-grammar (tok:char-group 51 '(#\+ #\-) list->string)) (prec:define-grammar (tok:char-group 20 '(#\|) list->string)) (prec:define-grammar (tok:char-group 30 '(#\< #\> #\= #\: #\~) list->string)) (prec:define-grammar (tok:char-group 40 (string-append "." tok:decimal-digits) (lambda (l) (if (equal? '(#\.) l) #\. (string->number (list->string l)))))) (prec:define-grammar (tok:char-group 41 (string-append tok:upper-case tok:lower-case "@%?_") list->string)) (prec:define-grammar (tok:char-group (lambda (chr) (or (eqv? #\" chr) (eof-object? chr))) #\" (lambda (l) (tok:read-char) (list->string (cdr l))))) ;;; Delimiters and Separators ;;; Delimiters used to be defined here, but now are defined ;;; dynamically by parse functions. (prec:define-grammar (prec:delim #\]) ;;(prec:delim #\;) ;;(prec:delim #\,) ;;(prec:postfix #\$ (lambda (x) (write x)) 0) ) ;;;prefix operators (prec:define-grammar (prec:prefix '+ #f 100)) (prec:define-grammar (prec:prefix '- 'negate 100)) (prec:define-grammar (prec:prefix "+/-" 'u+/- 100)) (prec:define-grammar (prec:prefix "-/+" 'u-/+ 100)) (prec:define-grammar (prec:prefix '(not ~) 'impl:not 70)) (prec:define-grammar (prec:prefix ":" 'settemplate! 20)) ;;;nary operators (prec:define-grammar (prec:nary '* '* 120)) (prec:define-grammar (prec:nary '+ '+ 100)) (prec:define-grammar (prec:nary '- '- 100)) (prec:define-grammar (prec:nary "+/-" 'b+/- 100)) (prec:define-grammar (prec:nary "-/+" 'b-/+ 100)) (prec:define-grammar (prec:nary '/ '/ 120)) (prec:define-grammar (prec:nary '(and #\&) '& 60)) (prec:define-grammar (prec:nary 'or 'or 50)) (prec:define-grammar (prec:nary "||" 'parallel 110)) ;;;infix operators ;(prec:infix 'x 'crossproduct 111 110) (prec:define-grammar (prec:infix #\. 'ncmult 110 109)) (prec:define-grammar (prec:infix '(^ **) '^ 140 139)) (prec:define-grammar (prec:infix '^^ '^^ 210 210)) (prec:define-grammar (prec:infix '(":=" ":") 'define 180 20)) (prec:define-grammar (prec:infix '= '= 80 80)) ;(prec:define-grammar (prec:infix '(~= <>) 'make-not-equal 80 80)) (prec:define-grammar (prec:infix 'mod 'mod 70 70)) (prec:define-grammar (prec:infix ':: 'suchthat 190 40)) (prec:define-grammar (prec:infix "|" 'suchthat 190 40)) ;;; I don't remember what I had in mind here. ;(prec:define-grammar (prec:infix "" '* 120 120)) ;null operator ;;;postfix operators (prec:define-grammar (prec:postfix #\! 'factorial 160)) (prec:define-grammar (prec:postfix #\' 'differential 170)) ;;;matchfix operators (prec:define-grammar (prec:matchfix #\( identity #f #\))) (prec:define-grammar (prec:matchfix #\[ vector #\, #\])) (prec:define-grammar (prec:matchfix #\{ 'or #\, #\} (prec:infix "|" 'suchthat 190 40))) (prec:define-grammar (prec:matchfix #\\ 'lambda #\, #\;)) (prec:define-grammar (prec:matchfix "|" 'abs #f "|")) ;;;special operators (prec:define-grammar (prec:inmatchfix #\( list #\, #\) 200)) (prec:define-grammar (prec:inmatchfix #\[ 'rapply #\, #\] 200)) ;;;rest operator reads expressions up to next delimiter. (prec:define-grammar (prec:prestfix 'set 'set 10)) (prec:define-grammar (prec:prestfix 'show 'show 10)) ;;;miscellany ;(prec:define-grammar (prec:prefix 'load 'load 50)) (prec:define-grammar (prec:nofix '% '%)) (prec:define-grammar (prec:nofix 'help 'help)) (prec:define-grammar (prec:nofix 'qed 'qed)) (prec:define-grammar (prec:commentfix "/*" (lambda (str) (and str (call-with-input-string str (lambda (pt) (fluid-let ((*prec:port* pt)) (if (eq? (get-grammar 'null) *echo-grammar*) (do ((i (string-length str) (+ -1 i))) ((zero? i)) (tok:read-char)) (do ((i (string-length str) (+ -1 i))) ((zero? i)) (display (tok:read-char))))))))) "*/")) (defgrammar 'standard (make-grammar 'standard ;name (lambda (grm) ;reader (prec:parse (grammar-read-tab grm) #\; (current-input-port))) *syn-defs* ;read-tab print-using-grammar ;writer tps:std)) ;write-tab (defgrammar 'disp2d (make-grammar 'disp2d ;name (lambda (grm) ;reader (prec:parse (grammar-read-tab grm) #\; (current-input-port))) *syn-defs* ;read-tab print-using-grammar ;writer tps:2d)) ;write-tab (set! *input-grammar* (get-grammar 'standard)) (set! *output-grammar* (get-grammar 'disp2d)) ;;;; Syntax definitions for TEX GRAMMAR ;;; Begin by Ignoring whitespace characters. (set! *syn-defs* *syn-ignore-whitespace*) (prec:define-grammar (tok:char-group 40 tok:decimal-digits (lambda (l) (string->number (list->string l))))) (prec:define-grammar (tok:char-group 41 (string-append tok:upper-case tok:lower-case) list->string)) (let ((seen1 #f)) (prec:define-grammar (tok:char-group (lambda (chr) (cond (seen1 (not (char-alphabetic? chr))) ((not (char-alphabetic? chr)) (set! seen1 chr) #t) (else (set! seen1 #t) #f))) '(#\\) (lambda (l) (cond ((char? seen1) (tok:read-char) (set! l (list #\\ seen1)))) (set! seen1 #f) (list->string l))))) (prec:define-grammar (prec:commentfix #\$ #f #\$)) (prec:define-grammar (prec:delim #\,)) (prec:define-grammar (prec:delim #\;)) (prec:define-grammar (prec:prefix #\+ #f 100)) (prec:define-grammar (prec:prefix #\- 'negate 100)) (prec:define-grammar (prec:postfix #\! 'factorial 160)) (prec:define-grammar (prec:postfix #\' 'differential 170)) (prec:define-grammar (prec:infix #\: 'define 180 20)) (prec:define-grammar (prec:infix #\= '= 80 80)) (prec:define-grammar (prec:nary '(#\* "\\,") '* 120)) (prec:define-grammar (prec:nary #\+ '+ 100)) (prec:define-grammar (prec:nary #\- '- 100)) (prec:define-grammar (prec:nary #\/ '/ 120)) (prec:define-grammar (prec:nary "\\over" '/ 120)) (prec:define-grammar (prec:nary #\& vector 50)) (prec:define-grammar (prec:nary "\\cr" vector 49)) (prec:define-grammar (prec:commentfix '("\\left" "\\right" "\\big" "\\bigm" "\\bigl" "\\bigr" "\\bigg" "\\biggm" "\\biggl" "\\biggr" "\\Big" "\\Bigm" "\\Bigl" "\\Bigr" "\\Bigg" "\\Biggm" "\\Biggl" "\\Biggr") #f #f)) (prec:define-grammar (prec:commentfix #\% #f #\newline)) (prec:define-grammar (prec:inmatchfix #\( #f #\, #\) 200)) (prec:define-grammar (prec:matchfix #\( #f #f #\))) (prec:define-grammar (prec:matchfix #\{ #f #f #\})) (prec:define-grammar (prec:matchfix "\\lbrace" #f #f "\\rbrace")) (prec:define-grammar (prec:inmatchfix #\[ 'rapply #\, #\] 200)) (prec:define-grammar (prec:inmatchfix "\\lbrack" 'rapply #\, "\\rbrack" 200)) (prec:define-grammar (prec:matchfix #\[ vector #\, #\])) (prec:define-grammar (prec:infix '(#\| "\\vert") 'suchthat 190 40)) (prec:define-grammar (prec:infix #\^ '^ 140 139)) (prec:define-grammar (prec:prefix "\\sqrt" (lambda (arg) `(^ ,arg (/ 1 2))) 100)) (prec:define-grammar (prec:prefix "\\frac" '/ 100)) ;prefix2 ;(prec:define-grammar (prec:delim "\\of")) ;(prec:define-grammar (prec:prefix "\\root" (lambda (arg) `(^ ,arg (/ 1 2))) 100)) (prec:define-grammar (prec:prefix 'load 'load 50)) (prec:define-grammar (prec:nofix '% '%)) (prec:define-grammar (prec:nofix 'help 'help)) (prec:define-grammar (prec:nofix '(qed bye exit) 'qed)) (prec:define-grammar (prec:prestfix 'set 'set 10)) (prec:define-grammar (prec:prestfix 'show 'show 10)) (defgrammar 'tex (make-grammar 'tex ;name (lambda (grm) ;reader (prec:parse (grammar-read-tab grm) #\; (current-input-port))) *syn-defs* ;read-tab print-using-grammar ;writer tps:tex)) ;write-tab jacal-1b9/modeinit.scm0000644001705200017500000000345710667300650012647 0ustar tbtb;; JACAL: Symbolic Mathematics System. -*-scheme-*- ;; Copyright 1989, 1990, 1991, 1992, 1993 Aubrey Jaffer. ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or (at ;; your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. (set! Language "English") ;grammar .scm should exist (set! math:debug #f) ; #t to break on soft errors, #f to continue. ;Does extra checking. (set! math:phases #f) ; #t to show phases of normaization. (set! math:trace #f) ; #t to trace variable eliminations, #f not to. (set! linkradicals #t) ;Relate radicals in the traditional manner. (set! horner #f) ;Horner's rule on expression output (set! page-height #t) ;#t for pagination on, #f off (set! page-width #t) ;Number or #t to use SLIB's width. #f for wide. (set! newextstr (string-standard-case "EXT0")) ;extension template (set! newlabelstr (string-standard-case "E0")) ;prompt template (set! newlabelsym (string->symbol newlabelstr)) (set! % novalue) (let ((init (in-vicinity (user-vicinity) "mathinit"))) (if (file-exists? init) (slib:load init))) ;User initialization file (if (and Language (= 3 (length (list-of-grammars)))) ;none loaded yet. (slib:load (in-vicinity (program-vicinity) Language))) jacal-1b9/jacal.info0000644001705200017500000033125010751434546012263 0ustar tbtbThis is jacal.info, produced by makeinfo version 4.8 from jacal.texi. This manual is for JACAL (version 1b9, February 2008), an interactive | symbolic mathematics system. Copyright (C) 1993-1999, 2002, 2006, 2007 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License." INFO-DIR-SECTION Mathematics START-INFO-DIR-ENTRY * Jacal: (jacal). Interactive Symbolic Mathematics. END-INFO-DIR-ENTRY  File: jacal.info, Node: Top, Next: Overview, Prev: (dir), Up: (dir) JACAL ***** This manual is for JACAL (version 1b9, February 2008), an interactive | symbolic mathematics system. Copyright (C) 1993-1999, 2002, 2006, 2007 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License." * Menu: * Overview:: Installing and Starting JACAL * Algebra:: Operators and Commands * Calculus:: Operators and Commands * Matrices and Tensors:: * Lambda Calculus:: Functions * Miscellaneous:: * Flags:: * Index::  File: jacal.info, Node: Overview, Next: Algebra, Prev: Top, Up: Top 1 Overview ********** JACAL is a symbolic mathematics system for the simplification and manipulation of equations and single and multiple valued algebraic expressions constructed of numbers, variables, radicals, and algebraic functions, differential, and holonomic functions. In addition, vectors and matrices of the above objects are included. JACAL 1b9 was released February 2008. Current information about | JACAL can be found on JACAL's "WWW" home page: | | `http://swiss.csail.mit.edu/~jaffer/JACAL' | | JACAL, part of the GNU project, is free software, and you are welcome | to redistribute it under certain conditions; See the file COPYING with | this program or type `(terms)();' to JACAL for details. | For a list of the features that have changed since the last JACAL release, see the file `ANNOUNCE'. For a list of the features that have changed over time, see the file `ChangeLog'. * Menu: * Authors and Bibliography:: * Installation:: How to install JACAL on your system. * Running Jacal:: * Release Notes:: Useful information. * GNU Free Documentation License::  File: jacal.info, Node: Authors and Bibliography, Next: Installation, Prev: Overview, Up: Overview 1.1 Authors and Bibliography ============================ Aubrey Jaffer Most of JACAL Michael Thomas Polynomial Factoring. Jerry D. Hedden Tensors. The maintainer can be reached as `agj @ alum.mit.edu'. Bibliography ------------ [ACP] Donald Ervin Knuth. `The Art of Computer Programming : Seminumerical Algorithms (Vol 2).' 2nd Ed (1981) Addison-Wesley Pub Co; ISBN: 0-201-03822-6 [GCL] Keith O. Geddes, Stephen R. Czapor, George Labahn. `Algorithms for Computer Algebra.' (October 1992) Kluwer Academic Pub; ISBN: 0-7923-9259-0 [Siret] Y. Siret (Editor), E. Tournier, J. H. Davenport, F. Tournier. `Computer Algebra: Systems and Algorithms for Algebraic Computation' 2nd edition (June 1993) Academic Press; ISBN: 0-122-04232-8 [R5RS] Richard Kelsey and William Clinger and Jonathan (Rees, editors) Revised(5) Report on the Algorithmic Language Scheme (r5rs_toc), `Higher-Order and Symbolic Computation' Volume 11, Number 1 (1998), pp. 7-105, or `ACM SIGPLAN Notices' 33(9), September 1998. *Note Revised(5) Report on the Algorithmic Language Scheme: (r5rs)Top. [SLIB] Todd R. Eigenschink and Aubrey Jaffer. SLIB; The Portable Scheme Library (slib_toc) *Note SLIB; The Portable Scheme Library: (slib)Top.  File: jacal.info, Node: Installation, Next: Running Jacal, Prev: Authors and Bibliography, Up: Overview 1.2 Installation ================ The JACAL program is written in the Algorithmic Language "Scheme". So you must obtain and install a Scheme implementation in order to run it. The installation procedures given here use the SCM Scheme implementation. If your system has a Scheme (or Guile) implementation installed, then the `scm' steps are unnecessary. JACAL also requires the SLIB Portable Scheme library which is available from `http://swiss.csail.mit.edu/~jaffer/SLIB'. -- System: i386 GNU/Linux with Redhat Package Manager (rpm) wget http://swiss.csail.mit.edu/ftpdir/scm/scm-5e5-1.i386.rpm | wget http://swiss.csail.mit.edu/ftpdir/scm/slib-3b1-1.noarch.rpm | wget http://swiss.csail.mit.edu/ftpdir/scm/jacal-1b9-1.noarch.rpm | rpm -U scm-5e5-1.i386.rpm slib-3b1-1.noarch.rpm jacal-1b9-1.noarch.rpm rm scm-5e5-1.i386.rpm slib-3b1-1.noarch.rpm jacal-1b9-1.noarch.rpm | The command `jacal' will start an interactive session. -- System: Unix -- System: GNU/Linux wget http://swiss.csail.mit.edu/ftpdir/scm/scm-5e5.zip | wget http://swiss.csail.mit.edu/ftpdir/scm/slib-3b1.zip | wget http://swiss.csail.mit.edu/ftpdir/scm/jacal-1b9.zip | unzip -ao scm-5e5.zip | unzip -ao slib-3b1.zip | unzip -ao jacal-1b9.zip | (cd slib; make install) (cd scm; make scm; make install) (cd jacal; make install) rm scm-5e5.zip slib-3b1.zip jacal-1b9.zip | The command `jacal' will start an interactive session using ELK, Gambit, Guile, Larceny, MIT-Scheme, MzScheme, Scheme48, SCM, or | SISC. Type `jacal --help' for instructions. | -- System: Apple `http://www.io.com/~cobblers/scm/' has downloads and utilities for installing SCM and SLIB on Macintosh computers. -- System: x86 Microsoft Download and run `http://swiss.csail.mit.edu/ftpdir/scm/SLIB-3b1-1.exe', | `http://swiss.csail.mit.edu/ftpdir/scm/SCM-5e5-1.exe', and | `http://swiss.csail.mit.edu/ftpdir/scm/JACAL-1b9-1.exe'. | Compiling Jacal --------------- For Scheme implementations with compilers, it is worthwhile to compile SLIB files, and the JACAL files `types.scm' and `poly.scm'.  File: jacal.info, Node: Running Jacal, Next: Release Notes, Prev: Installation, Up: Overview 1.3 Running Jacal ================= If you successfully executed one of the installations of the previous section, then typing `jacal' or clicking an icon will begin an interactive session. To manually start jacal, start your Scheme implementation with SLIB. This may involve setting up that implementation's initialization file or LOADing a `.init' file from the `slib' directory. Then type: (slib:load "/usr/local/lib/jacal/math") where `/usr/local/lib/jacal/' is a path to the JACAL directory. JACAL should then print: JACAL version 1b9, Copyright 1989-1999, 2002 Aubrey Jaffer | JACAL comes with ABSOLUTELY NO WARRANTY; for details type `(terms)'. This is free software, and you are welcome to redistribute it under certain conditions; type `(terms)' for details. ;;; Type (math) to begin. Do as it says: (math) => type qed; to return to scheme, type help; for help. e0 : And you are ready to try the commands described in the rest of the manual. Demonstrating Jacal ------------------- There are several demonstration files in the `jacal' directory. To run, use the batch command *Note batch: Miscellaneous. `batch("demo");' Demonstrates a variety of JACAL features. `batch("test.math");' Tests each operator. `batch("rw.math");' Demonstrates tensors and The Robertson-Walker Cosmology Model. Recovery from Errors -------------------- As JACAL is a complicated program there are bugs which will occasionally cause the program to stop with some sort of error reported by the underlying Scheme system. In interactive implementations (such as SCM) you can usually continue your session by typing `(math)'. The expression which was input to JACAL just before the error will be lost but you should be able to otherwise continue with your session. Stopping Jacal -------------- The command `quit();' will end your JACAL session. With non-interactive Scheme implementations the JACAL command `qed();' or typing the end-of-file character ( on MS-DOS and VMS, on others) will end your JACAL session. The command `qed();' will return to the interactive Scheme session. Typing `(math)' will return to the JACAL session. From the interactive Scheme session `(exit)' or possibly an end-of-file character will terminate the session.  File: jacal.info, Node: Release Notes, Next: GNU Free Documentation License, Prev: Running Jacal, Up: Overview | 1.4 Release Notes ================= With the standard input grammar, the precedence of `-' as a prefix behaves strangely. `a^-b*c' becomes `a^(-b*c)' while `a^b*c=> (a^b)*c'. Using `divide' to divide a polynomial by an integer does not work. The command `example' executes the example it gives. This can lead to unpredictable results if the variables and constants in the example have already been given values by the user. The function `minor' should be modified to accept lists for ROW and COL. Resultant might be modified to compute the resultant of a system of polynomials with respect to a list of variables. Conventions ----------- Things that are labeled as Operators can occur in expressions output by Jacal. Things that are labeled as Commands act upon their arguments and do not generally occur in expressions output by Jacal. Things that are labeled as flags are `set' to control aspects of the Jacal environment. The examples throughout this text were produced using `SCM'. Jacal has several grammers it understands. The `standard' grammar is used in this manual. It is like simple `TeX' grammar and algol family computer languages. Identifier names are case sensitive and can be any number of characters long. Manifest -------- COPYING details the LACK OF WARRANTY for Jacal and the conditions for distributing Jacal. HELP is online introduction to using Jacal. ChangeLog documents changes to Jacal. jacal is a unix (sh) script to start an interactive jacal session. demo demonstrates batch file use. "batch(demo);" to use in jacal. rw.math is a batch file of Robertson-Walker model of General Relativity. test.math is a batch file which tests Jacal. jacal.texi is documentation on how to use jacal in TeXinfo format. DOC has files telling about how jacal works. algdenom gives an algorithm for clearing radicals and other algebraic field extensions from denominators. grammar explains how to create new grammars. history gives a little history of jacal. lambda explains mid-level data formats. From a Dr. Dobbs article. ratint.tex article explaining jacal's eventual integration algorithm. math.scm is the file you load into scheme in order to run jacal. toploads.scm contains comments describing the rest of the files. modeinit.scm has initializations for modes in Jacal. view.scm is a program for viewing TeX expressions.  File: jacal.info, Node: GNU Free Documentation License, Prev: Release Notes, Up: Overview | 1.5 GNU Free Documentation License | ================================== | | Version 1.2, November 2002 | | Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. | 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | | Everyone is permitted to copy and distribute verbatim copies | of this license document, but changing it is not allowed. | | 0. PREAMBLE | | The purpose of this License is to make a manual, textbook, or other | functional and useful document "free" in the sense of freedom: to | assure everyone the effective freedom to copy and redistribute it, | with or without modifying it, either commercially or | noncommercially. Secondarily, this License preserves for the | author and publisher a way to get credit for their work, while not | being considered responsible for modifications made by others. | | This License is a kind of "copyleft", which means that derivative | works of the document must themselves be free in the same sense. | It complements the GNU General Public License, which is a copyleft | license designed for free software. | | We have designed this License in order to use it for manuals for | free software, because free software needs free documentation: a | free program should come with manuals providing the same freedoms | that the software does. But this License is not limited to | software manuals; it can be used for any textual work, regardless | of subject matter or whether it is published as a printed book. | We recommend this License principally for works whose purpose is | instruction or reference. | | 1. APPLICABILITY AND DEFINITIONS | | This License applies to any manual or other work, in any medium, | that contains a notice placed by the copyright holder saying it | can be distributed under the terms of this License. Such a notice | grants a world-wide, royalty-free license, unlimited in duration, | to use that work under the conditions stated herein. The | "Document", below, refers to any such manual or work. Any member | of the public is a licensee, and is addressed as "you". You | accept the license if you copy, modify or distribute the work in a | way requiring permission under copyright law. | | A "Modified Version" of the Document means any work containing the | Document or a portion of it, either copied verbatim, or with | modifications and/or translated into another language. | | A "Secondary Section" is a named appendix or a front-matter section | of the Document that deals exclusively with the relationship of the | publishers or authors of the Document to the Document's overall | subject (or to related matters) and contains nothing that could | fall directly within that overall subject. (Thus, if the Document | is in part a textbook of mathematics, a Secondary Section may not | explain any mathematics.) The relationship could be a matter of | historical connection with the subject or with related matters, or | of legal, commercial, philosophical, ethical or political position | regarding them. | | The "Invariant Sections" are certain Secondary Sections whose | titles are designated, as being those of Invariant Sections, in | the notice that says that the Document is released under this | License. If a section does not fit the above definition of | Secondary then it is not allowed to be designated as Invariant. | The Document may contain zero Invariant Sections. If the Document | does not identify any Invariant Sections then there are none. | | The "Cover Texts" are certain short passages of text that are | listed, as Front-Cover Texts or Back-Cover Texts, in the notice | that says that the Document is released under this License. A | Front-Cover Text may be at most 5 words, and a Back-Cover Text may | be at most 25 words. | | A "Transparent" copy of the Document means a machine-readable copy, | represented in a format whose specification is available to the | general public, that is suitable for revising the document | straightforwardly with generic text editors or (for images | composed of pixels) generic paint programs or (for drawings) some | widely available drawing editor, and that is suitable for input to | text formatters or for automatic translation to a variety of | formats suitable for input to text formatters. A copy made in an | otherwise Transparent file format whose markup, or absence of | markup, has been arranged to thwart or discourage subsequent | modification by readers is not Transparent. An image format is | not Transparent if used for any substantial amount of text. A | copy that is not "Transparent" is called "Opaque". | | Examples of suitable formats for Transparent copies include plain | ASCII without markup, Texinfo input format, LaTeX input format, | SGML or XML using a publicly available DTD, and | standard-conforming simple HTML, PostScript or PDF designed for | human modification. Examples of transparent image formats include | PNG, XCF and JPG. Opaque formats include proprietary formats that | can be read and edited only by proprietary word processors, SGML or | XML for which the DTD and/or processing tools are not generally | available, and the machine-generated HTML, PostScript or PDF | produced by some word processors for output purposes only. | | The "Title Page" means, for a printed book, the title page itself, | plus such following pages as are needed to hold, legibly, the | material this License requires to appear in the title page. For | works in formats which do not have any title page as such, "Title | Page" means the text near the most prominent appearance of the | work's title, preceding the beginning of the body of the text. | | A section "Entitled XYZ" means a named subunit of the Document | whose title either is precisely XYZ or contains XYZ in parentheses | following text that translates XYZ in another language. (Here XYZ | stands for a specific section name mentioned below, such as | "Acknowledgements", "Dedications", "Endorsements", or "History".) | To "Preserve the Title" of such a section when you modify the | Document means that it remains a section "Entitled XYZ" according | to this definition. | | The Document may include Warranty Disclaimers next to the notice | which states that this License applies to the Document. These | Warranty Disclaimers are considered to be included by reference in | this License, but only as regards disclaiming warranties: any other | implication that these Warranty Disclaimers may have is void and | has no effect on the meaning of this License. | | 2. VERBATIM COPYING | | You may copy and distribute the Document in any medium, either | commercially or noncommercially, provided that this License, the | copyright notices, and the license notice saying this License | applies to the Document are reproduced in all copies, and that you | add no other conditions whatsoever to those of this License. You | may not use technical measures to obstruct or control the reading | or further copying of the copies you make or distribute. However, | you may accept compensation in exchange for copies. If you | distribute a large enough number of copies you must also follow | the conditions in section 3. | | You may also lend copies, under the same conditions stated above, | and you may publicly display copies. | | 3. COPYING IN QUANTITY | | If you publish printed copies (or copies in media that commonly | have printed covers) of the Document, numbering more than 100, and | the Document's license notice requires Cover Texts, you must | enclose the copies in covers that carry, clearly and legibly, all | these Cover Texts: Front-Cover Texts on the front cover, and | Back-Cover Texts on the back cover. Both covers must also clearly | and legibly identify you as the publisher of these copies. The | front cover must present the full title with all words of the | title equally prominent and visible. You may add other material | on the covers in addition. Copying with changes limited to the | covers, as long as they preserve the title of the Document and | satisfy these conditions, can be treated as verbatim copying in | other respects. | | If the required texts for either cover are too voluminous to fit | legibly, you should put the first ones listed (as many as fit | reasonably) on the actual cover, and continue the rest onto | adjacent pages. | | If you publish or distribute Opaque copies of the Document | numbering more than 100, you must either include a | machine-readable Transparent copy along with each Opaque copy, or | state in or with each Opaque copy a computer-network location from | which the general network-using public has access to download | using public-standard network protocols a complete Transparent | copy of the Document, free of added material. If you use the | latter option, you must take reasonably prudent steps, when you | begin distribution of Opaque copies in quantity, to ensure that | this Transparent copy will remain thus accessible at the stated | location until at least one year after the last time you | distribute an Opaque copy (directly or through your agents or | retailers) of that edition to the public. | | It is requested, but not required, that you contact the authors of | the Document well before redistributing any large number of | copies, to give them a chance to provide you with an updated | version of the Document. | | 4. MODIFICATIONS | | You may copy and distribute a Modified Version of the Document | under the conditions of sections 2 and 3 above, provided that you | release the Modified Version under precisely this License, with | the Modified Version filling the role of the Document, thus | licensing distribution and modification of the Modified Version to | whoever possesses a copy of it. In addition, you must do these | things in the Modified Version: | | A. Use in the Title Page (and on the covers, if any) a title | distinct from that of the Document, and from those of | previous versions (which should, if there were any, be listed | in the History section of the Document). You may use the | same title as a previous version if the original publisher of | that version gives permission. | | B. List on the Title Page, as authors, one or more persons or | entities responsible for authorship of the modifications in | the Modified Version, together with at least five of the | principal authors of the Document (all of its principal | authors, if it has fewer than five), unless they release you | from this requirement. | | C. State on the Title page the name of the publisher of the | Modified Version, as the publisher. | | D. Preserve all the copyright notices of the Document. | | E. Add an appropriate copyright notice for your modifications | adjacent to the other copyright notices. | | F. Include, immediately after the copyright notices, a license | notice giving the public permission to use the Modified | Version under the terms of this License, in the form shown in | the Addendum below. | | G. Preserve in that license notice the full lists of Invariant | Sections and required Cover Texts given in the Document's | license notice. | | H. Include an unaltered copy of this License. | | I. Preserve the section Entitled "History", Preserve its Title, | and add to it an item stating at least the title, year, new | authors, and publisher of the Modified Version as given on | the Title Page. If there is no section Entitled "History" in | the Document, create one stating the title, year, authors, | and publisher of the Document as given on its Title Page, | then add an item describing the Modified Version as stated in | the previous sentence. | | J. Preserve the network location, if any, given in the Document | for public access to a Transparent copy of the Document, and | likewise the network locations given in the Document for | previous versions it was based on. These may be placed in | the "History" section. You may omit a network location for a | work that was published at least four years before the | Document itself, or if the original publisher of the version | it refers to gives permission. | | K. For any section Entitled "Acknowledgements" or "Dedications", | Preserve the Title of the section, and preserve in the | section all the substance and tone of each of the contributor | acknowledgements and/or dedications given therein. | | L. Preserve all the Invariant Sections of the Document, | unaltered in their text and in their titles. Section numbers | or the equivalent are not considered part of the section | titles. | | M. Delete any section Entitled "Endorsements". Such a section | may not be included in the Modified Version. | | N. Do not retitle any existing section to be Entitled | "Endorsements" or to conflict in title with any Invariant | Section. | | O. Preserve any Warranty Disclaimers. | | If the Modified Version includes new front-matter sections or | appendices that qualify as Secondary Sections and contain no | material copied from the Document, you may at your option | designate some or all of these sections as invariant. To do this, | add their titles to the list of Invariant Sections in the Modified | Version's license notice. These titles must be distinct from any | other section titles. | | You may add a section Entitled "Endorsements", provided it contains | nothing but endorsements of your Modified Version by various | parties--for example, statements of peer review or that the text | has been approved by an organization as the authoritative | definition of a standard. | | You may add a passage of up to five words as a Front-Cover Text, | and a passage of up to 25 words as a Back-Cover Text, to the end | of the list of Cover Texts in the Modified Version. Only one | passage of Front-Cover Text and one of Back-Cover Text may be | added by (or through arrangements made by) any one entity. If the | Document already includes a cover text for the same cover, | previously added by you or by arrangement made by the same entity | you are acting on behalf of, you may not add another; but you may | replace the old one, on explicit permission from the previous | publisher that added the old one. | | The author(s) and publisher(s) of the Document do not by this | License give permission to use their names for publicity for or to | assert or imply endorsement of any Modified Version. | | 5. COMBINING DOCUMENTS | | You may combine the Document with other documents released under | this License, under the terms defined in section 4 above for | modified versions, provided that you include in the combination | all of the Invariant Sections of all of the original documents, | unmodified, and list them all as Invariant Sections of your | combined work in its license notice, and that you preserve all | their Warranty Disclaimers. | | The combined work need only contain one copy of this License, and | multiple identical Invariant Sections may be replaced with a single | copy. If there are multiple Invariant Sections with the same name | but different contents, make the title of each such section unique | by adding at the end of it, in parentheses, the name of the | original author or publisher of that section if known, or else a | unique number. Make the same adjustment to the section titles in | the list of Invariant Sections in the license notice of the | combined work. | | In the combination, you must combine any sections Entitled | "History" in the various original documents, forming one section | Entitled "History"; likewise combine any sections Entitled | "Acknowledgements", and any sections Entitled "Dedications". You | must delete all sections Entitled "Endorsements." | | 6. COLLECTIONS OF DOCUMENTS | | You may make a collection consisting of the Document and other | documents released under this License, and replace the individual | copies of this License in the various documents with a single copy | that is included in the collection, provided that you follow the | rules of this License for verbatim copying of each of the | documents in all other respects. | | You may extract a single document from such a collection, and | distribute it individually under this License, provided you insert | a copy of this License into the extracted document, and follow | this License in all other respects regarding verbatim copying of | that document. | | 7. AGGREGATION WITH INDEPENDENT WORKS | | A compilation of the Document or its derivatives with other | separate and independent documents or works, in or on a volume of | a storage or distribution medium, is called an "aggregate" if the | copyright resulting from the compilation is not used to limit the | legal rights of the compilation's users beyond what the individual | works permit. When the Document is included in an aggregate, this | License does not apply to the other works in the aggregate which | are not themselves derivative works of the Document. | | If the Cover Text requirement of section 3 is applicable to these | copies of the Document, then if the Document is less than one half | of the entire aggregate, the Document's Cover Texts may be placed | on covers that bracket the Document within the aggregate, or the | electronic equivalent of covers if the Document is in electronic | form. Otherwise they must appear on printed covers that bracket | the whole aggregate. | | 8. TRANSLATION | | Translation is considered a kind of modification, so you may | distribute translations of the Document under the terms of section | 4. Replacing Invariant Sections with translations requires special | permission from their copyright holders, but you may include | translations of some or all Invariant Sections in addition to the | original versions of these Invariant Sections. You may include a | translation of this License, and all the license notices in the | Document, and any Warranty Disclaimers, provided that you also | include the original English version of this License and the | original versions of those notices and disclaimers. In case of a | disagreement between the translation and the original version of | this License or a notice or disclaimer, the original version will | prevail. | | If a section in the Document is Entitled "Acknowledgements", | "Dedications", or "History", the requirement (section 4) to | Preserve its Title (section 1) will typically require changing the | actual title. | | 9. TERMINATION | | You may not copy, modify, sublicense, or distribute the Document | except as expressly provided for under this License. Any other | attempt to copy, modify, sublicense or distribute the Document is | void, and will automatically terminate your rights under this | License. However, parties who have received copies, or rights, | from you under this License will not have their licenses | terminated so long as such parties remain in full compliance. | | 10. FUTURE REVISIONS OF THIS LICENSE | | The Free Software Foundation may publish new, revised versions of | the GNU Free Documentation License from time to time. Such new | versions will be similar in spirit to the present version, but may | differ in detail to address new problems or concerns. See | `http://www.gnu.org/copyleft/'. | | Each version of the License is given a distinguishing version | number. If the Document specifies that a particular numbered | version of this License "or any later version" applies to it, you | have the option of following the terms and conditions either of | that specified version or of any later version that has been | published (not as a draft) by the Free Software Foundation. If | the Document does not specify a version number of this License, | you may choose any version ever published (not as a draft) by the | Free Software Foundation. | | ADDENDUM: How to use this License for your documents | ==================================================== | | To use this License in a document you have written, include a copy of | the License in the document and put the following copyright and license | notices just after the title page: | | Copyright (C) YEAR YOUR NAME. | Permission is granted to copy, distribute and/or modify this document | under the terms of the GNU Free Documentation License, Version 1.2 | or any later version published by the Free Software Foundation; | with no Invariant Sections, no Front-Cover Texts, and no Back-Cover | Texts. A copy of the license is included in the section entitled ``GNU Free Documentation License''. | | If you have Invariant Sections, Front-Cover Texts and Back-Cover | Texts, replace the "with...Texts." line with this: | | with the Invariant Sections being LIST THEIR TITLES, with | the Front-Cover Texts being LIST, and with the Back-Cover Texts | being LIST. | | If you have Invariant Sections without Cover Texts, or some other | combination of the three, merge those two alternatives to suit the | situation. | | If your document contains nontrivial examples of program code, we | recommend releasing these examples in parallel under your choice of | free software license, such as the GNU General Public License, to | permit their use in free software. | |  File: jacal.info, Node: Algebra, Next: Calculus, Prev: Overview, Up: Top | 2 Algebra ********* * Menu: * Algebraic Operators:: * Algebraic Commands:: * Rational Expression:: * Polynomials:: * Factoring::  File: jacal.info, Node: Algebraic Operators, Next: Algebraic Commands, Prev: Algebra, Up: Algebra 2.1 Algebraic Operators ======================= -- Operator: + augend addend Addition of scalar quantities or componentwise addition of bunches is accomplished by means of the infix operator `+'. For example, e2 : a:[[1, 3, 5], [2, 4, 7]]; [1 3 5] e2: [ ] [2 4 7] e3 : b:[2, 4]; e3: [2, 4] e4 : a + b; [3 5 7 ] e4: [ ] [6 8 11] e5 : 3 + 2; e5: 5 e6 : c + b; e6: [2 + c, 4 + c] e7 : e1 + e5; 2 2 e7: 5 + (8 a + 12 a ) b -- Operator: - minuend subtrahend -- Operator: - subtrahend The symbol `-' is used to denote either the binary infix operator subtraction or the unary minus. e1 : -[1,2,3]; e1: [-1, -2, -3] e2 : 3-7; e2: -4 -- Operator: +/- minuend subtrahend -- Operator: -/+ minuend subtrahend -- Operator: +/- augend -- Operator: -/+ augend Jacal allows the use of `+/-' and `-/+' as ambiguous signs (unary plus-or-minus, unary minus-or-plus) and as ambiguous infix operators (binary plus-or-minus, binary minus-or-plus). The value `+/-' is also represented by the constant `%sqrt1', while `-/+' is represented by `-%sqrt1'. e7 : u:+/-3; e7: 3 %sqrt1 e8 : u^2; e8: 9 e9 : +/-(u); e9: 3 e10 : u-/+3; e10: b-/+(3 %sqrt1, 3) -- Operator: * multiplicand1 multiplicand2 Multiplication of scalar expressions such as numbers, polynomials, rational functions and algebraic functions is denoted by the infix operator `*'. For example, e1 : (2 + 3 * a) * 4 * a * b^2; 2 2 e1: (8 a + 12 a ) b One can also use `*' as an infix operator on bunches. In that case, it operates componentwise, in an appropriate sense. If the bunches are square matrices, the operator `*' multiplies corresponding entries of the two factors. It does not perform matrix multiplication. To multiply matrices one instead uses the operator `.' (i.e., a period). More generally, any binary scalar operator other than `^' can be used on bunches and acts componentwise. -- Operator: / dividend divisor The symbol for division in Jacal is `/'. For example, the value returned by `6 / 2' is `3'. e3 : (x^2 - y^2) / (x - y); e3: x + y -- Operator: ^ expression exponent The infix operator `^' is used for exponentiation of scalar quantitites or for componentwise exponentiation of bunches. For example, `2^5' returns 32. Unlike the other scalar infix operators, one cannot use `^' for component-wise operations on bunches. Furthermore, one should not try to use `^' to raise a square matrix to a power. Instead, one should use `^^'. e7 : (1+x)^4; 2 3 4 e7: 1 + 4 x + 6 x + 4 x + x -- Operator: = expression1 expression2 In Jacal, the equals sign `=' is _not_ used for conditionals and it is _not_ used for assignments. To assign one value to another, use either `:' or `:='. The operator `=' merely returns a value of the form `0 = EXPRESSION'. The value returned by `a = b', for example is `0 = a - b'. e6 : 1=2; e6: 0 = -1 -- Operator: || Z1 Z2 The infix operator `||' is from electrical engineering and represents the effective impedance of the parallel connection of components of impedances Z1 and Z2: e1 : Z1 || Z2; Z1 Z2 e1: ------- Z1 + Z2  File: jacal.info, Node: Algebraic Commands, Next: Rational Expression, Prev: Algebraic Operators, Up: Algebra 2.2 Algebraic Commands ====================== -- Command: eliminate [eqn_1 eqn_2 ...] [var_1 var_2 ...] Here EQN_I is an equation for I = 1 ... N and where VAR_J is a variable for J = 1 ... M. `eliminate' returns a list of equations obtained by eliminating the variables VAR_1, ..., VAR_M from the equations EQN_1, ..., EQN_N. e39 : eliminate([x^2+y=0,x^3+y=0],[x]); 2 e39: 0 = - y - y e40 : eliminate([x+y+z=3,x^2+y^2+z^2=3,x^3+y^3+z^3=3],[x,y]); e40: 0 = 1 - z -- Command: suchthat var eqn The equation EQN must contain an occurence of variable VAR. `suchthat' returns an expression for all complex values of VAR satisfying EQN. `suchthat' is useful for extracting an expression from an equation. e0 : a*x+b*y+c = 0; e0: 0 = c + a x + b y e1 : suchthat(x, e0); - c - b y e1: --------- a -- Command: suchthat var exp If an expression rather than an equation is given to `suchthat', it is as though the equation `EXP=0' was given. e2 : suchthat(x, e0); - c - b y e2: --------- a -- Operator: | var exp_or_eqn An alternative infix notation is also available for `suchthat'. When used in combination with the `{ }' notation for `or', the set notation used by some textbooks results. If VAR in EQN has multiple roots, a named "field extension" will be introduced to represent any one of those roots. When multiple values are returned, the result (in `disp2d' and `standard' grammars) is wrapped with `{ }'. e3 : x | a*x^2 + b*x + c; 2 ext3: {:@ | 0 = c + b :@ + a :@ } e3: ext3 e4 : e3 ^ 2; - c - b ext3 e4: ------------ a -- Command: extrule extsym Returns the rule defining named field extension EXTSYM. e5 : extrule(ext3); 2 e5: 0 = c + b ext3 + a ext3 -- Command: or expr_1 ... -- Command: or eqn_1 ... The function `or' takes as inputs one or more equations or values. If the inputs are equations, then `or' returns an equation which is equivalent to the assertion that at least one of the input equations holds. If the inputs to `or' are values instead of two equations, then the function `or' returns a multiple value. If the inputs to `or' consist of both equations and values, then `or' will return the multiple values. e1 : or(x=2,y=3); e1: 0 = -6 + 3 x + (2 - x) y e2 : or(2,3); 2 e2: {:@ | 0 = -6 + 5 :@ - :@ } e3 : e2^2; 2 e3: {:@ | 0 = -36 + 13 :@ - :@ } e4 : or(x=2,17); e4: 17 `{EQN, ... }' can be used as an alternate syntax for `or': e5 : {+1, -1}; 2 e5: {:@ | 0 = -1 + :@ }  File: jacal.info, Node: Rational Expression, Next: Polynomials, Prev: Algebraic Commands, Up: Algebra 2.3 Rational Expression ======================= -- Command: num expr The function `num' takes a rational expression as input and returns a numerator of the expression. e25 : num((x^2+y^2)/(x^2-y^2)); 2 2 e25: - x - y e26 : num(7/4); e26: 7 e27 : num(7/(4/3)); e27: 21 -- Operator: denom rational-expression The Jacal command `denom' is used to obtain the denominator of a rational expression. e26 : denom(4/5); e26: 5 -- Command: listofvars expr The command `listofvars' takes as input a rational expression and returns a list of the variables that occur in that expression. e7 : listofvars(x^2+y^3); e7: [x, y] e8 : listofvars((x^2+y^3)/(2*x^7+y*x+z)); e8: [z, x, y] -- Command: imagpart z Returns the coefficient of `%i' in expression Z; -- Command: realpart z Returns all but the coefficient of `%i' in expression Z; -- Command: abs z -- Command: cabs z `| Z |' Returns the square root of the sum of the squares of the `realpart' and the `imagpart' of Z.  File: jacal.info, Node: Polynomials, Next: Factoring, Prev: Rational Expression, Up: Algebra 2.4 Polynomials =============== -- Operator: degree poly var Returns the degree of polynomial or equation POLY in variable VAR. -- Operator: degree poly Returns the total-degree, the degree of its highest degree monomial, of polynomial or equation POLY. e26 : degree(a*x*x + b*y*x + c*y*y + d*x + e*y + f, y); e26: 2 e27 : degree(a*x*x + b*y*x + c*y*y + d*x + e*y + f); e27: 3 -- Operator: coeff poly var -- Operator: coeff poly var deg -- Operator: coeffs poly var The command `coeff' is used to determine the coefficient of a certain power of a variable in a given polynomial. Here POLY is a polynomial and VAR is a variable. If the optional third argument is omitted, then Jacal returns the coefficient of the variable VAR in POLY. Otherwise it returns the coefficient of VAR^DEG in POLY. The function `coeffs' returns a list of all of the coefficients. For example, e14 : coeff((x + 2)^4, x, 3); e14: 8 e15 : (x + 2)^4; 2 3 4 e15: 16 + 32 x + 24 x + 8 x + x e16 : coeff((x + 2)^4, x); e16: 32 e18 : coeffs((x + 2)^4, x); e18: [16, 32, 24, 8, 1] -- Operator: poly var vect -- Operator: poly var coeff1 ... The function `poly' provides an inverse to the function `coeffs', allowing one to recover a polynomial from its vector or list of coefficients. e15 : poly(y, [16, 32, 24, 8, 1]); 2 3 4 e15: 16 + 32 y + 24 y + 8 y + y e16 : poly(y, 16, 32, 24, 8, 1); 2 3 4 e16: 16 + 32 y + 24 y + 8 y + y -- Operator: poly eqn The function `poly' returns the expression equal to 0 in equation EQN. Be aware that the sign and scaling of the returned polynomial will not necessarily match those in the equation creating EQN. e17 : 2*a = 4*c; e17: 0 = - a + 2 c e18 : poly(e17); e18: - a + 2 c -- Operator: content poly var Returns a list of content and primitive part of a polynomial with respect to the variable. The content is the GCD of the coefficients of the polynomial in the variable. The primitive part is POLY divided by the content. e24 : content(2*x*y+4*x^2*y^2,y); 2 e24: [2 x, y + 2 x y ] -- Operator: divide dividend divisor var -- Operator: divide dividend divisor The command `divide' treats DIVIDENT and DIVISOR as polynomials in the variable VAR and returns a pair `[QUOTIENT, REMAINDER]' such that `DIVIDEND = DIVISOR * QUOTIENT + REMAINDER'. If the third argument VAR is omitted Jacal will choose a variable on its own with respect to which it will do the division. In particular, of DIVIDEND and DIVISOR are both numerical, one can safely omit the third argument. e5 : divide(x^2+y^2,x-7*y^2,x); 2 2 4 e5: [x + 7 y , y + 49 y ] e6 : divide(-7,3); e6: [-2, -1] e11 : divide(x^2+y^2+z^2,x+y+z); 2 2 e11: [- x - y + z, 2 x + 2 x y + 2 y ] e14 : divide(x^2+y^2+z^2,x+y+z,y); 2 2 e14: [- x + y - z, 2 x + 2 x z + 2 z ] e15 : divide(x^2+y^2+z^2,x+y+z,z); 2 2 e15: [- x - y + z, 2 x + 2 x y + 2 y ] -- Command: mod poly1 eqn var -- Command: mod poly1 poly2 var -- Command: mod poly1 poly2 Returns POLY1 reduced with respect to POLY2 (or EQN) and VAR. If POLY2 is univariate, the third argument is not needed. -- Command: mod poly1 n Returns POLY1 with all the coefficients taken modulo N. -- Command: mod poly1 Returns POLY1 with all the coefficients taken modulo the current modulus. If the modulus (N or the current modulus) is negative, then the results use symmetric representation. e19 : x^4+4 mod 3; 4 e19: 1 + x e20 : x^4+4 mod x^2=2; e20: 8 e22 : mod(x^3*a*7+x*8+34, -3); 3 e22: 1 - x + a x e23 : mod(5,2); e23: 1 e24 : mod(x^4+4,x^2=2,x); e24: 8 -- Command: gcd poly_1 poly_2 The Jacal function `gcd' takes as arguments two polynomials with integer coefficients and returns a greatest common divisor of the two polynomials. This includes the case where the polynomials are integers. e1 : gcd(x^4-y^4,x^6+y^6); 2 2 e1: x + y e2 : gcd(4,10); e2: 2 -- Command: discriminant poly var Here POLY is a polynomial and VAR is a variable. This function returns the square of the product of the differences of the roots of the polynomial POLY with respect to the variable VAR. e7 : discriminant(x^3 - 1, x); e7: -27 -- Command: resultant poly_1 poly_2 var The function `resultant' returns the resultant of the polynomials POLY_1 and POLY_2 with respect to the variable VAR. e2 : resultant(x^2 + a, x^3 + a, x); 2 3 e2: a + a -- Command: equatecoeffs z1 z2 var Returns the list of equations formed by equating each coefficient of variable VAR^n in Z1 to the corresponding coefficient of VAR^n in Z2. Z1 and Z2 can be polynomials or ratios of polynomials.  File: jacal.info, Node: Factoring, Prev: Polynomials, Up: Algebra 2.5 Factoring ============= -- Command: factor int The Jacal command `factor' takes as input an integer and returns a list of the prime numbers that divide it, each occurring with the appropriate multiplicity in the list. If the number is negative, the list will begin with -1. The results of the `factor' command are shown in a special "factored" format, which appears as the product of the factors. e0 : factor(120); 3 e0: 2 3 5 e1 : factor(-120); 3 e1: -1 2 3 5 -- Command: factor polyratio Given a univariate ratio of polynomials POLYRATIO, returns a matrix of factors and exponents. As above, the results are shown in factored form. e2 : factor((14*x^4-10/68*x^-5)/(5*x^2+1)); 9 -5 + 476 x e2: ------------------ 2 5 2 17 (1 + 5 x ) x e3 : (14*x^4-10/68*x^-5)/(5*x^2+1); 9 -5 + 476 x e3: -------------- 5 7 34 x + 170 x e4 : (476*x^9-5)/(34*(5*x^2+1)*x^5); 9 -5 + 476 x e4: -------------- 5 7 34 x + 170 x e5 : factor(x*y); e5: y x e6 : factor((x+a)*(y^4-z)); 4 e6: -1 (a + x) (- y + z) e7 : factor((x+u*a^3)*(y^4-z)); 3 4 e7: -1 (a u + x) (- y + z) e8 : factor((x+u*a^3)^2*(y^4-z)/((x+1)*(u^2-v^2))); 4 3 2 (- y + z) (a u + x) e8: ------------------------- (1 + x) (- u + v) (u + v) e9 : factor(200*(-1*x+1+y)*(u-r^6)*(21*x+2-t^4)); 3 2 6 4 e9: 2 5 (- r + u) (1 - x + y) (2 - t + 21 x) e10 : factor(2*(a+u)*(-v+b)*(a*x+y)^2); 2 e10: -1 2 (a + u) (- b + v) (a x + y) e11 : factor(2*(a+u)*(-v+b)*(a*x+y)^2/((u^2-v^2)*(11*x+55))); 2 2 (a + u) (- b + v) (a x + y) e11: ------------------------------ 11 (5 + x) (- u + v) (u + v) e12 : factor(2*(a+u)*(-v+b)*(a*x+y)^2/((u^2-v^2)*x^4*(11*x+55))); 2 2 (a + u) (- b + v) (a x + y) e12: ------------------------------- 4 11 (5 + x) (- u + v) (u + v) x e13 : factor((c^3*u+b*a)*(b*b*a+v*p^2*q^2*c)); 3 2 2 2 e13: (a b + c u) (a b + c p q v) e14 : factor((2*z+y-x)*(y^3-a*x^2)*(b*z^2+y)); 2 2 3 e14: (- x + y + 2 z) (y + b z ) (- a x + y ) e15 : factor((a*a*b*z+d)*(2*a*b*b*z+c)); 2 2 e15: (d + a b z) (c + 2 a b z) e16 : factor((a*a*b*z+d)*(2*a*b*b*z+c)*((u+a)*x+1)); 2 2 e16: (1 + (a + u) x) (d + a b z) (c + 2 a b z) e17 : factor((c*z+a)*(a*z+b)*(b*z+c)); e17: (b + a z) (c + b z) (a + c z) e18 : factor((a*a*b*(x+w)*z+d)*(2*a*b*b*z+c)); 2 2 2 e18: (d + (a b w + a b x) z) (c + 2 a b z) e19 : factor(((x+w)^2*z-u*d)*(-2*a*b*z+c)); 2 2 e19: -1 (- c + 2 a b z) (- d u + (w + 2 w x + x ) z) e20 : factor((-200*%i*x-c)*(x-d-z^5)/(a*(b^3-(a+u)*z))); 5 -1 (c + 200 %i x) (d - x + z ) e20: ------------------------------ 3 a (- b + (a + u) z) The rest of this section documents commands from the factoring package. To use this package, execute the following command from the JACAL prompt: `require("ff");' Several of these commands return a matrix. The first column contains the factors and the second column contains the corresponding exponent. -- Command: sff poly Given a primitive univariate polynomial POLY, calculate the square free factorisation of POLY. A "primitive" polynomial is one with no factors (other than units) common to all its coefficients. -- Command: ffsff poly p -- Command: ffsff poly p m Given a monic polynomial POLY, a prime P, and a positive integer M, calculate the square free factorisation of POLY in GF(p^m)[x]. If M is not supplied, `1' is assumed. e0 : ffsff(x^5+x^3+1, 53); [ 2 3 ] [16 - 22 x + 26 x + x 1] e0: [ ] [ -13 + x 2] -- Command: berl poly n Given a square-free univariate polynomial POLY and an integer power of a prime, Q, returns (as a bunch) the irreducible factors of POLY. e2 : berl(x^5+x^3+2, 53); 2 2 e2: [1 + x, 5 - 26 x + x , 11 + 25 x + x ] -- Command: parfrac polyratio Returns the partial fraction expansion of a rational univariate polynomial POLYRATIO. The denominator of POLYRATIO must be square free. This code is still being developed.  File: jacal.info, Node: Calculus, Next: Matrices and Tensors, Prev: Algebra, Up: Top 3 Calculus ********** 3.1 Differential Operator ========================= -- Operator: differential expr -- Operator: ' expr The Jacal command `differential' computes the derivative of the expression EXPR with respect to a generic derivation. It is generic in the sense that nothing is assumed about its effect on the individual variables. The derivation is denoted by a right quote. e6 : differential(x^2+y^3); 2 e6: 2 x x' + 3 y y' e7 : (x^2+y^3)'; 2 e7: 2 x x' + 3 y y' 3.2 Derivative Commands ======================= -- Command: diff expr var1 ... The Jacal command `diff' computes the derivative of the expression EXPR with respect to VAR1, .... e6 : diff(x^2+y^3,y); 2 e6: 3 y -- Command: partial expr var1 ... The Jacal command `partial' computes the partial derivative of the expression EXPR with respect to VAR1, .... e6 : partial(x^2+@1^3,1); 2 e6: 3 @1 -- Command: PolyDiff poly var1 ... The Jacal command `PolyDiff' computes the derivative of the expression POLY with respect to VAR1, .... It is faster than `diff' but POLY must be a polynomial.  File: jacal.info, Node: Matrices and Tensors, Next: Lambda Calculus, Prev: Calculus, Up: Top 4 Matrices and Tensors ********************** In JACAL, a matrix is just a `bunch' of equal length `bunch's, and this is the structure that the matrix operations currently supported by JACAL (ncmult(), ^^, transpose(), etc.) expect. * Menu: * Generating Matrices:: * Matrix Parts:: * Matrix commands:: * Tensors:: * tmult:: Tensor Multiplication * contract:: Tensor Contraction * indexshift:: Shift an index within a tensor * indexswap:: Swaps two indices within a tensor  File: jacal.info, Node: Generating Matrices, Next: Matrix Parts, Prev: Matrices and Tensors, Up: Matrices and Tensors 4.1 Generating Matrices ======================= -- Operator: bunch elt_1 elt_2 ... `[ELT_1, ELT_2, ...]' To collect any number of Jacal objects into a bunch, simply enclose them in square brackets. For example, to make the bunch whose elements are `1', `2', `4', type `[1, 2, 4]'. One can also nest bunches, for example, `[1, [[1, 3], [2, 5]], [1, 4]]'. Note however that the bunch whose only element is `[1, 2, 3]' is `[1 2 3]'. It is importance to notice that one has commas and the other doesn't. e3 : a:bunch(1, 2, 3); e3: [1, 2, 3] e4 : b:[a]; e4: [1 2 3] e5 : c:[b]; e5: [[1, 2, 3]] e6 : [[[1, 2, 3]]]; e6: [[1, 2, 3]] -- Operator: flatten bnch Removes bunch nesting from BNCH, returning a single bunch of the constituent expressions and equations. e0 : flatten([a, [b, [c, d]], [5]]); e0: [a, b, c, d, 5] -- Command: ident n The command `ident' takes as argument a positive integer N and returns an NxN identity matrix. This is sometimes more convenient than obtaining this same matrix using the command `scalarmatrix'. e6 : ident(4); [1 0 0 0] [ ] [0 1 0 0] e6: [ ] [0 0 1 0] [ ] [0 0 0 1] -- Command: scalarmatrix size entry The command `scalarmatrix' takes as inputs a positive integer SIZE and an algebraic expression ENTRY and returns an `N * N' diagonal matrix whose diagonal entries are all equal to ENTRY, where `N = SIZE'. e1 : scalarmatrix(3, 6); [6 0 0] [ ] e1: [0 6 0] [ ] [0 0 6] -- Command: diagmatrix list The Jacal command `diagmatrix' takes as input a list of objects and returns the diagonal matrix having those objects as diagonal entries. In case one wants all of the diagonal entries to be equal, it is more convenient to use the command `scalarmatrix'. e3 : diagmatrix(12,3,a,s^2); [12 0 0 0 ] [ ] [0 3 0 0 ] e3: [ ] [0 0 a 0 ] [ ] [0 0 0 2] [ s ] e4 : diagmatrix([1,2],2); [[1, 2] 0] e4: [ ] [ 0 2] -- Command: sylvester poly_1 poly_2 var Here, POLY_1 and POLY_2 are polynomials and VAR is a variable. The function `sylvester' returns the matrix introduced by Sylvester (`A Method of Determining By Mere Inspection the Derivatives from Two Equations of Any Degree, Phil.Mag. `16' (1840) pp. 132-135, Mathematical Papers, vol. I, pp. 54-57') for computing the resultant of the two polynomials POLY_1 and POLY_2 with respect to the variable VAR. If one wants to compute the resultant itself, one can simply use the command `resultant' with the same syntax. e5 : sylvester(a0 + a1*x + a2*x^2 + a3*x^3, b0 + b1*x + b2*x^2, x); [a3 a2 a1 a0 0 ] [ ] [0 a3 a2 a1 a0] [ ] e5: [b2 b1 b0 0 0 ] [ ] [0 b2 b1 b0 0 ] [ ] [0 0 b2 b1 b0] -- Command: genmatrix function rows cols The function `genmatrix' takes as arguments a FUNCTION of two variables and two positive integers, ROWS and COLS. It returns a matrix with the indicated numbers of rows and columns in which the $(i,j)$th entry is obtained by evaluating FUNCTION at $(i,j)$. The function may be defined in any of the ways available in Jacal, i.e previously by an explicit algebraic definition, by an explicit lambda expression or by an implicit lambda expression. e4 : @1^2+@2^2; 2 2 e4: lambda([@1, @2], @1 + @2 ) e5 : genmatrix(e4,3,5); [2 5 10 17 26] [ ] e5: [5 8 13 20 29] [ ] [10 13 18 25 34]  File: jacal.info, Node: Matrix Parts, Next: Matrix commands, Prev: Generating Matrices, Up: Matrices and Tensors 4.2 Matrix Parts ================ -- Command: row matrix i The command `row' returns the Ith row of the matrix MATRIX, where `i = INT'. If INT is larger than the number of rows of MATRIX, then Jacal prints an error message. The corresponding command for columns of a matrix is `col'. e3 : u:[[1, 2, 3], [1, 5, 3]]; [1 2 3] e3: [ ] [1 5 3] e4 : row(u, 2); e4: [1, 5, 3] -- Command: col matrix integer The command `col' is used to extract a column of a matrix. Here, MATRIX is a matrix and INTEGER is a positive integer. If that integer exceeds the number of columns, an error message such as ERROR: list-ref: Wrong type in arg1 () appears. Here is an example of correct use of the command `col': e19 : a:[[1,2,4],[2,5,6]]; [1 2 4] e19: [ ] [2 5 6] e20 : col(a,2); [2] e20: [ ] [5] -- Command: minor matrix i j The command `minor' returns the submatrix of MATRIX obtained by deleting the Ith row and the Jth column. e21 : b:[[1,2,3],[3,1,5],[5,2,7]]; [1 2 3] [ ] e21: [3 1 5] [ ] [5 2 7] e22 : minor(b,3,1); [2 3] e22: [ ] [1 5] -- Command: cofactor matrix i j The command `cofactor' returns the determinant of the I, J `minor' of MATRIX. -- Command: rapply bunch int_1 int_2 ... The function `rapply' is used to access elements of bunches. It can also access elements nested at lower levels in a bunch. In particular, it can also access matrix elements. In the above syntax, BUNCH is the bunch whose parts one wishes to access, and N, INT_1, INT_2, ..., INT_N are positive integers. It returns the INT_N-th element of the INT_{N-1}-th element of ... of the INT_2-th element of the INT_1-th element of BUNCH. One can have `n = 0'. In that case, `rapply' simply returns the bunch. e2 : rapply([[1,2,3],[1,4,6],3],2,3); e2: 6 e6 : rapply([a,b],2); e6: b e7 : rapply([a,b]); e7: [a, b]  File: jacal.info, Node: Matrix commands, Next: Tensors, Prev: Matrix Parts, Up: Matrices and Tensors 4.3 Matrix commands =================== -- Command: . matrix1 matrix2 Matrix multiplication. e1 : a:[[1, 2, 3], [5, 2, 7]]; [1 2 3] e1: [ ] [5 2 7] e2 : b:[[3, 2], [6, 4]]; [3 2] e2: [ ] [6 4] e3 : b . a; [13 10 23] e3: [ ] [26 20 46] -- Command: ^^ matrix exponent The infix operator `^^' is used for raising a square matrix to an integral power. e8 : a:[[1, 0], [-1, 1]]; [1 0] e8: [ ] [-1 1] e9 : a^^3; [1 0] e9: [ ] [-3 1] Negative exponents raise the inverse matrix to a power. e8 : [[a, b], [c, d]]; [a b] e8: [ ] [c d] e9 : e8^^-1; [ d - b ] [----------- -----------] [- b c + a d - b c + a d] [ ] e9: [ - c a ] [----------- -----------] [- b c + a d - b c + a d] e10 : e8^^-2; [ 2 - a b - b d ] [ b c + d -------------------------] [------------------------- 2 2 2 2] [ 2 2 2 2 b c - 2 a b c d + a d ] [b c - 2 a b c d + a d ] [ 2 ] e10: [ - a c - c d a + b c ] [------------------------- -------------------------] [ 2 2 2 2 2 2 2 2] [b c - 2 a b c d + a d b c - 2 a b c d + a d ] e11 : e8 . e9; [1 0] e11: [ ] [0 1] e12 : e9 . e8; [1 0] e12: [ ] [0 1] e13 : e10 . e8 . e8; [1 0] e13: [ ] [0 1] -- Command: dotproduct vector_1 vector_2 The Jacal function `dotproduct' returns the dot product of two row vectors of the same length. It will also give the dot product of two matrices of the same size by computing the sum of the dot products of the corresponding rows or, what is the same, the trace of one matrix times the transpose of the other one. e28 : a:[1,2,3]; b:[3,1,5]; e28: [1, 2, 3] e29 : e29: [3, 1, 5] e30 : dotproduct(a,b); e30: 20 -- Command: crossproduct vector_1 vector_2 The Jacal command `crossproduct' computes the cross product of two vectors. By definition, the two vectors must each have three components. e24: [2 x, y + 2 x y ] e25 : crossproduct([1,2,3],[4,2,5]); e25: [4, 7, -6] -- Command: determinant matrix The Jacal command `determinant' computes the determinant of a square matrix. Attempting to take the determinant of a non-square matrix will produce an error message. e1 : a:[[1,2],[6,7]]; [1 2] e1: [ ] [6 7] e2 : determinant(a); e2: -5 -- Command: transpose matrix Computes the transpose of `(MATRIX)'.  File: jacal.info, Node: Tensors, Next: tmult, Prev: Matrix commands, Up: Matrices and Tensors 4.4 Tensors =========== The `tensors' supported by JACAL are an extension of the matrix structure (i.e., a bunch of bunches of bunches ...) with the added stipulation that all `dimensions' of the tensor be the same length (e.g., 4x4x4). The number of dimensions (indices) in a tensor is its rank: A scalar is a tensor of rank 0; a vector is a rank 1 tensor; a matrix has rank 2; and so on. Further, just as matrix binary operations place restrictions on the matrices involved (e.g., the row/column length requirement for matrix multiplication), the tensor binary operations require that the dimensions of each tensor be of the same length. For example, you could not multiply a 3x3 tensor and a 4x4x4 tensor. JACAL's tensors do not support the construct of contravariant and covariant indices. Users must keep track of this information themselves, and perform the necessary operations with an appropriate metric so that the "index gymnastics" is performed correctly. Before using any of JACAL's tensor operations, execute the following command from the JACAL prompt: require("tensor"); This loads the file `tensor.scm' into JACAL, and makes the tensor operations available for use. JACAL currently supports four tensor operations: `tmult', `contract', `indexshift', and `indexswap'. Each of these is described in detail below.  File: jacal.info, Node: tmult, Next: contract, Prev: Tensors, Up: Matrices and Tensors 4.5 Tensor Multiplication ========================= -- Command: tmult matrix_1 matrix_2 index_1 index_2 `tmult' takes a minimum of two arguments which are the tensors on which the multiplication operation is to be performed. With no additional arguments, `tmult' will produce the outer product of the two input tensors. The rank of the resulting tensor is the sum of the inputs' ranks, and the components of the result are formed from the pair-wise products of components of the inputs. For example, for the input tensors `x[a,b]' and `y[c]' z:tmult(x,y);=> z[a,b,c] = x[a,b]*y[c] With an additional argument, `tmult' will produce the inner product of the two tensors on the specified index. For example, given `x[i,j]' and `y[k,l,m]' z:tmult(x,y,3); => length ----- \ z[a,b,c] = > x[a,q] * y[b,c,q] / ----- q = 1 Note that in this case X only has 2 indices. All of JACAL's tensor operations modify index inputs to be between 1 and the rank of the tensor. Thus, in this example, the 3 is modified to 2 in the case of X. As another example, with `x[i,j,k]' and `y[l,m,n]' z:tmult(x,y,2); => length ----- \ z[a,b,c,d] = > x[a,q,b] * y[c,q,d] / ----- q = 1 With four arguments, `tmult' produces an inner product of the two tensors on the specified indices. For example, for `x[i,j]' and `y[k,l,m]' z:tmult(x,y,1,3); => length ----- \ z[a,b,c] = > x[q,a] * y[b,c,q] / ----- q = 1 Note that matrix multiplication is the special case of an inner product (of two "two dimensional matrices") on the second and first indices, respectively: `tmult(x,y,2,1) == ncmult(x,y)' Finally, tmult handles the case of a scalar times a tensor, in which case each component of the tensor is multiplied by the scalar.  File: jacal.info, Node: contract, Next: indexshift, Prev: tmult, Up: Matrices and Tensors 4.6 Tensor contraction ====================== -- Command: contract matrix index1 ... The contraction operation produces a tensor of rank two less than a given tensor. It does this by performing a summation over two of the indices of the given tensor, as clarified in the examples below. `contract' takes at least one argument which is the tensor on which the contraction operation is to be performed. One or two additional arguments may be provided to specify the indices to be used in the summation. If no additional arguments are provided, the summation is performed over the first and second indices. With one additional argument, the summation is over the specified index and the one following it (e.g., if 3 is specified, the third and fourth indices are used). With two additional arguments, the summation is performed over the indices specified. The actual indices used will be constrained to be between 1 and the rank of the tensor. Examples: 1) For a square matrix (tensor of rank 2), `contract' returns a scalar that is the sum of the diagonal elements of the matrix. 2) Given `x[i,j,k,l]', the command y:contract(x,2,4); produces: length ----- \ y[a,b] = > x[a,q,b,q] / ----- q = 1 Special cases: If `contract' is given a scalar (rank 0 tensor) as input, it just returns the scalar. For a vector (tensor of rank 1), `contract' returns a scalar that is the sum of the elements of the vector.  File: jacal.info, Node: indexshift, Next: indexswap, Prev: contract, Up: Matrices and Tensors 4.7 Shifting of Tensor Indices ============================== -- Command: indexshift matrix index1 ... `indexshift' rearranges the indices of a tensor. It is one of two generalizations of the matrix transpose operation (cf. `indexswap'). `indexshift' takes at least one argument which is the tensor on which the index shifting is to be performed. One or two additional arguments may be provided to specify the index and the position to which it is to be shifted. If no additional arguments are provided, the first index of the tensor is shifted to the second position (equivalent the matrix transpose operation). If one additional argument is provided, it specifies the index to be shifted, and that index will be shifted "to the right" one position (e.g., if 3 is specified, the third index will be shifted to the forth position). If two additional arguments are provided, the first specifies the index and the second specifies the position to which it is to be shifted. The actual index shifted and its shifted position will be constrained to be between 1 and the rank of the tensor. For example, given `x[a,b,c,d]', the command `y:indexshift(x,1,3);' produces a tensor Y such that `y[a,b,c,d] == x[b,c,a,d]'. In this example, the element that was in position `[a,b,c,d]' in X will be in position `[b,c,a,d]' in Y. Special cases: If `indexshift' is given a scalar (rank 0 tensor) as input, it just returns the scalar. For a vector (tensor of rank 1), `indexshift' transposes the 1-by-n matrix (row vector) to an n-by-1 matrix (column vector).  File: jacal.info, Node: indexswap, Prev: indexshift, Up: Matrices and Tensors 4.8 Swapping of Tensor Indices ============================== -- Command: indexswap tensor ... `indexswap' rearranges the indices of a tensor. It is one of two generalizations of the matrix transpose operation (cf. `indexshift'). `indexswap' takes at least one argument which is the tensor on which index swapping is to be performed. One or two additional arguments may be provided to specify the indices to be swapped. If no additional arguments are provided, the first and second indices of the tensor are swapped (equivalent the matrix transpose operation). With one additional argument, the specified index is swapped with the one following it (e.g., if 2 is specified, the second and third indices will be swapped). If two additional arguments are provided, they specify the indices to be swapped. The actual indices used will be constrained to be between 1 and the rank of the tensor. For example, given x[a,b,c,d], the command `y:indexswap(x,2,4);' produces a tensor Y such that y[a,b,c,d] = x[a,d,c,b]. In this example, the element that was in position [a,b,c,d] in X will be in position [a,d,c,b] in Y. Special cases: If `indexswap' is given a scalar (rank 0 tensor) as input, it just returns the scalar. For a vector (tensor of rank 1), `indexswap' transposes the 1-by-n matrix (row vector) to an n-by-1 matrix (column vector).  File: jacal.info, Node: Lambda Calculus, Next: Miscellaneous, Prev: Matrices and Tensors, Up: Top 5 Lambda Calculus ***************** 5.1 Create a lambda expression ============================== -- Operator: lambda varlist expression Jacal has the ability to work with lambda expressions, via the command `lambda'. Furthermore, Jacal always converts user definitions of functions by any method into lambda expressions and converts the dummy variables of the function definition into symbols such as 1, 2, .... Jacal can manipulate lambda expressions by manipulating their function parts, as in `e14' below. Jacal can also invert a function using the command `finv'. e12 : lambda([x],x^2); 2 e12: lambda([@1], @1 ) e13 : lambda([x,y,z],x*y*z); e13: lambda([@1, @2, @3], @1 @2 @3) e14 : e12+e13; 2 e14: lambda([@1, @2, @3], @1 + @1 @2 @3) 5.2 Compute inverse function ============================ -- Command: finv function `FUNCTION^^-1' The command `finv' takes as input a function of one variable and returns the inverse of that function. The function may be defined in any of the ways permitted in Jacal, i.e. by an explicit algebraic definition, by an explicit lambda expression or by an implicit lamba expression. If F is the function, then typing `f^^-1' has the same effect as typing `finv(F)'. e0 : w(t):=t+1; w(t): lambda([@1], 1 + @1) e0 : finv(w); e0: lambda([@1], -1 + @1)  File: jacal.info, Node: Miscellaneous, Next: Flags, Prev: Lambda Calculus, Up: Top 6 Miscellaneous *************** -- Command: % The symbol `%' represents the last expression obtained by Jacal. It can be used in formulas like any other constant or variable or expression. e21: 5 e22 : %; e22: 5 e23 : %^2; e23: 25 -- Command: batch filename The command `batch' is used to read in a file containing programs written in Jacal. Here, FILENAME is a string in double quotes. The precise way in which one refers to a file is, of course, system dependent. batch("demo"); of the file demo in the JACAL directory will give a demonstration of JACAL's capabilities. -- Command: commands The command `commands' produces a list of all of the command available in Jacal. It is called as s function of no arguments. Explicitly: e21 : commands(); u-/+ u+/- transpose transcript differential terms system sylvester show set scalarmatrix row resultant rapply quit qed discriminant poly or num negate mod minor matrix load listofvars ident genmatrix gcd finv factor example eliminate dotproduct divide diff diagmatrix determinant describe denom crossproduct content commands col coeffs coeff bunch batch b+/- ^^ ^ = / - + * % -- Command: describe command The command `describe' is the heart of the online help facility of Jacal. Here, COMMAND is a string which is the name of a command and `describe' produces a brief description of the command and in many cases includes an example of its use. Together with the command `commands()', which prints a list of all available Jacal commands, and the command `example', which gives an example of the use of the command, one can in principle use Jacal without a manual after one has learned how to get started. e27 : describe(col); column. column of a matrix e27 : describe(resultant); resultant. The result of eliminating a variable between 2 equations (or polynomials). 27 : describe(+); Addition, plus. a + b -- Command: example command Here, COMMAND is a string which is the name of a Jacal command. `example' gives an example of the use of the command. See also *Note describe: Miscellaneous. e43 : example(+); a + b e43: a + b -- Command: load string The Jacal command `load' takes as input a string and reads in a `Scheme' file whose name is obtained by appending the extension `.scm' to the string. If you want to read in a file of Jacal commands, do not use `load'. Instead use the command `batch'. To load in the file `foo.scm', e9 : load("foo"); e9: foo -- Command: qed Exit from Jacal to Scheme. With interactive Scheme systems (such as SCM), It does not return you to the operating system. Instead it suspends Jacal and returns you to the underlying scheme. You can return to the Jacal session where you left off by simply typing `(math)'. If you do not wish to return to Jacal but really want to terminate the session and return to the operating system, then after typing `qed();', type `(slib:exit)' or use `quit'. -- Command: quit Exit directly from Jacal to the operating system. You will not be able to continue your Jacal session. type qed(); to return to scheme e1 : qed(); scheme > (math) type qed(); to return to scheme e2 : quit(); unix> -- Command: system command One can issue commands to the operating system without leaving Jacal. To do this, one uses the command `system'. For example, in a UNIX operating system, the command `system("ls");' will print the directory. One way in which the command `system' might be especially useful is to edit files containing Jacal scripts without leaving Jacal, particularly in non-UNIX machines or on machines without GNU emacs. e0 : system("echo hi there"); hi there e0: 0 -- Command: terms Prints a copy of the GNU General Public License e1 : terms(); GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 | Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [ rest deleted for brevity] -- Command: transcript string The command `transcript' allows one to record a Jacal session. It is called with the syntax `transcript(STRING);', where STRING is the name of the file in which one wants to keep the transcript of the session. When one wishes to stop recording, one types `transcript();'. One is then free to use `transcript' again later in the session on another file. One can use it on the same file, but the file is overwritten. Presently, the command `transcript' does not echo commands to a file. e9 : a:[1,2,3]; e9: [1, 2, 3] e10 : transcript("foo"); e10: foo e11 : a; e11: [1, 2, 3] e12 : transcript(); e12 : system("cat foo"); e10: foo e11 : a; e11: [1, 2, 3] e12 : transcript(); e12: 0 -- Command: set flag value There are various flags that the Jacal user can control, namely the Jacal command line prompt, the priority for printing terms in Jacal output, the input grammar and the output grammar. For a discussion of the various grammars please *Note Flags::. The command `show' is closely related, allowing one to see what the current settings are. -- Command: show flag The command `show' enables the Jacal user to examine the current setting of various flags as well as to list the flags that can be set by the user and to display other information. To change the settings of the flags, use the command `set'. To see all the information accessible through the `show' command, type `show all'. To see the available grammars, type `show grammars'. To see the current input grammar type `show ingrammar'. To see the current output grammar, type `show outgrammar'. To see the current priority for printing expressions, type `show priority'. e1 : show all; prompt priority outgrammar ingrammar grammars all e1 : show prompt; e1: e1 e3 : show priority; :@ (differential :@) @3 @2 @1 %inftsl y x u-/+ u+/- transpose transcript differential terms t system sylvester showpriority show set scalarmatrix row resultant rapply quit qed prompt priority discriminant poly or num negate mod minor matrix load listofvars ident genmatrix gcd finv factor example eliminate e1 dotproduct divide diff diagmatrix determinant describe denom crossproduct content commands col coeffs coeff c bunch batch b-/+ b+/- b all a ^^ ^ = / - + * % %sqrt1 %i e3 : show outgrammar; e3: disp2d e4 : show ingrammar; e4: standard e5 : show grammars; e5: [disp2d, standard, schemepretty, scheme]  File: jacal.info, Node: Flags, Next: Index, Prev: Miscellaneous, Up: Top | 7 Flags ******* -- Flag: prompt string If one changes the prompt, STRING is a string of alphanumeric characters without quotes. After this command is executed, subsequent commands will cause new prompts to be obtained from STRING by incrementing it. If the prompt ends in a letter, it will be treated as a digit in base 26 and incremented. If it ends in a string of digits, that string will be treated as a number in base 10 and incremented. The remaining characters in the string will play no role in this incrementation. e1 : set prompt az9Z; e1 : a+b; az9Z: a + b az9AA : a+b; az9AA: a + b az9AB : set prompt ok99; az9AB : a+b; ok99: a + b ok100 : a+b; ok100: a + b ok101 : -- Flag: ingrammar grammar -- Flag: outgrammar grammar The following examples show how one changes the input grammar or the output grammar. e1 : a:[[[1,2,3]]]; e1: [[1, 2, 3]] e2 : set outgrammar standard; e2 : a; e2: [[[1, 2, 3]]] e3 : set outgrammar scheme; e3 : a; (define e3 #(#(#(1 2 3)))) e4 : (1+x)^5; (define e4 (+ 1 (* 5 x) (* 10 (^ x 2)) (* 10 (^ x 3)) (* 5 (^ x 4)) (^ x 5))) e6 : set ingrammar scheme; e6 : (+ e4 1); (define e6 (+ 2 (* 5 x) (* 10 (^ x 2)) (* 10 (^ x 3)) (* 5 (^ x 4)) (^ x 5))) e7 : (set ingrammar disp2d) e7 : diagmatrix(3,6); (define e7 #(#(3 0) #(0 6))) e8 : set outgrammar disp2d; e8 : e7; [3 0] e8: [ ] [0 6] e9 : set outgrammar standard; e9 : e7; e9: [[3, 0], [0, 6]] Note that in the above examples, it is possible to input and output expressions in scheme by setting the ingrammar and/or outgrammar to `scheme'. Doing so result in linear output (as with `standard grammar') as opposed to a two dimensional display (as with `disp2d'). The analogue of `disp2d' for scheme output is scheme pretty-printing. To have such output, set the output grammar to `schemepretty'. e4 : set outgrammar schemepretty; e4 : (1+x)^5; (define e4 (+ 1 (* 5 x) (* 10 (^ x 2)) (* 10 (^ x 3)) (* 5 (^ x 4)) (^ x 5))) Jacal also allows for output to be automatically typeset in TeX. This can be quite useful if one wants to use the results of one's computations in published articles. Continuing with the example of `(1+x)^5' above, we have: e5 : set outgrammar tex; e5 : e4; e5: 1 + 5 x + 10 x^{2} + 10 x^{3} + 5 x^{4} + x^{5} e6 : (1+1/x)^3/(1-1/y)^4; e6: {\left(1 + 3 x + 3 x^{2} + x^{3}\right) y^{4}}\over{x^{3} - 4 x^{3} y + 6 x^{3} y^{2} - 4 x^{3} y^{3} + x^{3} y^{4}} That looks much better when formatted by TeX in an article than the actual Jacal output in `disp2d' grammar. -- Flag: priority int The following examples show how to set the priority of printing terms. e10 : a; e10: [[[1, 2, 3]]] e11 : show priority a; ;;; not a simple variable: (((1 2 3) . ()) . ()) e12 : show priority b; e12: 128 e13 : show priority c; e13: 128 e14 : b+c; e14: b + c e15 : c+b; e15: b + c e16 : set priority b 200; e16 : b+c;  File: jacal.info, Node: Index, Prev: Flags, Up: Top | Index ***** [index] * Menu: * %: Miscellaneous. (line 7) * ': Calculus. (line 11) * *: Algebraic Operators. (line 79) * +: Algebraic Operators. (line 7) * +/-: Algebraic Operators. (line 53) * -: Algebraic Operators. (line 40) * -/+: Algebraic Operators. (line 54) * .: Matrix commands. (line 7) * /: Algebraic Operators. (line 98) * =: Algebraic Operators. (line 119) * ^: Algebraic Operators. (line 106) * ^^: Matrix commands. (line 28) * abs: Rational Expression. (line 50) * Algebra: Algebra. (line 6) * Algebraic Commands: Algebraic Commands. (line 6) * Algebraic Operators: Algebraic Operators. (line 6) * Apple: Installation. (line 42) * Authors: Authors and Bibliography. (line 6) * batch: Miscellaneous. (line 22) * berl: Factoring. (line 172) * Bibliography: Authors and Bibliography. (line 6) * bunch: Generating Matrices. (line 7) * cabs: Rational Expression. (line 51) * Calculus: Calculus. (line 6) * coeff: Polynomials. (line 22) * coeffs: Polynomials. (line 24) * cofactor: Matrix Parts. (line 62) * col: Matrix Parts. (line 23) * commands: Miscellaneous. (line 32) * Compiling Jacal: Installation. (line 54) * content: Polynomials. (line 80) * contract: contract. (line 7) * Conventions: Release Notes. (line 24) * crossproduct: Matrix commands. (line 112) * degree: Polynomials. (line 7) * Demonstrating Jacal: Running Jacal. (line 38) * denom: Rational Expression. (line 24) * describe: Miscellaneous. (line 47) * determinant: Matrix commands. (line 123) * diagmatrix: Generating Matrices. (line 71) * diff: Calculus. (line 31) * differential: Calculus. (line 10) * discriminant: Polynomials. (line 178) * divide: Polynomials. (line 91) * dotproduct: Matrix commands. (line 94) * eliminate: Algebraic Commands. (line 7) * equatecoeffs: Polynomials. (line 196) * example: Miscellaneous. (line 66) * extrule: Algebraic Commands. (line 71) * factor: Factoring. (line 7) * Factoring: Factoring. (line 6) * ffsff: Factoring. (line 159) * finv: Lambda Calculus. (line 36) * flatten: Generating Matrices. (line 34) * gcd: Polynomials. (line 163) * genmatrix: Generating Matrices. (line 117) * GNU/Linux: Installation. (line 26) * i386: Installation. (line 16) * ident: Generating Matrices. (line 42) * imagpart: Rational Expression. (line 44) * indexshift: indexshift. (line 7) * indexswap: indexswap. (line 7) * ingrammar: Flags. (line 37) * lambda: Lambda Calculus. (line 10) * listofvars: Rational Expression. (line 32) * load: Miscellaneous. (line 76) * Manifest: Release Notes. (line 41) * minor: Matrix Parts. (line 44) * mod: Polynomials. (line 125) * num: Rational Expression. (line 7) * or: Algebraic Commands. (line 79) * outgrammar: Flags. (line 38) * Overview: Overview. (line 6) * parfrac: Factoring. (line 182) * partial: Calculus. (line 40) * poly: Polynomials. (line 50) * PolyDiff: Calculus. (line 49) * Polynomials: Polynomials. (line 6) * priority: Flags. (line 116) * prompt: Flags. (line 7) * qed: Miscellaneous. (line 87) * quit: Miscellaneous. (line 96) * rapply: Matrix Parts. (line 66) * Rational Expression: Rational Expression. (line 6) * realpart: Rational Expression. (line 47) * Recovery from Errors: Running Jacal. (line 53) * Release Notes: Release Notes. (line 6) * resultant: Polynomials. (line 187) * row: Matrix Parts. (line 7) * Running Jacal: Running Jacal. (line 6) * scalarmatrix: Generating Matrices. (line 57) * Scheme: Installation. (line 6) * set: Miscellaneous. (line 168) * sff: Factoring. (line 154) * show: Miscellaneous. (line 176) * Stopping Jacal: Running Jacal. (line 63) * suchthat: Algebraic Commands. (line 22) * sylvester: Generating Matrices. (line 94) * system: Miscellaneous. (line 108) * terms: Miscellaneous. (line 122) * tmult: tmult. (line 7) * transcript: Miscellaneous. (line 133) * transpose: Matrix commands. (line 138) * Unix: Installation. (line 25) * x86: Installation. (line 46) * |: Algebraic Commands. (line 48) * ||: Algebraic Operators. (line 130)  Tag Table: Node: Top785 Node: Overview1746 Node: Authors and Bibliography3209 Node: Installation4653 Node: Running Jacal7309 Node: Release Notes9757 Node: GNU Free Documentation License12493 Node: Algebra46987 Node: Algebraic Operators47278 Node: Algebraic Commands51173 Node: Rational Expression54436 Node: Polynomials55727 Node: Factoring61521 Node: Calculus67210 Node: Matrices and Tensors68610 Node: Generating Matrices69262 Node: Matrix Parts73775 Node: Matrix commands76226 Node: Tensors79844 Node: tmult81296 Node: contract83988 Node: indexshift85864 Node: indexswap87650 Node: Lambda Calculus89196 Node: Miscellaneous90845 Node: Flags98593 Node: Index102443  End Tag Table jacal-1b9/DOC/0000755001705200017500000000000010751510041010716 5ustar tbtbjacal-1b9/DOC/algdenom0000644001705200017500000000242304741711330012436 0ustar tbtb Algorithm to Remove Radicals From Denominators Based on the denominator s(y) generate a factor which when multiplied times the ratio will remove y from the denominator s(y). Let y be defined by a polynomial p(y)=0. Let s(y) be a polynomial in y with deg(s(y)) < deg(p(y)). Psuedo-dividing p(y) by s(y), the psuedo-quotient q1(y) and the psuedo-remainder r1(y) satisfy lc^(n-m+1)*p(y) = q1(y)*s(y) + r1(y) ; deg(r1(y)) < deg(s(y)) If deg(r1(y))=0 then q1(y)*s(y) = -r1 else psuedo-divide p(y) by r1(y) lc^(n-m+1)*p(y) = q2(y)*r1(y) + r2(y) ; deg(r2(y)) < deg(r1(y)) This is repeated until deg(rk(y)) = 0. Thus q1(y)*q2(y)*...*qk(y)*s(y) = (-1)^k * rk. The product q1(y)*q2(y)*...*qk(y) is a factor which when multiplied times a ratio will remove y from the denominator s(y). Ira Gessel suggests instead using the extended Euclidean Algorithm. Given p(y) and s(y) as above, it produces polynomials a(y) and b(y) such that a(y)*p(y) + b(y)*s(y) = gcd(p(y),s(y)) = r1. Because p(y)=0 the product b(y)*s(y) = r1. If rk=0 then p(y) and s(y) have a common factor and hence we are dividing by zero. An example of this is 1/(y+2) where y is defined by y^2 - 4 = 0. If deg(s(y))=1 the first algorithm terminates after the first division; The second algorithm will require more divisions. jacal-1b9/DOC/grammar0000644001705200017500000000466205414433066012312 0ustar tbtb THE LEXER In English.scm there are the lines: (lex:def-class 70 '(#\^) #f) (lex:def-class 49 '(#\*) #f) (lex:def-class 50 '(#\/) #f) (lex:def-class 51 '(#\+ #\-) #f) (lex:def-class 20 '(#\|) #f) (lex:def-class 30 '(#\< #\> #\= #\: #\~) #f) (lex:def-class 40 '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) (lambda (l) (string->number (list->string l)))) (lex:def-class 41 '(#\A #\B #\C #\D #\E #\F #\G #\H #\I #\J #\K #\L #\M #\N #\O #\P #\Q #\R #\S #\T #\U #\V #\W #\X #\Y #\Z #\a #\b #\c #\d #\e #\f #\g #\h #\i #\j #\k #\l #\m #\n #\o #\p #\q #\r #\s #\t #\u #\v #\w #\x #\y #\z #\@ #\_ #\% #\?) #f) (lex:def-class (lambda (chr) (or (eqv? #\" chr) (eof-object? chr))) '(#\") (lambda (l) (lex:read-char) (string->symbol (list->string (cdr l))))) (lex:def-class 0 (list slib:tab slib:form-feed #\ #\newline) #f) These lines define which character can be grouped into symbols in the standard input-grammar. In the first line is only the character ^ and its class number is not 1 removed from any other. Therefore it can only group with itself. Eg. ^ ^^ ^^^ ^^^^ ... e5 : a+^^^^-c; e5: ^^^^ + a - c The line (lex:def-class 30 '(#\< #\> #\= #\: #\~) #f) says that any consecutive combination of < > = : and ~ will be grouped together. 41 is one greater than 40 so a symbol can begin with a class 41 character and continue with either class 41 or class 40 characters. 51 can have subsequent 50 characters; this gives us +/- and -/+. 50 can have subsequent 49 characters; this gives us /*. Class 0 is special (all the other numbers are arbitrary). It designates whitespace. #\" has a function rather than a class number. This function is #t when the symbol should end. The last argument to lex:def-class is the function to run on the list of characters of a symbol. If #f then a symbol is generated from the character list. INSTALLING A GRAMMAR (defgrammar 'mygrammar (make-grammar 'mygrammar (lambda (grm) (read)) ;the reader #f ;lex-tab #f ;read-tab (lambda (sexp grm) (write sexp));the writer #f)) ;write-tab The grm arguments are passed the whole grammar (a list of the args passed to make-grammar). Lex-tab is used by the lexer if you call it. The read-tab can be used by the reader if you want it. the write-tab contains the templates for the writer. You can probably use inprint for the writer (which uses templates like those at the beginning of English.scm). jacal-1b9/DOC/eqalign.sty0000644001705200017500000000461605513716402013117 0ustar tbtb% There's no easy way to generate equation numbers like (1a), (1b), (1') etc. % However these are both easily fixed by reading in eqalign.sty (via the % optional arg to \documentstyle) where eqalign.sty contains: % eqalign (style option for all style) to reenable PLAIN TeX's % \eqalign command and generalize the LaTeX's equation numbering. % Written by Charles Karney (Karney%PPC.MFENET@NMFECC.ARPA) 1986/01/03. % This style option can be used with any style. E.g., % \documentstyle[11pt,eqalign]{article} % It provides: % (1) \eqalign, \displaylines, \eqalignno, and \leqalignno from Plain % TeX. % (2) \eqn(A5c) gives \eqno\hbox{(A5c)}. This ensures that the "A" and % "c" are set in Roman. % (3) \eqnum increments the equation counter and prints it. E.g., % $$x^2+y^2=z^2, \eqn(\eqnum)$$ % (4) \eqlab{