There are no other files named form.doc in the archive.

.PS 59 70.AP.P 5,0,5.SP 2.FLAG INDEX.FLAG CAPITALIZE .tp 8.C; FORMAL-SR MATRIX COMPUTATION SYSTEM .tp 8.C; Allen I. Fleishman, Ph.D. .tp 8.C; Lederle Laboratories .SP 1.TITLE FORMAL Document Version 2.2 Note - this manual has been adapted from an earlier version originally written by Ledyard R Tucker. .s 1 FORMAL is a &F&O&RTRAN &Matrix &Algebra &Library that includes programs written by Carl Finkbeiner of Proctor and Gamble, Ledyard R Tucker of the University of Illinois, and Allen I. Fleishman of Stevens Institute. The programs were modified for Stevens Institute by Allen Fleishman. This library provides a number of subroutines for performing matrix and statistical operations in FORTRAN computer programs. The subroutines facilitate writing FORTRAN programs without interfering with their flexibility. Advanced FORTRAN users may elect to skip the following introduction to the FORMAL-SR COMPUTATION SYSTEM and go immediately to the sections on advanced FORMAL use (e.g., Use of FORMAL with varied or Non-Square Matrices on page 9 and the subroutines which follow). Although this library is sufficiently extensive to permit writing of complete programs it may be combined with FORTRAN statements in more extensive programs. A &Simplified-&Restricted system has been devised using the FORMAL procedures in order to provide students with minimal or no knowledge of FORTRAN a means to obtain computations on matrix problems. This system is designated the FORMAL-SR MATRIX COMPUTATION SYSTEM and will provide a working program for many class size problems and projects. This library allows the user to perform easy I/O (e.g., titles, matrix printers, scatterplots), matrix operations (e.g., eigen roots and vectors, inverses, Kronecker products), elementwise operations (e.g., reciprocols of all elements, square roots of all elements), matrix manipulations (e.g., copying matrices, concatenating or partitioning matrices), and standard operations (e.g., computing correlations, factor analyses, Monte Carlo programs, ANOVA). The standard FORMAL-SR COMPUTATION SYSTEM provides memory units for 20 matrices, each matrix having up to 15 rows and up to 15 columns. Matrices larger than 13 rows or 13 columns should not be used with the FORMAL-SR MATRIX COMPUTATION SYSTEM, because some of the subroutines involve restrictions on matrix sizes to less than the maximum memory unit size. The number of memory units and their maximum dimensions may be revised for a particular program. The procedure for making these revisions is described below (see note on Revision of Number of Storage Units and Size of Matrices and Use of FORMAL with varied or Non-Square Matrices). Computations and data handling operations in the FORMAL-SR MATRIX COMPUTATION SYSTEM are programmed by either a series of CALL statements to subroutines or simple FORTRAN statements described in the sections of these notes on classes of operations. Operation of this system is described in terms of an Outline of Card Pack on pages 4-5 and an example on pages 5-9. Notes for revision and extended use of the system follow the example. .subtitle Type#of#Cards .index Type of Cards .s 1 .tp 8.C; Type of Cards .s 1 Computations are controlled by a pack of punched cards which may be classified into four types: accounting cards, system cards, program cards, and data cards. (See the Outline of Card Pack on pages 4-5 and the Card Pack for Example on pages 6-7). There are two cards for accounting: one that indicates whose job it is .index accounting (the PPN) and a second which indicates the secret password. These two cards are in section A of the Outline and are the first two cards in the Card Pack. The form of these cards is illustrated in the Card Pack for Example on page 6. Note that the PPN number (the Programmer Project Number) and the PASSWORD are fictitious. The system cards appear in several places in the deck. They .index system cards are: the first card of section B of the Outline (card 3 in the Card Pack), the $INCLUDE and $DATA cards in section E (cards 47 and 48 in the Card Pack), and the final card in section G (card 55 in the Card Pack). In the FORMAL-SR MATRIX COMPUTATION SYSTEM there are three classes of program cards: invocation cards, operation .index program cards cards, and end of program cards; sections B, C, and D respectively of the Outline. The invocation cards are the .index invocaton cards last eight cards in section B of the Outline, as well as cards 4-11 of the Card Pack. Invocation cards are essential for the FORMAL system, however, revisions of these cards may be made. Such revisions are discussed later. The end of program cards are given .index end of program cards in section D and are cards 45 and 46 of the Card Pack. A few general points: .list.le;All program cards are to begin in column 7 and may not have anything punched beyond column 72. This does not apply to accounting or system cards which are explicitly stated to begin in column 1 or to data cards which can have data in any of the 80 columns. .le;Unless otherwise stated (e.g., in section on Non-square matrices) references to rows (or columns) refers to the number of rows (or columns) to be operated on. This may be less than: a)#the ^&dimensional\& size of the memory unit (i.e., 'I1') or b)#the ^&actual\& size of the data set. For example, one can print out only the first two rows of an input data set even if the matrix is dimensioned 15#x#15 ('I1 = 15') and even if the matrix has more than 2 rows of data (e.g., 5 rows of data). That is, line 18 of the Card pack could have been 'CALL#PRINT#(S1,#2,#3,#'F')'. .le;Variables are of two basic types: .index Integer variables (1) Integers - these variables always begin with a letter from I to N (a useful mnemonic is to remember the name '&I&Nteger'). Integers are always whole numbers and never contain a decimal place. Commonly seen integers as used in these programs are: the number of rows (often abbreviated 'nr'), the options and the flags (e.g., iopt or iflag). .index Floating point variables (2) Floating point (or 'F') - these variables always begin with a letter from A to H or O to Z. Floating point variables .index F variable can take on fractional values. The most frequently seen 'F' variable is data (this is true even if the data you happen to have is always a whole number). As a safe rule of thumb, if you create a variable with the same first letter as the first letter of the program's variables, no errors will be made. However if the variable was to look like nr (an integer variable) and you supplied a constant called ROWS (an 'F' variable), an error will be made and the computer may not be smart enough to realize it!!! .le;Spaces may appear freely between words (see below). .le;FORTRAN constants and CALL statements may be intermingled (i.e., one can create a constant anywhere in the program). .le;Within a program description , matrices generally appear in the following order: 1) input matrices (i.e., matrices needed to obtain results) and 2) output matrices. All matrices are signified by a capital S and an upper case letter (e.g., I, J, K). The upper case letter signifies a particular matrix. For example, in the TRNSP (matrix transpose) program as described on page 22, the first matrix, SI, is the matrix that the user wants to transpose, and SJ, the second matrix, is the transposed matrix. .end list All program cards from Sections B, C, and D (in general all cards which are to begin from column 7) are 'free field'. That is, >spaces are ignored. Of course you cannot put a space in the middle of a word (e.g., CA__LL, S__10, and SCA__ML are all invalid words). However spaces around words or punctuation are possible and often aid in reading (e.g., you may notice the spaces after SUB and after the commas in line 28). A second useful technique is to put >comment cards into programs. Comment cards have a 'C' in the first column. The remainder of the card is ignored. Therefore you can write a message to yourself as a reminder of the purpose of the program (or section of the program) and the meaning of each variable. You may misplace your general notes of a program, but if the notes are imbedded within the computer deck they will always be available. The operation cards contain the details of the computations to be .index operation cards performed. The computations utilize various subroutines in the FORMAL library and FORTRAN program statements. The operation cards are indicated in section C of the Outline and are illustrated by cards 12-44 of the Card Pack for Example. Data is read into the computer by methods described in the section Data Input. In the example, cards 12-15 follow the procedure described for Definition of Constants by Simple FORTRAN Statements. Card 16 uses the subroutine INPUT to read a matrix from cards into memory unit S1. Cards 17 and 18 provide printing of a title and the data from memory unit S1 (see the section on Printing of Results). The operation called for in the example results in the printed matrix at the top of page 8. Two general features of the FORMAL system are illustrated in the statement on card 18, "CALL#PRINT#(S1,5,3,'F')". The first feature is that one or more memory units are seen within the parentheses. These memory units contain the data involved in the operation to be performed or are the memory units into which results are to be placed. For the PRINT statement there is only one memory unit which contains the matrix to be printed. The second feature is that the number of rows and the number of columns of the matrix are indicated as integers, 5 and 3 in the example (an integer is a number without a decimal). Card 19 illustrates a third way to enter data into the computer using the subroutine GENR8 described in the section DATA INPUT. The results of this operation are titled and printed by the statements in cards 20 and 21 and are shown on page 8. Matrix operations with interspersed printing of results constitute the remainder of the illustrative program. These operations are chosen in accordance with the mathematics and desired results for the problem. The program is composed of a sequence of single step matrix operations. Each step is defined by a single CALL statement which names: the operation, the memory units containing the data to be utilized, and the matrix sizes. Subsequent sections of these notes provide details for the various operations. In general, the procedure for writing a computation program involves defining the computations to be performed as a series of step by step operations which are translated into a series .SUBTITLE Type of Cards/Outline of Card Pack of CALL statements. A useful procedure in program writing is to keep a running record of the matrices in the various memory units. This record or log is illustrated on page 7 as a Memory Usage Log for Example. Each step in the computations is indicated by a CALL statement. Constant reference to this log helps prevent writing one result over another matrix that is to be used subsequently. Writing of one matrix over another matrix destroys the preceding matrix. The most recently written matrix remains in the memory unit. Therefore, when a matrix is no longer needed in subsequent computations or to print results, the memory unit containing that matrix may be reused to store another matrix. The record also aids in locating the memory units containing desired matrices. Management of the usage of memory units is one of the tricky aspects of computer programming. Decks of data cards constitute the fourth class of cards in a FORMAL-SR MATRIX COMPUTATION SYSTEM program. These decks are indicated as section F of the Outline and are illustrated by cards 49-54 of the Card Pack for Example. Each data deck is preceded by a 'header' card (e.g., illustrated as card 49), which is followed by the cards containing data. Details for the data decks are given in the section for DATA INPUT. There should be a data deck for each matrix read into the computer. These data decks are placed into the pack in the order by which they are to be read. In the example there is only one data matrix so that there is only one data deck. .subtitle Outline of Card Pack/Example of Computation of FORMAL-SR .S 1.tp 8.C; Outline of Card Pack .s 1 A.###Job identification cards. .lm 7.BR;(Start punching in column 1.) .br;$JOB name_<p,pn_>/NAME:'your name' .br;$PASSWORD secret password .lm 0.s 1 .br B.###FORMAL-SR invocation cards. .lm 7.BR (For the first card start punching in column 1; .lm 13 punch the remaining seven cards starting in column 7.) .lm 7.br.sp 1 .br;$FORTRAN .lm 13.br;IMPLICIT#DOUBLE#PRECISION#(A-H,O-Z) .br;DIMENSION S1(15,15),S2(15,15),S3(15,15),S4(15,15) .br;DIMENSION S5(15,15),S6(15,15),S7(15,15),S8(15,15) .br;DIMENSION S9(15,15),S10(15,15),S11(15,15),S12(15,15) .br;DIMENSION S13(15,15),S14(15,15),S15(15,15),S16(15,15) .br;DIMENSION S17(15,15),S18(15,15),S19(15,15),S20(15,15) .br;COMMON/B/I1 .br;I1=I5 .SP 1.lm 0.s 1 C.###Operation cards consisting of: .list .le;CALL statements for FORMAL subroutines (see sections on FORMAL subroutines); .le;FORTRAN program statements; and .le;FORTRAN constants. .end list D.###End of program cards. .lm 13.br;(Start punching in column 7.) .sp 1.br;STOP .br;END .SP 1.lm 0.s 1;E.###Start computation and read data card. .lm 7.br;(Start punching in column 1.) .sp 1 $INCLUDE#FORMAL.REL_<1413,546_>/SEARCH .br;$DATA .s 1.SP 1.lm 0;F.###Data decks (see section on INPUT). .s 1;G.###Blue end of job card. .S 2.tp 8.C;Example of Computations by FORMAL-SR .s 1 The following data matrix X contains measures of five objects on three central attributes. .s 1.tp 8.C; DATA MATRIX X .s 1.tp 8.C; #########Central Attribute .tp 8.C;Object####1####2####3 .s 1 .tp 8.C;##1#######5####4####3 .tp 8.C;##2#######3####1####2 .tp 8.C;##3#######3####3####3 .tp 8.C;##4#######4####2####6 .tp 8.C;##5#######1####0####5 .s 2 Compute the sample mean vector M, the matrix of deviation measures from the sample means Xd, the sample covariance matrix Cxx, the standard deviation matrix Sx, and the sample correlation matrix Rxx. .s 2 ^&Mathematical__Notes.\& .NOFILL.NOJUSTIFY N = Number of objects in the sample. (1) = A column vector with N entries of 1.0. M = Vector of means of attributes = (1/N)(1)'X. Xd = X - (1)'M. Cxx = [1/(N-1)]Xd'Xd. Sx = Diag (Cxx). Rxx = Sx##Cxx#Sx#. .FILL.JUSTIFY .subtitle Card Pack for Example .page .tp 8.C; Card Pack for Example .s 1.nofill.nojustify.sp 1 Card Number Information Punched on cards (not punched) (start in columns 1 or 7 as appropriate) 1 $JOB _<1234,567_>/NAME:'SMITH, JOHN' 2 $PASSWORD HUSH 3 $FORTRAN 4 IMPLICIT DOUBLE PRECISION (A-H,O-Z) 5 DIMENSION S1(15,15),S2(15,15),S3(15,15),S4(15,15) 6 DIMENSION S5(15,15),S6(15,15),S7(15,15),S8(15,15) 7 DIMENSION S9(15,15),S10(15,15),S11(15,15),S12(15,15) 8 DIMENSION S13(15,15),S14(15,15),S15(15,15),S16(15,15) 9 DIMENSION S17(15,15),S18(15,15),S19(15,15),S20(15,15) 10 COMMON /B/I1 11 I1 = 15 12 RN = 5.0 13 RNM = RN - 1.0 14 RNI = 1.0/RN 15 RNMI = 1.0/RNM 16 CALL INPUT (S1) 17 CALL TITLE ('ORIGINAL DATA MATRIX X',23) 18 CALL PRINT (S1, 5, 3, 'F') 19 CALL GENR8 (1.0, S9, 5, 1) 20 CALL TITLE ('COLUMN VECTOR OF ONES', 21) 21 CALL PRINT (S9, 5, 1, 'F') 22 CALL TRNSP (S9, S10, 5, 1) 23 CALL MATML (S10, S1, S8, 1, 5, 3) 24 CALL SCAML (RNI, S8, S2, 1, 3) 25 CALL TITLE ('MEAN VECTOR X BAR', 18) 26 CALL PRINT (S2, 1, 3, 'F') 27 CALL MATML (S9, S2, S8, 5, 1, 3) 28 CALL SUB (S1, S8, S3, 5, 3) 29 CALL TITLE ('DEVIATION MEASURES MATRIX X SUB D', 34) 30 CALL PRINT (S3, 5, 3, 'F') 31 CALL TRNSP (S3, S8, 5, 3) 32 CALL MATML (S8, S3, S7, 3, 5, 3) 33 CALL SCAML (RNMI, S7, S4, 3, 3) 34 CALL TITLE ('COVARIANCE MATRIX C SUB XX', 27) 35 CALL PRINT (S4, 3, 3, 'F') 36 CALL DIAG (S4, S8, 3) 37 CALL SQRT (S8, S5, 3, 3, -0.00001) 38 CALL TITLE ('STANDARD DEVIATION MATRIX S SUB X', 34) 39 CALL PRINT (S5, 3, 3, 'F') 40 CALL INVRS (S5, S8, 3) 41 CALL MATML (S8, S4, S7, 3, 3, 3) 42 CALL MATML (S7, S8, S6, 3, 3, 3) 43 CALL TITLE ('CORRELATION MATRIX R SUB XX', 28) 44 CALL PRINT (S6, 3, 3, 'F') 45 STOP 46 END 47 $INCLUDE FORMAL.REL_<1413,546_>/SEARCH .subtitle Card Pack for Example/Memory Usage Log for Example 48 $DATA 49 00050003(1X, 3F1.0) PROBLEM 1 DATA MATRIX 50 1543 51 2312 52 3333 53 4426 54 5105 55 _<blue end of job card_> .subtitle Memory Usage Log for Example .s 2.fill.justify.SP 1 .tp 8.C; Memory Usage Log for Example .INDEX Memory Usage Log .s 1 .nofill.nojustify.SP 1 Matrices Contents S1 X - raw data S2 M - vector of means S3 Xd - matrix of deviation scores S4 Cxx - covariance matrix S5 Sd - Diag (Cxx) - matrix with standard deviations in diagonal S6 Rxx - correlation matrix S7 [Xd' Xd], [INVERSE(Sx)*Cxx] S8 (1)'X, (1)M, Xd', DIAGONAL(Cxx), INVERSE(Sx) S9 (1) - column vector of ones S10 (1)' - row vector of ones S11 S12 S13 S14 S15 S16 S17 S18 S19 S20 .s 1 Constants Contents RN N RNM (N - 1) RNI 1/N RNMI 1/(N - 1) .subtitle Example Output .INDEX Example Output .page.nofill.nojustify * F O R M A L * (FORTRAN MATRIX ALGEBRA LIBRARY) DATE: 23-Aug-79 TIME: 14:51 SPECIFICATIONS FOR INPUT MATRIX # 1(LURN = 2): NUMBER OF ROWS = 5; NUMBER OF COLS = 3; FORMAT =(1X, 3F1.0) (this should be on the above line) PROBLEM 1 DATA MATRIX DATA READ FROM DATA FILE FRMLIN.DAT ORIGINAL DATA MATRIX X 1 2 3 1 5.00000 4.00000 3.00000 2 3.00000 1.00000 2.00000 3 3.00000 3.00000 3.00000 4 4.00000 2.00000 6.00000 5 1.00000 0.00000 5.00000 COLUMN VECTOR OF ONES 1 1 1.00000 2 1.00000 3 1.00000 4 1.00000 5 1.00000 MEAN VECTOR X BAR 1 2 3 1 3.20000 2.00000 3.80000 DEVIATION MEASURES MATRIX X SUB D 1 2 3 1 1.80000 2.00000 -0.80000 2 -0.20000 -1.00000 -1.80000 3 -0.20000 1.00000 -0.80000 4 0.80000 0.00000 2.20000 5 -2.20000 -2.00000 1.20000 COVARIANCE MATRIX C SUB XX .subtitle Example Output/Note of Revision of Storage Units 1 2 3 1 2.20000 2.00000 -0.45000 2 2.00000 2.50000 -0.75000 3 -0.45000 -0.75000 2.70000 STANDARD DEVIATION MATRIX S SUB X 1 2 3 1 1.48324 0.00000 0.00000 2 0.00000 1.58114 0.00000 3 0.00000 0.00000 1.64317 .subtitle Note on Revision of Number of Storage Units and Size of Matrices .TP 9 CORRELATION MATRIX R SUB XX 1 2 3 1 1.00000 0.85280 -0.18464 2 0.85280 1.00000 -0.28868 3 -0.18464 -0.28868 1.00000 .fill.justify.s 2 .tp 8.C; Note on Revision of Number of Storage Units and Size of Matrices .INDEX Revision of matrix sizes .INDEX Size of Matrices .INDEX Number of Storage Units .s 1 Matrix size may be larger than 15 x 15 for some computing jobs. This will require two revisions in the invocation cards. The first revision is to change the memory unit sizes in the DIMENSION statements to the desired sizes. For example, if 20 x 20 memory units are desired, &a&l&l of the DIMENSION statements would look like the following: .br;#######DIMENSION S1(20,20),S2(20,20),S3(20,20),S4(20,20) .br;The matrices must be square (exception to this rule can be found below). A second revision is to change the number '15' in the 'I1#=#15' statement to the new memory unit size. Therefore, if the memory units were changed to 20 x 20, the statement would become 'I1#=#20'. One can also change the number of storage matrices by inserting additional (or deleting old) DIMENSION statements. For example, in the cards above only four matrices are used (i.e., S5 through S20 were not needed therefore they were never 'created'). .subtitle Use#of#FORMAL#with#Varied#or#Non-Square#Matrices .s 1 .tp 8.C; Use of FORMAL with Varied or Non-Square Matrices .INDEX Varied Matrix dimensions .INDEX Non-Square Matrices .s 1 Matrices may be non-square. However square matrices are simpler to use with FORMAL. Frequently a user requires rectangular matrices where the number of rows (or columns) might be much greater than the number of columns (or rows) (e.g., data matrix). Under this condition prefix the program name with an 'X' (e.g., .index 'X' programs INVRS becomes XINVRS, XTX becomes XXTX). Enter the number of rows for which you dimensioned each matrix after the first parenthesis. For example: .tp 8.lm 7.nofill.nojustify.s 1 IMPLICIT DOUBLE PRECISION (A-H, O-Z) DIMENSION S1(5,5), S2(100,5),S3(100,5), S4(5,5) . . . COMMON /B/ I1 I1 = 5 . . . CALL XINPUT (100,S2) CALL INPUT (S1) CALL XMATML (100,5,100, S2, S1, S3, 20, 3, 3) CALL XPRINT (100, S3, 100, 5, 'F') CALL INVRS (S1, S2, 3) .lm 0.fill.justify.s 1 The first three numbers in the XMATML call '(100,5,100,...' refer to the number of rows in the DIMENSION statement (the first number of each pair). For example, S2 was dimensioned as &1&0&0 x 5 , S1 was dimensioned as &5 x 5 and S3 was dimensioned as &1&0&0 x 5. Also note the order of the numbers is S2, S1, and S3. This is the order by which you input the matrices for matrix multiplication. The first number is the row dimension, as seen in the DIMENSION statement, for the first matrix used (i.e., S2) in the Call statement. The second number is the row dimension for the second matrix used (i.e., S1), etc. These numbers tell FORMAL the ^&largest\& size matrix it can use. The size matrix ^&actually\& input or created by the program may and typically should be smaller (and ^&never\& larger) than the row dimension size. As shown in the above example, S1 and S2 were actually 20#x#3 and 3#x#3 matrices respectively. Also note that the dimensioned size of the matrices differ (i.e., S1 and S2 are different sizes, 5 x 5 and 100 x 5 respectively). Please note in this example that the simpler (non 'X') version of FORMAL can be used with this more advanced use of FORMAL (e.g., the inverse of matrix S1). However, when the 'non-X' FORMAL-SR MATRIX COMPUTATION SYSTEM is used the dimensions of &a&l&l matrices within that call must be: 1)#square, 2)#the same size, and 3)#have size equal to I1 as in line 11 of the Card Pack for Example. That is, the inverse program operates on S1 and S2. These matrices are: 1)square matrices, 2)of equal size (each 5 x 5), and 3) have I1 (or 5) rows and columns. In the subroutine descriptions which follow, the 'X' version follows the simpler version. The variable <>NRMi (or NCMI) will .index <NCMI refer to the &Number of &Rows (or &Columns) in the &Main program for matrix SI (e.g., NRM3 above would be 100). Not all subroutines have an 'X' version. Specifically, unless a program inputs a matrix (e.g., TITLE or PAGE), there would not be an 'X' version of it (as there is no need for one). .subtitle Data#Input .s 1.tp 8.tp 8.C; Data Input .INDEX Data Input .s 1 Three methods for recording values in the computer for a FORMAL-SR computing job are described. All values input to this system should be real numbers. While only the so-called F format will be considered here, D format is permissable as well. In F format each value is a number with a decimal. All values are assumed to be positive unless preceded by a minus sign. .s 1 1.##^&Definition__of__Constants__by__Simple__<FORTRAN<__Statements\& .INDEX Constants .s 1 Constant values may be entered into a computing job using simple FORTRAN statements. For example, a constant value is the number of objects/subjects in a sample for which a statistical analysis is to be performed. Note that all integer constants used in computations will be converted to real numbers. The conversion to a real number is accomplished by inclusion of a decimal point followed by (at least) one zero. The corresponding real number in F format for use in a calculation is 13.0 when there are 13 subjects/objects in the sample. A very useful sequence of FORTRAN statements is given below. .tp 8.lm 7.nofill.nojustify RN## = n.0 RNM# = RN - 1.0 RNI# = 1.0/RN RNMI = 1.0/RNM .lm 0;In these statements: .lm 7 n #is the integer number of objects (e.g., 13); RN is the symbolic name for the number of objects N; RNM is the symbolic name for (N-1); RNI is the symbolic name for 1/N; and RNMI is the symbolic name for 1/(N-1). .fill.justify.lm 0 Note that simple arithmetic operations (e.g., subtraction or division) are possible. The arithmetic symbols are +, -, *, /, ** for addition, subtraction, multiplication, division and exponentiation respectively. Parentheses may be freely used. More advanced calculations are possible (see any FORTRAN text). Any sequence of letters and digits up to six characters long may be used as the symbolic name for a constant provided that: .lm 5.i -3;1. the first character is a letter ^&other\& than I, J, K, L, M, or N (these characters are for special variables called integers which can only be whole numbers and can never be fractions); and .i -3;2. the name of the variable is unique (i.e., you do not want to forget and change it accidentally). .s 1.lm 0 2.##^&Subroutine__<>INPUT\& .s 1 This subroutine is used to read a matrix from cards into one of the matrix memory units. The program statement to use this subroutine is (starting in column 7): .lm 7;CALL INPUT##(SI) .br;CALL XINPUT (NRMI, SI) .lm 0;where I is an integer designating the particular memory unit. When this subroutine is used the data deck must be preceded by a 'header card'. This card will tell FORMAL the number of rows and the number of columns that will be read in along with information on how the data is formated in your data deck. The form of the header card is (starting in column 1): .lm 4.br rrrrcccc (format string) deck identification .lm 0.br where: 'rrrr' is a four digit integer equal to the number of rows of the matrix. You must use (and right justify) all four of the digits. For example, if you want to read in 14 rows of data, the first card of your data deck must begin with '0014'; 'cccc' is a four digit integer equal to the number of columns of the matrix (as above you must use all digits and right justify the number); 'format string' describes the sequence of values in each row of the matrix (for a simple situation see below or for more information see format elements in the SPSS manual section 4.6.3 or any FORTRAN text); and 'deck identification' helps: 1)#to identify which data set you are working with (you may be using FORMAL for two different sets of data) and 2)#to identify the data set when examining FORMAL output (it is printed out at the place where the data is read into the program). The simplest situation for a format string occurs when every value in a row of a matrix involves the following: the same number of characters, the same number of decimal places, and all of the values in the row are punched into one card. In this case the format string has the form: .i 7.br;(mX,cFw.d) .br;where: m is a one or two digit integer equal to the number of card columns to be skipped before a useful data value occurs [initial columns may be used for card or subject identification (e.g., 1 for first card/subject, 2 for second, ...)]; nc is a one or two digit number equal to the number of columns of the matrix (i.e., number of variables to be read in); w is an integer equal to the number of characters used for each value (e.g., If you are reading in a number like 171.43 do not forget to count the decimal point. Therefore w would equal 6); and d is an integer equal to the number of decimal places in each value (e.g., since there are two numbers on the right side of the decimal point above ('43'), d would equal 2). Two important points to consider: .list .le;In case some of the values are negative, an initial character space for each value should be reserved for the algebraic sign. For positive values this character may be blank or set to either a zero or a plus sign. .le;It is not necessary to punch a decimal point, the computer will interpret the last d characters as decimal places when a decimal point is not punched (e.g., one could read data such as 171.43 from data that is punched in as 17143 using a format of 'F5.2'). .le;Remember that the format string is enclosed in parentheses. .end list For example, consider that the following original factor matrix is to be punched into a data deck and input to the program. .sp 1 .i 21;column 1 .tp 8.C;1##0.796 0.394 .tp 8.C;2##0.787 0.447 .tp 8.C;3##0.803 0.350 .tp 8.C;4##0.704 0.365 .tp 8.C;5##0.711 -.575 .tp 8.C;6##0.697 -.524 .tp 8.C;7##0.582 -.610 .tp 8.C;8##0.597 -.528 .tp 8.C;9##0.726 0.286 .SP 1.s 1.br;Note that zeros have been recorded to the left of the decimal point for all positive numbers so that there are the same number of characters for each number. A card could be punched for each row of the above matrix. The first two characters would be the row number followed by six characters for the first value and six more characters for the second value. The fifth and eleventh characters would be decimal points. The header card would be either of two forms: .br.i 7;00090002(2X, F6.3, F6.3) ORIGINAL FACTOR MATRIX .br;or .br.i 7;00090002(2X,2F6.3) ORIGINAL FACTOR MATRIX .br;The first four digits of both forms ('0009') indicate that the matrix has nine rows and the next four digits of both forms ('0002') indicate that the matrix has only two columns. You may think that you see three columns above, but the computer will ignore (or skip) over the card/row number. The characters within the parentheses constitute the 'format string' which describes how the data cards are punched. The character '2X' indicates that the first two columns of the card will be ignored. The 'F' indicates F format. The '6' indicates six characters are used for the value. The '3' following the decimal place indicates that there are three digits after the decimal place. Make note of the following two features: 1) each description for a group of characters in a data card is separated from other descriptions by a comma and zero or more spaces, 2) a blank space is before each number (e.g., '__0.796__0.394'). This blank is read as the first of six characters. When the computer sees a blank space as data it treats it as a zero. Therefore the first number above is effectively seen as 00.796 or 0.796. Since both values in each row of data are punched alike the second form of the header card may be used. A '2' indicates that the description 'F6.3' is repeated. An integer preceding the 'F' of a description indicates the number of consecutive repetitions of that description. Another example is presented on line 49 of the Card Pack for Example on page 6. .s 1 3.##^&Special__Matrices\& .index Special Matrices .s 1 .list.p 5, 0, 5.lm 0.le;^&Subroutine__<>GENR8\& This subroutine is used to create a matrix having the same value in every cell. The program statement to use this subroutine is: .i 7;(starting in column 7) .i 7.br;CALL #GENR8 (a, SI, nr, nc) .i 7.br;CALL XGENR8 (NRMI, a, SI, nr, nc) .lm +5.p -3, 0, 5.br;where: a is a real number to be inserted into each cell; I is an integer designating the memory unit to contain the matrix; nr is an integer equal to the number of rows of the matrix; and nc is an integer equal to the number of columns of the matrix. .s 1.LM 0 .p 5, 0, 5.lm 0.le;^&Subroutine__<>IDENT\& This subroutine is used to create an identity matrix of size n. The program statement is: .lm 7.br;CALL #IDENT (SI, n) .br;CALL XIDENT (NRMI, SI, n) .lm 5.p -3, 0, 5.br;where: I is an integer designating the memory unit to contain the identity matrix; and n is an integer equal to the order of the identity matrix (i.e., the number of rows and columns). .end list.lm 0.page.subtitle Printing of Results .tp 8.C;Printing of Results .LIST .p 5, 0, 5.lm 0.le;^&Subroutine__<>TITLE\& This subroutine is used to print titles (or any type of message) on the output. One frequent use is in the identification of matrices. The program statement to use this subroutine is: .i 7;CALL TITLE (' character string or title ', n) .lm 5.p -3, 0, 5.br;where: character string is the title to be printed (this character string is enclosed in apostrophies and in general apostrophies should not be included in the character string although an advanced technique could be used to include apostrophies); n is an integer equal to the number of characters in the character string (count blank spaces as characters). .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>PAGE\& This subroutine ejects a page on the output. No computations are done. It is useful in 'tidying up' the output. The program statement is: .br.i 7;CALL PAGE .s 1.p 5, 0, 5.lm 0.le;^&Subroutine__<>PRINT\& This subroutine is used to print a matrix. The program statement to use this subroutine is: .br.i 7;CALL #PRINT (SI, nr, nc, 'F') .br.i 7;CALL XPRINT (NRMI, SI, nr, nc, 'F') .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing the matrix to be printed; nr is an integer equal to the number of rows of the matrix; and nc is an integer equal to the number of columns of the matrix. .lm 0.br A change may be made from F format to D format by changing the 'F' to 'D' in the CALL statement. This change is useful for printing extremely large or small values. In D format a decimal fraction is printed in scientific notation. That is, a decimal fraction is printed containing the significant digits and the location of the decimal is indicated by a signed integer after the letter E (for exponent). For a positive integer the decimal point is moved to the right and for a negative integer the decimal point is moved to the left. The absolute value of the integer indicates the number of places to move the decimal. For example, -0.55785E+01 is the same as -5.5785 and +0.13459E-02 is the same as +0.0013459. .s 1.p 5, 0, 5.lm 0.le;^&Subroutine__<>PUNCH\& This subroutine is used to punch a matrix. The program statement to use this subroutine is: .br.i 7;CALL #PUNCH (SI, nr, nc) .br.i 7;CALL XPUNCH (NRMI, SI, nr, nc) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing the matrix to be punched; nr is an integer equal to the number of rows of the matrix; and nc is an integer equal to the number of columns of the matrix. .lm 0 A FORMAL header card is first punched. The format of the data will then be punched in 'D' format (see above). The first five columns of each card will be the row number of the matrix and the second five columns contain the specific card number for that row as more than one card will often be necessary. These two numbers should be ignored when reading from this file. That is, they are only useful to identify the order of the input. Finally the data will be punched in '5D14.7' format. The results will be output to logical unit '1'. One may need to 'assign' that unit (see 'Use at Terminal' section), which is the disk, to other units (e.g., terminal, line printer). This is because my current site does ^¬\& have a card punch. .S 1.p 5,0,5.lm 0.le;^&Subroutine__<>PLOT\& This subroutine is used to 'draw' scatterplots for all pairs of variables/columns (i.e., across rows). The program statement to use this subroutine is: .br.i 7;CALL #PLOT (SI, nr, nc, iflag) .br.i 7;CALL XPLOT (NRMI, NCMI, SI, nr, nc, iflag) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing the data to be plotted; nr is an integer designating the number of rows of the matrix; nc is an integer designating the number of columns of the matrix; and iflag is an integer in the range of -2 to +2, indicating the style the plot is to be printed in: .P -5,0,1.LM +5.br; -2#=#identify all points without drawing a set of axes; .br; -1#=#count all points (X = 1 point, 2 = two points, ...#, 9 = nine points, M = more than nine points) without drawing axes; .br; #0#=#plot the points not in pairs but as successive values (e.g., for each variable the first datum will be plotted at the first position in the plot, the second datum will be plotted at the second position, etc.), there will be no axes and the points will be identified (as if iflag were -2); .br; +1#=#count all points (as in iflag#=#-1 above) but draw a set of axes through center of plot; and .br; +2#=#identify all points (as in iflag#=#-2 above) but draw a set of axes (as in +1 above). .p 5,0,5.lm 0 Point identification, as in iflag options plus or minus 2, shall identify only the first 124 points. The first 26 points shall be identified as letters 'A' through 'Z', the next 10 points shall be numbers 0 through 9, and the next 26 points will be letters 'a' through 'z' (again). This sequence shall be repeated once. The scaling (upper and lower bounds of the axes) shall depend on only the first 124 points. See CPLOT to control axes otherwise. If nc is set to 1 (i.e., only one variable is to be plotted) a sequential value plot, as in iflag of 0, will be done. If iflag is any value less than -2 or greater than +2 an error will be identified, but processing will be continued with iflag equal to -1. When iflag is 0, the number of columns (nc) must be ^&less\& than the dimensioned number of columns of the memory unit. .S 1.p 5,0,5.lm 0.le;^&Subroutine__<>CPLOT\& This subroutine is also used to 'draw' scatterplots across all pairs of variables. This program differs from PLOT above in that only data which is between the minimum and maximum values are plotted. The boundaries of the plot are given by these minimum and maximum values, as it is often useful to see points relative to a particular framework (e.g., plotting factor loadings relative to +1 and -1 or plotting normal deviates relative to +4 and -4). The variates within the call to this subroutine are the same as that in XPLOT with the exception of xmin, xmax, ymin, and ymax. The program statement to use this subroutine is: .br.i 7;CALL #CPLOT (SI, nr, nc, xmin, xmax, ymin, ymax, iflag) .br.i 7;CALL XCPLOT (NRMI, NCMI, SI, nr, nc, xmin, xmax, ymin, ymax, .BR.I 6;2#iflag) .LM 0 .lm +5.p -3,0,5.br;where (in addition to those variables seen above): xmin is the minimum value of the first variable to be plotted (and will be the largest value to be seen on the axes); xmax is the maximum value of the first variable to be plotted (and will be the smallest value to be seen on the axes); ymin is the minimum value of the second variable; and ymax is the maximum value of the second variable. .END LIST .subtitle Matrix Operations .page.tp 8.C;^&Matrix__Operations\& .list .p 5, 0, 5.lm 0.le;^&Subroutine__<>ADD\& This subroutine is used to perform matrix addition: .br.i 7;A#+#B#=#C .br;Program statement: .br.i 7;CALL #ADD (SI, SJ, SK, nr, nc) .br.i 7;CALL XADD (NRMI, NRMJ, NRMK, SI, SJ, SK, nr, nc) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing matrix A; J is an integer designating the memory unit containing matrix B; K is an integer designating the memory unit to contain matrix C; nr is an integer equal to the number of rows of the matrices; and nc is an integer equal to the number of columns of the matrices. .s 1.p 5, 0, 5.lm 0.le;^&Subroutine__<>CHLSK\& Given a square, symmetric matrix A which is positive definite, this subroutine creates a lower triangular matrix B such that: .br;########A#=#BB' .br;Program statement: .br.i 7;CALL #CHLSK (SI, SJ, n) .br.i 7;CALL XCHLSK (NRMI, NRMJ, SI, SJ, n) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing matrix A; J is an integer designating the memory unit to contain matrix B; and n is an integer equal to the order of A and B. .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>COLSM\& This subroutine adds the elements down the columns of a matrix A and stores the results as a row vector in the first row of a memory unit B. This is equivalent to: .br;########(1)'A#=#B .br;where (1)' is a row vector containing nr entries of unity. .br;Program statement: .br.i 7;CALL #COLSM (SI, SJ, nr, nc) .br.i 7;CALL XCOLSM (NRMI, NRMJ, SI, SJ, nr, nc) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing matrix A; J is an integer designating the memory unit to contain matrix B; nr is an integer equal to the number of rows of A; and nc is an integer equal to the number of columns of A and B. .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>DET\& This subroutine computes the determinate of a square, real matrix. (Note - the order of the matrix must be ^&greater\& than 1 and ^&less\& than the size of the memory units.) .br;Program statement: .br.i 7;CALL #DET (SI, D, n, SJ) .br.i 7;CALL XDET (NRMI, NCMI, NRMJ, NCMJ, SI, D, n, SJ) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing the matrix; D is a FORTRAN constant to contain the value of the determinant which may be a separate constant located in the (1,1) cell of a memory unit Sk which is designated as D; n is an integer equal to the number of rows and columns of the matrix (must be ^&less\& than the size of the memory unit); and J is an integer designating a memory unit to be used by the program and will contain the inverse of the input matrix in case the determinant is not zero. .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>EIGEN\& This program is used to find the eigen solution for a symmetric matrix A: .br.i 7;A#=#VDV' .br;where: V is an orthonormal matrix containing eigenvectors as columns; and D is a diagonal matrix containing the corresponding eignenroots or eigenvalues. The eigenvectors and eigenvalues are arranged in descending algebraic order of the eigenvalues. .br;Program statement: .br.i 7;CALL #EIGEN (SI, SJ, SK, n, m) .br.i 7;CALL XEIGEN (NRMI, NRMJ, NRMK, SI, SJ, SK, n, m) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing matrix A; J is an integer designating the memory unit to contain matrix V; K is an integer designating the memory unit to contain matrix D; n is an integer equal to the order of A; and m is an integer equal to the number of eigenvectors and eigenvalues to be output into matrices V and D. .br; Note - V is n x m and D is m x m. .s 1.p 5, 0, 5.lm 0.le;^&Subroutine__<>GINVR\& This subroutine is used to determine the generalized inverse of a matrix. If Y were the generalized inverse then: .br.i 7;ABA#=#A .br;Note - the order of each of the matrices must be greater than 10 and ^&less\& that the size of the memory units. .br;Program statement: .br.i 7;CALL #GINVR (SI, SJ, nr, nc, SK, SL, SM) .br.i 7;CALL XGINVR (NRMI, NRMJ, NRMK, NRML, NRMM, SI, SJ, nr, nc, SK, .br.i 6;2 SL, SM) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing the matrix to have a generalized inverse computed, A; J is an integer designating the memory unit to contain the generalized inverse, B; nr is an integer equal to the number of rows of the input matrix, A; nc is an integer equal to the number of columns of the input matrix, A; and K, L, and M are integers designating 'work' matrices (temporary matrices to be used in the computations). .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>INVRS\& This subroutine is used to determine the inverse of a square matrix. .br;Note - the order of A must be greater than 1 and less than the size of the memory units. .br;Program statement: .br.i 7;CALL #INVRS (SI, SJ, n) .br.i 7;CALL XINVRS (NRMI, NCMI, NRMJ, NCMJ, SI, SJ, n) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing the input matrix; J is an integer designating the memory unit to contain the inverse of the input matrix; n is an integer equal to the number of rows and columns of the matrices (must be ^&less\& than the size of the memory units).

.s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>KRONK\&

This subroutine is used to compute the Kronecker product of two matrices: .br.i 7;A#X#B#=#C .br;Note - the size of matrix C must be the smaller of nrI*nrJ or ncI*ncJ, where nrI is the number of rows in matrix A, nrJ is the number of rows in matrix B, ncI is the number of columns of A, and ncJ is the number of columns in matrix B. .br;Program statement: .br.i 7;CALL #KRONK (SI, SJ, SK, nrI, ncI, nrJ, ncJ) .br.i 7;CALL XKRONK (NRMI, NRMJ, NRMK, SI, SJ, SK, nrI, ncI, nrJ, ncJ) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing A; J is an integer designating the memory unit containing B; K is an integer designating the memory unit to contain C; nrI is an integer equal to the number of rows of A; ncI is an integer equal to the number of columns of A; nrJ is an integer equal to the number of rows of B; and ncJ is an integer equal to the number of columns of B. .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>MATML\& This subroutine is used to perform matrix multiplication: .br.i 7;AB#=#C .br;Program statement: .br.i 7;CALL #MATML (SI, SJ, SK, nr, nb, nc) .br.i 7;CALL XMATML (NRMI, NRMJ, NRMK, SI, SJ, SK, nr, nb, nc) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing A; J is an integer designating the memory unit containing B; K is an integer designating the memory unit containing C; nr is an integer equal to the number of rows of A and C; nb is an integer equal to the number of columns of A and rows of B; and nc is an integer equal to the number of columns of B and C. .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>PRDDI\& This subroutine finds the product of the elements of the main diagonal of a matrix and outputs the product to a FORTRAN constant, PR. .br;Program statement: .br.i 7;CALL #PRDDI (SI, n, PR) .br.i 7;CALL XPRDDI (NRMI, SI, n, PR) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing the matrix; n is an integer equal to the order of that matrix; and PR is a FORTRAN constant which will be equal to the product of the elements across the major diagonal. (Note - PR may be output as the (1,1) element of a matrix.) .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>RANK\& This subroutine determines the rank of a real matrix. Note - the number of columns of the matrix must be ^&less\& than the size of the memory units ^&minus\& one. .br;Program statement: .br.i 7;CALL #RANK (SI, SJ, nr, nc, RNK) .br.i 7;CALL XRANK (NRMI, NCMI, NRMJ, SI, SJ, nr, nc, RNK) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing the matrix; J is an integer designating the memory unit to contain a temporary 'work' matrix which may be used by the program; nr is an integer equal to the number of rows of the matrix; nc is an integer equal to the number of columns of the matrix (must be ^&less\& than the size of the memory units ^&minus\& one); and RNK is a FORTRAN constant which on input equals the smallest eigenvalue to be counted and on output contains the rank. It may be the (1,1) cell of a memory unit Sk which is designated RNK. ^&When used repeatedly remember to re-initialize RNK (i.e., set it to a small number).\& A good initial value for RNK might be 0.0001. .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>RXTX\& This subroutine premultiplies a matrix read in from cards by its transpose: .br.i 7;A'A#=#B .br;Note - (1)#Number of columns of A must be ^&less\& than the size of the memory units. .br;#######(2)#This program combines the functions of INPUT and XTX as seen above and below. .br;Program statement: .br.i 7;CALL #RXTX (SI, nr, nc) .br.i 7;CALL XRXTX (NRMI, SI, nr, nc) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit to contain B; nr is an integer equal to the number of rows of A (must be ^&identical to\& the number of rows as stated on the 'header card'); and nc is an integer equal to the number of columns of A (must be ^&identical to\& the number of columns as stated on the 'header card'). .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>SCAML\& This subroutine is used to multiply a matrix by a scalar quantity: .br.i 7;aB#=#C .br;Program statement: .br.i 7;CALL #SCAML (a, SI, SJ, nr, nc) .br.i 7;CALL XSCAML (NRMI, NRMJ, a, SI, SJ, nr, nc) .LM +5.P -3, 0, 5.br;where: a is a real number. It may be a stored constant such as RNI. It may be the (1,1) entry of a matrix stored in memory unit SH, in which case SH is entered in the CALL statement at the location of a. 'a' may be a real number in F format (with a decimal - e.g., 0.25); I is an integer designating the memory unit containing B; J is an integer designating the memory unit to contain C; nr is an integer equal to the number of rows of B and C; and nc is an integer equal to the number of columns of B and C. .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>SIMLN\& This subroutine is used to obtain the solution for simultaneous linear equations of the form: .br.i 7;XB#=#Y .br;where X is an nr x nr matrix; Y is an nr x ns matrix; and B is an r x s matrix. X and Y are given and adjoined horizontally to form matrix A: .br.i 7;A#=#[X,Y], .br;so that A is a matrix with nr rows and nc = nr#+#ns columns. Matrix A is input into the subroutine. A solution for matrix B is obtained. .br; The number of columns of A must be ^&less\& than the size of the memory units. .br;Program statement: .br.i 7;CALL #SIMLN (SI, SJ, nr, nc) .br.i 7;CALL XSIMLN (NRMI, NRMJ, SI, SJ, nr, nc) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing A; J is an integer designating the memory unit containing B; nr is an integer equal to the number of rows of A and B; and nc is an integer equal to the number of columns of A (must be ^&less\& than the size of the memory units). .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>SUB\& This subroutine is used to perform matrix subtraction: .br;########A#-#B#=#C .br;Program statement: .br.i 7;CALL #SUB (SI, SJ, SK, nr, nc) .br.i 7;CALL XSUB (NRMI, NRMJ, NRMK, SI, SJ, SK, nr, nc) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing matrix A; J is an integer designating the memory unit containing matrix B; K is an integer designating the memory unit to contain matrix C; nr is an integer equal to the number of rows of the matrices; and nc is an integer equal to the number of columns of the matrices. .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>TRACE\& This subroutine computes the trace of a square matrix, A. .br;Program statement: .br.i 7;CALL #TRACE (SI, n, SJ) .br.i 7;CALL XTRACE (NRMI, NRMJ, SI, n, SJ) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing matrix A; n is an integer equal to the order of A; and J is an integer designating the memory unit to contain the trace as a 1 x 1 matrix. (Note - the trace may be output as a FORTRAN constant.) .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>TRNSP\& This subroutine is used to transpose a matrix: .br.i 7;Transpose of A = A' .br;Program statement: .br.i 7;CALL #TRNSP (SI, SJ, nr, nc) .br.i 7;CALL XTRNSP (NRMI, NRMJ, SI, SJ, nr, nc) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing A; J is an integer designating the memory unit to contain A'; nr is an integer equal to the number of rows of A and columns of A'; and nc is an integer equal to the number of columns of A and rows of A'. .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>XTX\& This subroutine premultiplies a matrix A by its transpose: .br.i 7;A'A#=#B .br;Note - number of columns of A must be ^&less\& than the size of the memory units. .br;Program statement: .br.i 7;CALL #XTX (SI, SJ, nr, nc) .br.i 7;CALL XXTX (NRMI, NRMJ, SI, SJ, nr, nc) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing A; J is an integer designating the memory unit to contain B; nr is an integer equal to the number of rows of A; and nc is an integer equal to the number of columns of A (must be ^&less\& than the size of the memory units). .br; Note - B will be a matrix of order nc x nc. .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>XXT\& This subroutine postmultiplies a matrix A by its transpose: .br.i 7;AA'#=#B .br;Note - number of rows of A must be ^&less\& than the size of the memory units. .br;Program statement: .br.i 7;CALL #XXT (SI, SJ, nr, nc) .br.i 7;CALL XXXT (NRMI, NRMJ, SI, SJ, nr, nc) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing A; J is an integer designating the memory unit to contain B; nr is an integer equal to the number of rows of A (must be ^&less\& than the size of the memory units); and nc is an integer equal to the number of columns of A. .br; Note - B will be a matrix of order nr x nr. .s 1 .end list .subtitle Elementwise operations .page .tp 8.C; Elementwise Operations .index Elementwise Operations .list .p 5, 0, 5.lm 0.le;^&Subroutine__<>ABS\& This subroutine is used to create a matrix containing the absolute value of each of the entries of a given matrix: .br.i 7;Abs[a(i,j)] = b(i,j) .br;Program statement: .br.i 7;CALL #ABS (SI, SJ, nr, nc) .br.i 7;CALL XABS (NRMI, NRMJ, SI, SJ, nr, nc) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing A; J is an integer designating the memory unit to contain B; nr is an integer equal to the number of rows of the matrices; and nc is an integer equal to the number of columns of the matrices. .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>ELEDI\& This subroutine is used to perform elementwise division of entries in two matrices to create a third matrix: .br.i 7;a(i,j)/b(i,j) = c(i,j) .br;Matrices A and B must be the same order which will be the order of C. .br;Program statement: .br.i 7;CALL #ELEDI (SI, SJ, SK, nr, nc, iflag) .br.i 7;CALL XELEDI (NRMI, NRMJ, NRMK, SI, SJ, SK, nr, nc, iflag) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing A; J is an integer designating the memory unit containing B; K is an integer designating the memory unit to contain C; nr is an integer equal to the number of rows of the matrices; nc is an integer equal to the number of columns of the matrices; and iflag is an integer flag to tell the program what to do when division by zero is attempted. If set to 0 the program will stop if matrix B has any zero elements. If set to 1 the program will insert a zero into those elements of C for which a zero element of B was found. .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>ELEML\& This subroutine is used to perform elementwise multiplication of the entries in two matrices to create a third matrix: .br.i 7;a(i,j)xb(i,j) = c(i,j) .br;Matrices A and B must be the same order which will be the order of C. For example, a single matrix may be used as both A and B, thus obtaining in C the squares of the entries in F. .br;Program statement: .br.i 7;CALL #ELEML (SI, SJ, SK, nr, nc) .br.i 7;CALL XELEML (NRMI, NRMJ, NRMK, SI, SJ, SK, nr, nc) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing A; J is an integer designating the memory unit containing B; K is an integer designating the memory unit to contain C; nr is an integer equal to the number of rows of the matrices; and nc is an integer equal to the number of columns of the matrices. .s 1 .tp 8.p 5, 0, 5.lm 0.le;^&Subroutine__<>RECIP\& This subroutine is used to create a matrix containing the reciprocals of the entries of a given matrix: .br.i 7;[1/a(i,j)]#=#b(i,j) .br;Program statement: .br.i 7;CALL #RECIP (SI, SJ, nr, nc, iflag) .br.i 7;CALL XRECIP (NRMI, NRMJ, SI, SJ, nr, nc, iflag) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing A; J is an integer designating the memory unit to contain B; nr is an integer equal to the number of rows of the matrices; and iflag is an integer flag to tell the program what to do when division by zero is attempted. If set to 0, the program will insert a zero when a corresponding zero element in A is found. If set to 1, processing is to stop when an entry of zero is found in A. .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>SQRT\& This subroutine is used to create a matrix containing the square roots of the elements in a given matrix: .br.i 7;Square root of [a(i,j)] = b(i,j) .br;Program statement: .br.i 7;CALL #SQRT (SI, SJ, nr, nc, eps) .br.i 7;CALL XSQRT (NRMI, NRMJ, SI, SJ, nr, nc, eps) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing A; J is an integer designating the memory unit to contain B; nr is an integer equal to the number of rows of the matrices; nc is an integer equal to the number of columns of the matrices; and eps is a FORTRAN constant which is negative and small in absolute value. If an entry in A is negative but less than eps in absolute value, this entry is converted to zero in B. If an entry in A is more negative than eps, processing is stopped. A possible value might be -0.001. Note that in computing, an expected value of zero might be slightly less than zero (i.e., negative) due to rounding. .end list.s 1 .index Data Handling Operations .page.tp 8.C; Data Handling Operations .subtitle Data Handling Operations .list.p 5, 0, 5.lm 0.le;^&Subroutine__<>COPY\& This subroutine is used to copy a matrix from one memory unit to another. .br;Program statement: .br.i 7;CALL #COPY (SI, SJ, nr, nc) .br.i 7;CALL XCOPY (NRMI, NRMJ, SI, SJ, nr, nc) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing the matrix; J is an integer designating the memory unit to contain the matrix; nr is an integer equal to the number of rows of the matrix; and nc is an integer equal to the number of columns of the matrix. .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>DIAG\& This subroutine is used to create a diagonal matrix D containing the diagonal entries of a square matrix A. .br;Program statement: .br.i 7;CALL #DIAG (SI, SJ, n) .br.i 7;CALL XDIAG (NRMI, NRMJ, SI, SJ, n) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing A; J is an integer designating the memory unit to contain D; and n is an integer equal to the number of rows and columns of A and D. .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>HORIZ\& This subroutine is used to horizontally 'join' two matrices, X and Y, together to form a new 'super' matrix A. Matrices X and Y both have nr rows. .br.i 7;A#=#[X,Y] .br;Let X have 'x' columns and Y have 'y' columns; A will have c#=#x#+#y columns (the first x columns from matrix X and the last y columns from matrix Y). .br;Program statement: .br.i 7;CALL #HORIZ (SI, SJ, SK, nr, nx, ny) .br.i 7;CALL XHORIZ (NRMI, NRMJ, NRMK, SI, SJ, SK, nr, nx, ny) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing X; J is an integer designating the memory unit containing Y; K is an integer designating the memory unit to contain A; nr is an integer equal to the number of rows of each matrix; nx is an integer equal to the number of columns of X; and ny is an integer equal to the number of columns of Y. .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>PARTT\& This subroutine is used to select a rectangular section or partition of a matrix A and copy this section into a new matrix B. The beginning row of the section in matrix A is 'nrb' and the ending row is 'nre'. The beginning column is 'ncb' and the ending column is 'nce'. .br;Program statement: .br.i 7;CALL #PARTT (SI, SJ, nrb, nre, ncb, nce) .br.i 7;CALL XPARTT (NRMI, NRMJ, SI, SJ, nrb, nre, ncb, nce) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing matrix A; J is an integer designating the memory unit to contain matrix B; nrb is an integer equal to the beginning row number of the section; nre is an integer equal to the ending row number of the section; ncb is an integer equal to the beginning column number of the section; and nce is an integer equal to the ending column number of the section. .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>RO2DI\& This subroutine is used to create a diagonal matrix D whose elements along the diagonal are entries from the first row of a second matrix A. .br;Program statement: .br.i 7;CALL #RO2DI (SI, SJ, n) .br.i 7;CALL XRO2DI (NRMI, NRMJ, SI, SJ, n) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing matrix A; J is an integer designating the memory unit to contain D; and n is an integer equal to the order of A. .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>RO2MT\& This subroutine is used to create a matrix B for which every row is identical to the first row of a given matrix A. The first row of matrix A is copied nr times to form a matrix B. This operation is the same as the matrix product: .br.i 7;(1)A#=#B .br;where (1) is a column vector with nr entries of unity. .br;Program statement: .br.i 7;CALL #RO2MT (SI, SJ, nr, nc) .br.i 7;CALL XRO2MT (NRMI, NRMJ, SI, SJ, nr, nc) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing row vector/matrix A; J is an integer designating the memory unit to contain matrix B; nr is an integer equal to the number of rows of B; and nc is an integer equal to the number of columns of A and B. .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>VRTCL\& Given two matrices X and Y, each having nc columns, a new matrix A is formed by adjoining matrices X and Y vertically: .br.i 7;A#=###X .br.i 7;######Y .br;Let X have 'x' rows and Y have 'y' rows; A will have r#=#x#+#y rows (the first x rows of A will be from X and the last y rows of A will be from Y). .br;Program statement: .br.i 7;CALL #VRTCL (SI, SJ, SK, nx, ny, nc) .br.i 7;CALL XVRTCL (NRMI, NRMJ, NRMK, SI, SJ, SK, nx, ny, nc) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing X; J is an integer designating the memory unit containing Y; K is an integer designating the memory unit to contain A; x is an integer equal to the number of rows of X; y is an integer equal to the number of rows of Y; and nc is an integer equal to the number of columns of the matrices. .s 1 .end list .p 5, 0, 5.lm 0 .subtitle Statistical Programs .page.tp 8.C; Statistical Operations .index Statistical Operations .s 1.tp 8.C; A.##Factor Analytic and Correlational Methods .index Factor Analytic Methods .index Correlational Methods .s 1.list.p 5, 0, 5.lm 0.le;^&Subroutine__<>DAPPR\& This subroutine is used to obliquely rotate a factor loading matrix, using either a 'mechanical' rotator (termed artificial personal probability) or a rotation 'directed' by the user (i.e., input is in the form of probability of being in the hyperplane). .br;Program statement: .br.i 7;CALL #DAPPR (SI, SJ, SK, SL, SM, SN, SO, SP, SQ, nat, nf, .br.i 6;1 mcase, mpj, mapp, mprin, pcon, wcon, coslt, ncyclt) .br.i 7;CALL XDAPPR (NRMI, NRMJ, NRMK, NRML, NRMM, NRMN, NRMO, .br.i 6;1 NRMP, NRMQ, SI, SJ, SK, SL, SM, SN, SO, SP, SQ, nat, nf, .br.i 6;2 mcase, mpj, mapp, mprin, pcon, wcon, coslt, ncyclt) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing the original factor matrix; J is an integer designating the memory unit to contain the N' matrix of hyperplane normals; K is an integer designating the memory unit containing matrix P during solution and converted to B for output (see MPJ); L is an integer designating the memory unit to contain APP (see note concerning mapp); M is an integer designating the memory unit containing the inverse of NN' and will contain PHI for output; N, O, P, and Q are integers designating some 'scratch' memory units (i.e., memory units that the computer can work with to obtain an answer); nat is the number of attributes (variables); nf is the number of factors; mcase is an integer flag for APP function. Set mcase#=#1 for one sided function (e.g., you expect the factors to have a positive manifold). Set mcase#=#2 for a two sided function (e.g., factors will correlate both positively &a&n&d negatively with one another); mpj is an integer flag for initial weights hypothesized. Set mpj#=#0 for initial weights to be obtained by a VARIMAX rotation. Set mpj#=#1 for initial hypothesis factor weights to be input in SK; mapp is an integer flag concerning iteration of APP. Set mapp#=#0 for APP iteration. Set mapp#=#1 for a fixed APP as input to SL; mprin is an integer flag concerning the printing of technical output. Set mprin#=#0 for printed output. Set mprin#=#1 for printing matrices APP and P on each cycle; pcon is a power constant in APP function (set it to 10.0); wcon is the proportion of mean absolute factor weight for APP (set it to 0.5); coslt is a limit for COS between successive trial normals in test for convergence (set it to 0.99999); and ncyclt is the maximum number of iteration cycles (set it to 20). .s 1; To fit a hypothetical matrix, the input to APP is the probability of being in the hyperplane. This is another way of saying the probability of ^&NOT\& loading on the factor. If you have a matrix of probabilities of loading of the factor, then subract them from 1.0. Let MAPP#=#1 and set MPJ#=#1. .s 1 .tp 9 .p 5, 0, 5.lm 0.le;^&Subroutine__<>FAHIR\& This subroutine does factor analysis using the highest covariance (or correlation if the input matrix is a correlation matrix) as communality estimate. .br;Program statement: .br.i 7;CALL #FAHIR (SI, SJ, SK, SL, nat, nf) .br.i 7;CALL XFAHIR (NRMI, NRMJ, NRMK, NRML, SI, SJ, SK, SL, nat, nf) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing the covariance (or correlation) matrix; J is an integer designating the memory unit to contain the covariance (or correlation) matrix with the highest covariances (or correlations) on the diagonal; K is an integer designating the memory unit to contain the factor matrix; L is an integer designating the memory unit to contain the communalities for each factor per variable; nat is the number of attributes (variables); and nf is the number of factors desired. If nf is greater than the number of positive eigenvalues, nf will be changed. Therefore nf should &n&o&t be input as a number, but as a variable (see FORTRAN constants). .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>FAWMV\& This subroutine does factor analysis using the multiple variance (or correlation if the input matrix is a correlation matrix) as communality estimate. If the matrix is singular the highest covariance is used as the communality estimate (see FAHIR above). .br;Program statement: .br.i 7;CALL #FAWMV (SI, SJ, SK, SL, nat, nf) .br.i 7;CALL XFAWMV (NRMI, NRMJ, NRMK, NRML, SI, SJ, SK, SL, nat, nf) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing the covariance (or correlation) matrix; J is an integer designating the memory unit to contain the covariance (or correlation) matrix with the multiple variances (or correlations) on the diagonal; K is an integer designating the memory unit to contain the factor matrix; L is an integer designating the memory unit to contain the communalities for each factor per variable; nat is the number of attributes (variables); and nf is the number of factors desired. If nf is greater than the number of positive eigenvalues, nf will be changed. Therefore nf should &n&o&t be input as a number, but as a variable (see FORTRAN constants). .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>ITPFA\& This subroutine is used to compute communalities by the iterated principal components method. .br;Program statement: .br.i 7;CALL #ITPFA (SI, SJ, SK, SL, SM, nat, nf) .br.i 7;CALL XITPFA (NRMI, NRMJ, NRMK, NRML, NRMM, SI, SJ, SK, SL, .br.i 6;2 SM, nat, nf) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing the input covariance (or correlation) matrix; J is an integer designating the memory unit to contain the factor matrix; K and L are integers designating temporary 'work' matrices for the computer; M is an integer designating the memory unit to contain the covariance (or correlation) matrix with the communality estimates on the major diagonal; nat is an integer equal to the number of attributes (variables); and nf is an integer equal to the number of factors. .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>LSHYP\& This subroutine is used to rotate a factor matrix to form a best (least squares) hyperplane fit to a matrix selected by the user. .br;Program statement: .br.i 7;CALL #LSHYP (SI, SJ, SK, SL, SM, SN, nr, nc, iflag) .br.i 7;CALL XLSHYP (NRMI, NRMJ, NRMK, NRML, NRMM, NRMN, SI, SJ, .br.i 6;2 SK, SL, SM, SN, nr, nc, iflag) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing the input factor matrix; J is an integer designating the memory unit containing the selection matrix (all 0s or 1s - 0 if in the factor and 1 if not); K is an integer designating the memory unit to contain the normal matrix (transposed); L, M, and N are integers designating temporary 'work' memory units to be used by the computer; nr is an integer equal to the number of rows of both SI and SJ; nc is an integer equal to the number of columns of both SI and SJ; and iflag is an integer equal to 0 if the user wants to skip intermediate technical results or 1 to print out intermediate results. .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>MISNR\& This subroutine is used to compute a correlation matrix (when some missing data exists). .br;Program statement: .br.i 7;CALL #MISNR (SI, SJ, SK, SL, SM, SN, SO, SP, SQ, SR, ns, .br.i 6;2 nat, iopt, ione) .br.i 7;CALL XMISNR (NRMI, NRMJ, NRMK, NRML, NRMM, NRMN, NRMO, NRMP, .br.i 6;2 NRMQ, NRMR, SI, SJ, SK, SL, SM, SN, SO, SP, SQ, SR, ns, .br.i 6;3 nat, iopt, ione) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing the raw data; J is an integer designating the memory unit to contain the means of the variables (if options 5 or 6 are used, this matrix has the means for row variables when there is data for this variable and the column variable); K is an integer designating the memory unit to contain the variances of the variables (if options 6 or 8 are used, this matrix has the means for column variables when there is data for this variable and the row variable); L#is an integer designating the memory unit to contain the covariance matrix; M#is an integer designating the memory unit to contain the correlation matrix; N is an integer designating the memory unit containing information on how missing data is stored; O, P, and Q are integers designating memory units containing matrices the computer can use to store intermediate results; R#is an integer designating the memory unit to contain the sample sizes for pairwise correlations; ns is an integer describing the number of subjects in the data (number of useful rows in SI); nat is an integer describing the number of variables (attributes) in the data (number of columns in SI); iopt is an integer flag describing numerous options on handling missing data: .nojustify.nofill iopt result 1 Compute vector of means and sample sizes only. 2 Compute correlation, etc. matrices but do &n&o&t check for missing data (will give incorrect results if missing data is present). 3 Replace missing data by mean. 4 Delete all of the subject's data if there is any missing data. 5 Compute covariances based on available pairs of data. Means and covariances will be based on avail- able pairwise data for that pair of variables only. Correlations will be based on these covariances and variances from the diagonal of the covariance matrix. 6 Compute pairwise covariances as in 5 above. Estimates of variances (for correlations) are based on pairwise data for that pair of variables only. 7 Covariances are based on available pairs, however the full data means will be utilized. Correlations will be based on full data variances (diagonal of covariance matrix). 8 Covariance matrix computed as in 7 above. Correlations use the pairwise data variances (as in option 6 above). .fill.justify .SUBTITLE Monte Carlo Programs ione is an integer containing either -1, 0, or +1. The integer is added to the sample size (N) in the denominator of the variances and covariances. For example, if -1 is input the variance will be computed by (Sum#of#Squares)/(N#-#1). This will result in the unbiased variance estimate. When ione is 0 the result will be the maximum likelihood estimate. When ione is +1 the result is a minimum error estimate. .s 1.lm 3;[Note: As a special option (only for the most advanced users) one can generate cross product and normed cross product matrices. That is, occassionally it is useful ^¬\& to subtract the mean in computations for either the covariances or the correlations. The covariances will be cross products and the correlations are called normed (i.e., made to unit length) cross products. To use this option, place immediately after the "COMMON/B/I1" statement a new statement "COMMON/KMISNR/KMISNR", then somewhere before the call to MISNR put in the statement ">KMISNR = 1". In order to compute regular correlations again set "KMISNR = 0" (i.e., to again subtract the mean in the calculations). .lm 0.S 1.p 5, 0, 5.lm 0.le;^&Subroutine__<>VARMX\& This subroutine is used to rotate a factor matrix orthogonally to the VARIMAX criterion. .br;Program statement: .br.i 7;CALL #VARMX (SI, SJ, SK, nat, nf) .br.i 7;CALL XVARMX (NRMI, NRMJ, NCMJ, SI, SJ, nat, nf, SK, mkraw) .lm +5.p -3, 0, 5.br;where: I is an integer designating the memory unit containing the input factor matrix; J is an integer designating the memory unit to contain the factor loading matrix; K is an integer designating a temporary 'work' ^&vector\& for the computer; nat is an integer equal to the number of attributes (variables); nf is an integer equal to the number of factors; and mkraw is an integer flag. If set to 0 a raw (unweighted) solution will be done. If set to 1 a normalized solution is performed. .END LIST [Note - the 'X' version is slightly different in form from the 'non-X' version.] .tp 8.C;B.##Monte Carlo Programs .SUBTITLE Discriminant Analysis .S 1.index Monte Carlo Programs .lm 10.rm -10 Note - A full description of the following Monte Carlo programs will not be given. For more detailed information see FORMAL.DOC. .lm 0.rm +10 .s 1.list.p 5, 0, 5.lm 0.le;^&Subroutine__<>RANDQ\& This subroutine is used to generate a sample SSCP (Sum of Squares and Cross Products) matrix and a mean vector. The data has a multivariate normal distribution given a population mean and a covariance matrix. .s 1.p 5, 0, 5.lm 0.le;^&Subroutine__<>RNDCR\& This program is used to compute matrices containing means, standard deviations, covariances and correlations from the matrices of products and sums. .s 1 .p 5, 0, 5.lm 0.le;^&Subroutine__<>RNDVC\& This program is used to generate a vector of random normal deviates, mean = 0 and standard deviation = 1, randomly sorted. .s 1.p 5, 0, 5.lm 0.le;^&Subroutine__<>TSAMX\& This program is used to generate a vector of random normal deviates with a given population mean vector and a covariance matrix. .end list.s 1.p 5, 0, 5.lm 0 .s 1.TP 9.tp 8.C; C.##Discriminant Analysis .index Discriminant Analysis Note - A full description of the following Monte Carlo programs will not be given. For more detailed information see FORMAL.DOC. .s 1.p 5, 0, 5.lm 0;^&Subroutine__<>DISCR\& This subroutine is used to do a discriminant analysis. Input will be the hypothesis effect and denominator effect (error) Sum of Squares and Cross Products (SSCP). Output will be Phi, Lambda, Bartlett's V statistic, eigen roots and vectors of the total SSCP matrix, weight matrix and group means for the discriminant function. .s 1.tp 8.tp 8.C;D.##Analysis of Variance .index Analysis of Variance .s 1.p 5, 0, 5.lm 0;^&Subroutine__<>BALANO\& This subroutine is a general analysis of variance program applicable to a wide range of balanced designs. In the case of designs with a replication factor, BALANO allows inequality in the number of replications in each cell. If the number of replications is equal or proportional, the analysis is handled by least squares (weighted means). If the number of replications is not proportional, then an unweighted means analysis is performed. This is an approximation to the least squares solution. BALANO accepts some designs that are not completely crossed, namely those nested designs in which all main factors are balanced. Hence hierarchical designs are allowed. Repeated measure designs are allowed as well. In these designs the replication factor is not nested in all of the other factors. .br;Program statement: .br.i 7;CALL BALANO (NRMI, NRMJ, NRMK, SI, SJ, SK, SL, NRI, NCJ, .br.i 6;1 nf, ndep, xmis, iflag1, iflag2, iflag3) .lm +5.p -3 0 5.br;where: I is an integer designating the memory unit to contain the data and level numbers to be input to BALANO. Each observation (row of data) input to BALANO must be identified by a number for each factor including the replication factor. These numbers represent the levels of the corresponding factors and must precede the dependent variables. In the output produced by BALANO, each factor is given a unique letter name beginning with A. Thus the first column of the data matrix corresponds to the levels of factor A which is described in the first row of the factor specification matrix, SJ (see below). Each additional factor is given the next letter in the alphabet and a corresponding row in the factor specification matrix. The dependent variables follow the factor levels on each row in the data matrix and are numbered one through the total number of dependent variables in the output of the program. For example, a row in SI contains the following data: 9. 8. 7. 6. 5. Assuming that this design has three factors and two dependent variables then 9, 8, and 7 are the levels for the factors A, B, and C respectively. 6 and 5 are dependent variables 1 and 2 respectively. It does not matter what order the rows are in, as long as the dependent variables correspond to the levels input in the same row in matrix SI. J is an integer designating the memory unit to contain the factor specification matrix. Each row in this matrix corresponds to a factor in the order in which the factors appear in the data matrix SI (i.e. the first row in the factor specification matrix corresponds to the first column in the data matrix, etc.). There must be one row in the matrix SJ for each factor. Each column in the factor specification matrix corresponds to the following parameters: .TP 8.lm +5.br;Column Description .br;##1 # 0 if it is the fixed factor. .br;# # 1 if it is the random factor. .s 1;##2 # 0 if it is not the replication factor. .br;# # 1 if it is the replication factor. .s 1;#3-11 # Factors in which this factor is nested. .lm -5.s 1;All elements in the factor specification matrix which are not used must be set to zero. K is an integer designating a one dimensional 'scratch' memory unit that has been dimensioned as SK(NRMK). If the dimension NRMK is too small, BALANO will output a minimum required value for you. L is an integer designating a vector that contains the number of levels for each factor, i.e. SL(1) contains the number of levels of the first factor, SL(2) contains the number of levels of the second factor, etc. All locations in SL not used are set to zero. This memory unit must be dimensioned as SL(10). NRI is an integer equal to the number of rows of the data matrix SI. NCJ is an integer equal to the number of columns of the factor specification matrix SJ. This number need only be large enough so that all non-zero values are within the matrix. nf is the number of factors including the replication factor (if there is one). Maximum = 10. ndep is the number of dependent variables. xmis is the code for missing data for the dependent variable in matrix SI. If there is no missing data, then xmis should be set to a value not found in any of the data which is input to the data matrix SI. iflag1 is +1 if the user desires to do an unweighted means analysis even though proportional cell frequencies could be found. iflag2 is +1 to suppress printing of all means .lm +7;-1 to suppress printing of all interaction means .br;-2 to suppress printing of all level means. .lm -7; iflag3 is the factor number for which printing of interaction means is to be suppressed (only one factor number allowed). .lm 0.p 5 0 5.s 1 A numerical example from Winer, page 376 (table 7.8-3), is illustrated here using BALANO. TEST.FOR is the calling program that you want to run. .nofill.nojustify .s 1 .EX TEST.FOR,FORMAL.REL/SEARCH,REL:IMSL/SEARCH .s 1 The program TEST.FOR for this example is listed below. .s 1 IMPLICIT DOUBLE PRECISION(A-H,O-Z) DIMENSION S1(36,4),S2(3,3),S3(147),S4(10) CALL IOPUT('BALDAT.DAT','BALOUT.DAT',3) CALL XINPUT(36,S1) CALL XINPUT (3,S2) CALL XINPUT(10,S4) CALL BALANO(36,3,147,S1,S2,S3,S4, 1 36,3,3,1,999.,0,0,0) STOP END .s 1 The data file (BALDAT.DAT in line 3 of the program above) to be input to BALANO is listed below: .s 1 00360004(4F3.0) 1 1 1 3 1 2 1 6 1 3 1 9 1 1 2 6 1 2 2 10 1 3 2 14 1 1 3 10 1 2 3 15 1 3 3 18 2 1 4 8 (e.g., factor A - level 2; factor B - level 1; factor 2 2 4 12 C - level 4; score on dependent variable is 8) 2 3 4 16 2 1 5 3 2 2 5 5 2 3 5 8 2 1 6 1 2 2 6 3 2 3 6 8 2 1 7 12 2 2 7 18 2 3 7 26 2 1 8 9 2 2 8 10 2 3 8 18 3 1 9 10 3 2 9 22 3 3 9 16 3 1 10 3 3 2 10 15 3 3 10 8 3 1 11 7 3 2 11 16 3 3 11 10 3 1 12 5 3 2 12 20 3 3 12 12 00030003(3F3.0) 0 0 0 (factor A is a fixed factor) 0 0 0 (factor B is a fixed factor) 1 1 1 (factor C, the replication factor, is random and nested in 00100001(F3.0) factor A) 3 (factor A has 3 levels) 3 (factor B has 3 levels) 12 (the subjects factor C has 12 levels or subjects) 0 0 (Note: these were set to zero) 0 0 0 0 0 .fill.justify; Part of the output file that BALANO will print for you (BALOUT.DAT in line 3 of the program above) is listed below. .nofill.nojustify SOURCE DEG OF FREEDOM SUM OF SQUARES MEAN SQUARE F RATIO PROB. NUM DEN A 2 9 0.22933333E+02 0.11466667E+02 0.1685 0.8476 C 9 0.61262222E+03 0.68069136E+02 B 2 18 0.36505556E+03 0.18252778E+03 84.0759 0.0000 AXB 4 18 0.19586667E+03 0.48966667E+02 22.5550 0.0000 BXC 18 0.39077778E+02 0.21709877E+01 FACTOR C IS THE REPLICATION FACTOR AND C HAS AN UNEQUAL NUMBER OF LEVELS FOR EACH COMBINATION OF LEVELS OF THE FACTORS IN WHICH IT IS NESTED. HOWEVER THE NUMBER OF LEVELS ARE PROPORTIONAL AND HENCE THE DESIGN IS BALANCED. THE ANALYSIS OF VARIANCE IS EXACT EXCEPT FOR TRUNCATION AND ROUNDING ERRORS. .fill.justify .page .subtitle Advanced Techniques .tp 8.C;Advanced Techniques .index Advanced Techniques .LIST.s 1.p 5, 0, 5.lm 0.le;^&Subroutine__<>IOPUT\& This subroutine will allow the user to write to any file (including the line printer or tape) and read the input data from any file (including the card reader or tape). .br;Program statement: .i 7;CALL IOPUT('input string', 'output string', iflag) .lm +5.p -3, 0, 5.br;where: 'input string' is the name of the file containing input data. The form of this string can be 'dev:filenm.ext[p,pn,sfd...]' (the most common form of this string will be 'filenm.ext'). When the user elects not to use this subroutine or uses option 2 or 3 the program will read its data from a file called FRMLIN.DAT. 'output string' is the name of the file to contain the output from FORMAL. The form of this string is identical to 'input string' above. When the user does not use this subroutine or uses option 1, the filenm.ext will default to FRMLOT.DAT; and iflag is an integer flag to indicate what actions this program will take: .nojustify.nofill 1 - only open the input file (output will still be FRMLOT.DAT). 2 - only open the output file (input will still be FRMLIN.DAT). 3 - open both the input and output files. .justify.fill.lm 0.p 5,0,5 By use of this subroutine one can read a data file that is on disk rather than using a deck of cards. In this case leave out the data and the $DATA cards (e.g., cards 48 through 54 in the Card Pack for Example) and replace them with a '$EXECUTE' card (beginning in column 1). In the above subroutine, prefix the input data disk file name with 'DSK:'. For example, if there were a data file called 'FILE.DAT' in the user area _<1234,567_> and you wanted the output to print on the line printer as usual, insert the following card before the first INPUT command: .br.i 7;CALL IOPUT ('DSK:FILE.DAT_<1234,546_>','FRMLOT.DAT',1) .br;Note: if the user area is your own you may omit the ppn numbers and their brackets. .s 1.p 5, 0, 5.lm 0.le;^&Subroutine__<>TINPT\& This subroutine will allow the user to input data from any data set or new file name. .br;Program statement: .i 7;CALL #TINPT ('input string', SI) .i 7;CALL XTINPT (NRMI, 'input string', SI) .lm +5.p -3, 0, 5.br;where: 'input string' is the name of the file containing input data; the form of this string can be 'dev:filenm.ext[p,pn,sfd...]' (the most common form of this string will be 'filenm.ext'); and I is an integer designating the memory unit to contain the new input matrix. .end list.p 5, 0, 5 .lm 0 The form of the 'input string' is the same as in IOPUT above. Before the use of this program the user must have the device name assigned to unit 25. That is, the user must have made an open similar to: .index <ASSIGN statement .subtitle Advanced Techniques/Terminal Usage/Debugging Aids .i 6;_.ASS DSK 25 .br;within the TOPS10 calls or at the terminal (other more advanced methods are possible by use of the logical device name and a COMMON statement). .subtitle Use at Terminal .s 1.tp 8.tp 8.C;Use at Terminal .index Use at Terminal .s 1 To use FORMAL from the terminal one must put the program in one file, which has an extension of FOR (e.g., HWTEST.FOR), and the input data in a second file. The input data file can have any name but the computer will default to 'FRMLIN.DAT' if the user does not provide a input file name (to do this see IOPUT above). The output will be in a third file, again with any name as defined in IOPUT above or with the default value of 'FRMLOT.DAT'. To run FORMAL from the terminal either type the following into a file (e.g., HWTEST.CTL) or type it into the terminal as you sit there: .nofill.nojustify.lm 6 _.ASS DSK 2 (if the user wants to input data from the terminal instead of the the disk change DSK above to TTY)

_.ASS DSK 3 (if the user wants to have the output go automatically to the line printer do not enter this line; if the user wants to have the output automatically appear at the terminal change 'DSK 3' to 'TTY 3') _.EX progname.FOR,FORMAL.REL[1413,546]/SEARCH (if the user is running BALANO, insert the following after SEARCH: ".../SEARCH,REL:IMSL.REL/SEARCH") _.Q progname.FOR,'input.file','output.file' (if the _.ASS DSK 2 line is changed to TTY 2 there will be no input file so leave out the 'input.file', if the _.ASS DSK 3 statement is not present or changed to TTY 3 there will be no 'output.fil' so leave 'output.fil' out of this 'print' command) .justify.fill.lm 0 .br;where progname.FOR is the name of the FORMAL program (e.g., HWTEST.FOR). If the user has created a file as above (e.g., HWTEST.CTL), to run it type: .i 6;_.<>SUBMIT HWTEST.CTL .br;in order to have the program run at batch and submitted automatically. Otherwise type: .i 6;_.<>DO HWTEST.CTL .br;to have the program run semi-automatically (in front of the user at the terminal). .subtitle Advanced Debugging Aids .s 1.tp 8.C; Advanced Debugging Aids .index Advanced Debugging Aids .s 1 Throughout FORMAL every attempt was made to anticipate and minimize possible user errors and lessen their effect if made. Nevertheless, errors will occur. When FORMAL finds an error the program will attempt to describe what the error is and where it is found. In describing the location of the error three variables are frequently printed out: call statement number, subroutine number, and depth. The call statement number, >ipgm in the program, is the current number of .index Call Statement Number FORMAL call statements made from the user's program. That is, if an error was seen in the 25th call to FORMAL, the call statement number will be 25. The subroutine number, >isub in the program, is the number of subroutines .index Subroutine Statement Number used indirectly since the last call in the user's program. That is, most programs call other programs and isub is the number of such calls. .index Depth Depth, >izncr in the program, will be 0 at all FORMAL calls from the user's program; it will be 1 at all FORMAL calls made one subroutine away from the main program; it will be 2 at all FORMAL calls made two subroutines away from the main program, etc. .s 1 For example, let us suppose that the 25th call were to INVRS and the input matrix was singular. E.g., let us suppose that in the Example Card Pack one of the variables had zero variance. Then: .nofill.nojustify.s 1 A call to INVRS will call XINVRS, XINVRS calls XDIMCH then returns to XINVRS, XINVRS calls XDIMCH then returns to XINVRS, XINVRS calls XDIMCH then returns to XINVRS, XINVRS calls XDIMCH then returns to XINVRS, XINVRS calls QMINVZ, QMINVZ calls XDIMCH then returns to QMINVZ, QMINVZ calls XDIMCH then returns to QMINVZ, QMINVZ calls XDIMCH then returns to QMINVZ, and finally QMINVZ calls QWRGDM. .s 1 The following output would be seen: * * * * * T I L T * * * * * * * * * * THE MATRIX PASSED WAS SINGULAR NO INVERSE WAS POSSIBLE. FATAL ERROR IN THE INVRS PROGRAM. THIS WAS THE 25-TH CALL MADE BY YOU TO THE FORMAL LIBRARY. ACTUALLY 10 MORE CALLS WERE MADE TO THE FORMAL PACKAGE (INTERNALLY), CURRENT DEPTH: 3 * * * * * PROCESSING MUST TERMINATE PREMATURELY * * * * * .s 1 .fill.justify.lm 0 You may note that ten subroutine calls were made (internally) by FORMAL subroutines: once to XINVRS, QMINVZ, and QWRGDM and seven times to XDIMCH. The depth is three when FORMAL calls XINVRS. Then XINVRS eventually calls QMINVZ and QMINVZ calls QWRGDM which describes the error. .page.do index is three when FORMAL calls XINVRS. Then XINVRS eventually calls QMINVZ and QMINVZ calls QWRGDM which describes the error. .page.do index L calls XINVRS. Then XINVRS eventually calls QMINVZ and QMINVZ calls QWRGDM which describes the error. .page.do index is three when FORMAL calls XINVRS. Then XINVRS eventually calls QMINVZ and QMINVZ calls QWRGDM which describes the error. .page.do index