;;; -*- Mode: Lisp; Package: Maxima; Syntax: Common-Lisp; Base: 10 -*- ;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; The data in this file contains enhancments. ;;;;; ;;; ;;;;; ;;; Copyright (c) 1984,1987 by William Schelter,University of Texas ;;;;; ;;; All rights reserved ;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; (c) Copyright 1980 Massachusetts Institute of Technology ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (in-package "MAXIMA") (macsyma-module fortra) (DECLARE-TOP (SPECIAL LB RB ;Used for communication with MSTRING. $LOADPRINT ;If NIL, no load message gets printed. 1//2 -1//2) (*LEXPR FORTRAN-PRINT $FORTMX)) (DEFMVAR $FORTSPACES NIL "If T, Fortran card images are filled out to 80 columns using spaces." BOOLEAN MODIFIED-COMMANDS '$FORTRAN) (DEFMVAR $FORTINDENT 0 "The number of spaces (beyond 6) to indent Fortran statements as they are printed." FIXNUM MODIFIED-COMMANDS '$FORTRAN) (DEFMVAR $FORTFLOAT NIL "Something JPG is working on.") ;; This function is called from Macsyma toplevel. If the argument is a ;; symbol, and the symbol is bound to a matrix, then the matrix is printed ;; using an array assignment notation. (DEFMSPEC $FORTRAN (L) (SETQ L (FEXPRCHECK L)) (LET ((VALUE (STRMEVAL L))) (COND ((MSETQP L) (SETQ VALUE `((MEQUAL) ,(CADR L) ,(MEVAL L))))) (COND ((AND (SYMBOLP L) ($MATRIXP VALUE)) ($FORTMX L VALUE)) ((AND (NOT (ATOM VALUE)) (EQ (CAAR VALUE) 'MEQUAL) (SYMBOLP (CADR VALUE)) ($MATRIXP (CADDR VALUE))) ($FORTMX (CADR VALUE) (CADDR VALUE))) (T (FORTRAN-PRINT VALUE))))) ;; This function is called from Lisp programs. It takes an expression and ;; a stream argument. Default stream is NIL in MacLisp and *STANDARD-OUTPUT* ;; in LMLisp. This should be canonicalized in Macsyma at some point. ;; TERPRI is a PDP10 MacLisp flag which, if set to T, will keep symbols and ;; bignums from being broken across page boundaries when printed. $LOADPRINT ;; is NIL to keep a message from being printed when the file containing MSTRING ;; is loaded. (MRG;GRIND) (DEFPROP MEXPT (#\* #\*) DISSYM) (DEFUN FORTRAN-PRINT (X &OPTIONAL (STREAM #+Maclisp NIL #-Maclisp *standard-output*) &AUX #+PDP10 (TERPRI T) #+PDP10 ($LOADPRINT NIL) ;; This is a poor way of saying that array references ;; are to be printed with parens instead of brackets. (LB #. left-parentheses-char ) (RB #. right-parentheses-char )) ;; Restructure the expression for displaying. (SETQ X (FORTSCAN X)) ;; Linearize the expression using MSTRING. Some global state must be ;; modified for MSTRING to generate using Fortran syntax. This must be ;; undone so as not to modifiy the toplevel behavior of MSTRING. (UNWIND-PROTECT (DEFPROP MEXPT MSIZE-INFIX GRIND) (DEFPROP MMINUS 100. LBP) (DEFPROP MSETQ (#\:) STRSYM) (SETQ X (mstring x)) ;; Make sure this gets done before exiting this frame. (DEFPROP MEXPT MSZ-MEXPT GRIND) (REMPROP 'MMINUS 'LBP) ) ;; MSTRING returns a list of characters. Now print them. (DO ((C #.(char-int #\0) (f+ 1 (remainder (f- c #. (char-int #\0)) 16) #. (char-int #\0))) (COLUMN (f+ 6 $FORTINDENT) (f+ 9 $FORTINDENT))) ((NULL X)) ;; Print five spaces, a continuation character if needed, and then ;; more spaces. COLUMN points to the last column printed in. When ;; it equals 80, we should quit. (COND ((= C #. (char-int #\0)) (PRINT-SPACES COLUMN STREAM)) (T (PRINT-SPACES 5 STREAM) (TYO (code-char C) STREAM) (PRINT-SPACES (f- COLUMN 6) STREAM))) ;; Print the expression. Remember, Fortran ignores blanks and line ;; terminators, so we don't care where the expression is broken. (DO () ((= COLUMN 72.)) (IF (NULL X) (IF $FORTSPACES (TYO #\SPACE STREAM) (RETURN NIL)) (progn (and (equal (car x) #. back-slash-char) (setq x (cdr x))) (TYO (POP X) STREAM))) (INCREMENT COLUMN)) ;; Columns 73 to 80 contain spaces (IF $FORTSPACES (PRINT-SPACES 8 STREAM)) (TERPRI STREAM)) '$DONE) (DEFUN PRINT-SPACES (N STREAM) (DOTIMES (I N) (TYO #\SPACE STREAM))) ;; This function is similar to NFORMAT. Prepare an expression ;; for printing by converting x^(1/2) to sqrt(x), etc. A better ;; way of doing this would be to have a programmable printer and ;; not cons any new expressions at all. Some of this formatting, such ;; as E^X --> EXP(X) is specific to Fortran, but why isn't the standard ;; function used for the rest? (DEFUN FORTSCAN (E) (COND ((ATOM E) (cond ((eq e '$%i) '((mprogn) 0.0 1.0)) (t E))) ;%I is (0,1) ((AND (EQ (CAAR E) 'MEXPT) (EQ (CADR E) '$%E)) (LIST '($EXP SIMP) (FORTSCAN (CADDR E)))) ((AND (EQ (CAAR E) 'MEXPT) (ALIKE1 (CADDR E) 1//2)) (LIST '(%SQRT SIMP) (FORTSCAN (CADR E)))) ((AND (EQ (CAAR E) 'MEXPT) (ALIKE1 (CADDR E) -1//2)) (LIST '(MQUOTIENT SIMP) 1 (LIST '(%SQRT SIMP) (FORTSCAN (CADR E))))) ((AND (EQ (CAAR E) 'MTIMES) (RATNUMP (CADR E)) (zl-MEMBER (CADADR E) '(1 -1))) (COND ((EQUAL (CADADR E) 1) (FORTSCAN-MTIMES E)) (T (LIST '(MMINUS SIMP) (FORTSCAN-MTIMES E))))) ((EQ (CAAR E) 'RAT) (LIST '(MQUOTIENT SIMP) (FLOAT (CADR E)) (FLOAT (CADDR E)))) ((EQ (CAAR E) 'MRAT) (FORTSCAN (RATDISREP E))) ;; complex numbers to f77 syntax a+b%i ==> (a,b) ((and (memq (caar e) '(mtimes mplus)) ((lambda (a) (and (numberp (cadr a)) (numberp (caddr a)) (not (zerop1 (cadr a))) (list '(mprogn) (caddr a) (cadr a)))) (simplify ($bothcoef e '$%i))))) (T (CONS (CAR E) (MAPCAR 'FORTSCAN (CDR E)))))) (DEFUN FORTSCAN-MTIMES (E) (LIST '(MQUOTIENT SIMP) (COND ((NULL (CDDDR E)) (FORTSCAN (CADDR E))) (T (CONS (CAR E) (MAPCAR 'FORTSCAN (CDDR E))))) (FLOAT (CADDR (CADR E))))) ;; Takes a name and a matrix and prints a sequence of Fortran assignment ;; statements of the form ;; NAME(I,J) = (DEFMFUN $FORTMX (NAME MAT &OPTIONAL (STREAM #-CL NIL #+CL *standard-output*) &AUX ($LOADPRINT NIL)) (COND ((NOT (symbolp NAME)) (MERROR "~%First argument to FORTMX must be a symbol.")) ((NOT ($MATRIXP MAT)) (MERROR "Second argument to FORTMX not a matrix: ~M" MAT))) (DO ((MAT (CDR MAT) (CDR MAT)) (I 1 (f1+ I))) ((NULL MAT)) (DECLARE (FIXNUM I)) (DO ((M (CDAR MAT) (CDR M)) (J 1 (f1+ J))) ((NULL M)) (DECLARE (FIXNUM J)) (FORTRAN-PRINT `((MEQUAL) ((,NAME) ,I ,J) ,(CAR M)) STREAM))) '$DONE) ;; Local Modes: ;; Comment Column:26 ;; End: