Computer8 Math. Applic. Vol. 25, No. 6, pp. 3-14, 1993 Printed in Great Britain. All rights reserved
THE
NATURAL
REPRESENTATION
0097-4943/93 $6.00 + 0.00 Copyright(~) 1993 Pergamon Press Ltd
OF
REAL
NUMBERS
AUBREY M C I N T O S H AND J E N N I F E R BRODBELT Department of Chemistry, The University of Texas at Austin Austin, TX 78712-1167, U.S.A.
(Received October 1990 and in rcvimcd form November 1990) A b s t r a c t - - T h i s paper reports the modular design of software library components which read, write, add, subtract, multiply, and divide real valued numbea~ with attention to significant digits and digit grouping. Additionally, an example is pres~ated about how to use this module to make other library components to read, write, and manipulate data matrix files with attention to embedded prose documentation. These components can be used to apply literate programming to data files.
DISCUSSION There are several concerns in the development of scientific computer software. Modular libraries [1], friendliness [1,2] and literacy (technology transfer) [3,4] are mentioned in recent literature. Portability between machines remains an issue as well [3]. This paper explores an application of literate programming to scientific data itself. The software module, presented in this paper as PreciseP~eal, reads, writes, adds, subtracts, multiplies and divides real numbers. This package notes the significant digits without special user effort, manages those digits while doing arithmetic operations, and writes numbers with the indicated number of significant digits. Output numbers contain commas. Additional modules perform basic matrix operations using this Precisel~al module, and read and write matrix document files. Provisions are made for embedded comments within the matrix, as well as extensive prose documentation following the numerical part of the matrix. Recent research in computer operating systems emphasizes the idea of Text as a fundamental type of data in computer operations [2,5]. Additional work emphasized the use of computers to produce documentation [3] as well as utilize typefaces [6,7]. The literate program file Test.Mod, Figure 1, is an example from the public domain MacOberon operating system release by Michael Franz in Prof. N. Wirth's group at Computersysteme ETH Zurich. This document is simultaneously several things: (1) It is the source of a computer program which can be submitted exactly as is to the Oberon compiler. (2) It is a typeset version of a program which is more easily readable than many program listings. (3) It is, in the Oberon environment where it is presented, a complete section of a user manual that walks the user through a successful compile, execute and modify cycle. Figure 1 is not typeset or changed in any way from the file in the Oberon system; nor are there multiple versions of the file for printing, compilation, or on-line help. The system was designed where one single document serves all these purposes. This design of a data file format a s a complete document is powerful. Formulating the support for a natural representation for real numbers is just one component in this overall effort. This viewpoint of a data file as a complete This work has been supported by the Welch Foundation (F-1155), the National Science Foundation (Post-doctoral Starter Grant), and the Society of Analytical Chemists of Pittsburgh. Typeset by .AA~q-~X
4
A. MCINTOSH, J. BRODBELT MODULE Test; (* Simple Example *) IMPORT Texts, Oberon; VAR W: Texts.Writer; PROCEDURE Do*; BEGIN Texts.WriteString(W, "Hello"); Texts.WrlteLn(W); T~xts.Append(Oberon.Log, W.buf) END Do; BEGIN Texts.OpenWdter(VV) END Test. 1. Move the cursor into this viewer and press the Enter key on the keypad. This will cause the viewer to be marked (a star will appear). 2. Execute the command Compiler.Compile * (press control key over it). A star as a parameter always Indicates the marked viewer. 3. You may now Invoke the new command Teat.Do as often as you like. Just move the mouse cursor over it and press control. 4. Modify the program, for example by changing the text that is printed. 5. Compile again by invoking Compiler.Compile * as usual. 6. Execute Test.Do again: the changes you made in the program have no effect (yet), because the old version of module Testis still loaded. 7. You may (re-)load the latest version of a command by interclicking the mouse button during invocation (pressing the control key). Oberon Compiler Options
The Oberon Compiler accepts the following options: s Enable generation of new Symbol File x Disable Index Checks n Disable NIL Checks t Disable Type Checks r Enable Range Checks Each file parameter may be followed by a slash ("r) and a list of options.
Examples: Compiler.Compile */n Compiler.Compile ddt.Mod/s Hennessy.Mod/sxnt -
Figure 1. document departs from the historical viewpoint toward input and output in scientific computing. Typically, input and output from programs are very different, separate sets. However, even in a punch card based FORTRAN environment, this separation is not necessary: Listing output from a compiler can be legal FORTRAN statements, line numbers can be in the comment columns, and error messages can be comment records printed after the offending cards, but marked specially in columns 72-80. In that case, output punched into a new card deck could be re-entered into the compiler, and an uncorrected program would produce an output deck identical to itself. Perhaps more importantly, in such an environment a partially corrected deck of 2000 may be re-entered and the compiler would produce error listings for the updated work. Knuth's fundamental work emphasizes that our main programming task is not instructing a computer what to do, but rather explaining to human beings what we want the computer to do [3]. This viewpoint is anticipated to impact heavily the utilisation of existing quantum chemistry programs by new researchers [4]. Knuth's solution, WEB, allows one file to serve as a programmer's working medium, the program, and the typeset document image file. The use of a single file format for both input and output is also a cohesive concept in the setting where a program iterates to a solution. For example, there are methods which calculate
The n a t u r a l representation of real numbers
5
(Manually created and dated. August 1846. No input files used.)
( 5 (mass values rows), 4 (scans columns) } (rrVz)
(Successive scans.)
(background) (230.00) 0 (230.01) 0.9 (230.02) 1.5
0 0.8 1.4
0 0.9 1.5
0 1.1 1.3
(sample) (230.80) (230.81)
0.5 1.1
1 2.3
0.5 0.9
0 0
This prose continuss to be a part of the data file. Since it is any human readable text, a wide variety of material Is conformant. This part of the file offers much utility as, for example, program version annotations, copies of the Input data files, or even Bibliographic data can be placed here. This example matrix data file is inspired by a Mass Spec Facility data file from a sample that vaporized from the probe late in the run, and then was gone. The dimensionality of the data is enclosed in { }, and in this case comments are used to annotate it. This prose description continues and now changes subtly Into the actual formal specification of the data file (.rex3):
DRAFT
SPECIFICATION
speclalChars = ( ) { } prose - {readableChars} comment = ( prose ) dimensions = { Integer ( , Integer } } data = realnumber {realnumber} matdx = dimensions data prose tilde matdxflle = matrix { matrix }.
(Manual example done.)
Figure 2.
the eigenvectors for a matrix by iterative methods. Both the input and output from such programs are eigenvector documents. As more experimental data becomes available for covariance matrix computations, the latest final eigenvector matrix is a natural starting point for the new calculations. Carefully naming the various parts of the program's input is a part of this software design process [3,5]. The parts of a real number, as we would naturally use them, include signs, digits, commas, embedded spaces, a decimal, scale factors, and units. These names are used as fun-
A. MCINTOSH, I. BRODBELT
( MatrixMultiply version 1 C:premul.mx3 C:postmul.mx3 ---> C:mulout.mx3 12-25-1745 08:46:00) {3,3} 15 15 15
12 0.0 -12.00
2 -4.0 2.00
(PreMatrix input. ) {3,3} 8
1
6
3.0 4.00
5.0 9.00
7.0 2.00
The Turtle numbers:
This is a sample matrix to test the multiply routines. This particular matrix is called the Lo Shu. Legend says that a certain emperor Yu saw a mystical turtle on the Yellow River. The dots on the turtles shell made this arrangement, where all rows, columns, and diagonals add to 15, and only consecutive digits are used. John Fults, Open Court Publishing Co., Box 599, La Salle, Ii 61301 ISBN 0-87548-197-3 QA165.F84 512. 72 73-23041(PostMatrix input. ) {3,3} 1 1 1
1.00 0.00 -1.00
1.000_0 -2.000_0 1.000_0
This is the eigenvector matrix for Turtles. When it is the post matrix, the columns of the output should show different significant figures(version I MatrixMultiply done) Figure 3.
damental units in a more formal description of a real number, and incorporated into procedure names. These formal description units form a basis to attain programming objectives. The resulting program reads naturally and intuitively, allowing a few lines of code to be located quickly when changes are desired. Importantly, where there are deviations from the natural syntax, there is still a basis to justify the deviation, and an obvious place to look when the code requires modification. Comparison of the definition for Mx3Scanner.Mx3Elements in the Appendix against Figure 2, the prototype matrix file, show the clear, intuitive similarity between the data structure in the program and the data structure in the prototype. More discussion about this interrelationship follows in the section about matrix definition. Continuity with existing practice is also an important consideration in a design. PreciseReal reads the standard FORTRAN floating point format, which includes the familar scale factor in the number, e.g., 1.02e-002. The limits for the SI scale factors in this implementation are - 1 8 (atto) to +15 (Peta). Scale factors outside this limit are scaled to the correct thousands and printed in the older form, i.e., 2.5e-21. M A T R I X FILES The natural representation of data extends beyond real numbers. Figure 2 shows a prototype matrix file. Again notice that this figure is easier to read than conventional computer output.
The natural representation of real numbers
7
One design element is the use of natural appearing comments in the data file (like this one, they appear within parentheses). This matrix file structure allows programs to document the time they were executed, which files were used as their input, and user prose comments may be carried forward. This self documenting audit trail capability allows review of lab data and different versions of calculations to be managed more effectively. The MatrixMultiply Output in Figure 3 shows a simple example of this capability. IMPLEMENTATION The specific tools in this development were the Logitech 3.3t beta test compiler, similar to the current 3.4 commercial release of December 1989. Experience with other projects suggests that this code should be portable to other environments, including VAX/VMS, and the Macintosh with little if any change. The Appendix contains Definition Modules, followed by selected code fragments. Definition Modules document the names of the procedures and system wide variables; they form the essential basis of this package. Changes to the Definition Modules constitute a major revision to the software. A team of programmers can write replacement code given these definition files. The selected code fragments are presented using a style similar to a WEB [3]. ~EFEKENCES 1. C.F. Bunge, J&uregui, Rocio & Cisneros, Gerardo, Writing friendly programs in modular form, Computers Chem. 13 (3), 277-290 (1989). 2. Niklaus Wirth and J. Gutlmecht, The Oberon System, Software--Practice and Experience 19 (9), 857-893 (1989). 3. Donald E. Knuth, Literate programming, The Computer Journal 27, 97-111 (1984). 4. Carlos F. Bunge and Gerardo Cisneros, Modular libraries and literate programming in software for ab initio atomic and molecular electronic structure calculations, Computers Chem. 12 (2), 85-89 (1988). 5. Nildaus Wirth, Algorithms and Data Structures, Prentice-Hall, Englewood Cliffs, (1986). 6. Donald E. Knuth, Mathematical typography, Bulletin of the American Mathematical Societ~ 1, 337-372 (1979). 7. Donald E. Knuth, The TEX book, Addison Wesley, Reading, (1986). 8. Niklans Wirth, Programming in Modula-e, Introduction, Springer-Verlag, Berlin, (1986).
8
A. MCINTOSH, J. BRODBELT
APPENDIX 1. Transferring electronic typeset text between locations. The running Journal heading and the two column listings obtained at our location were eventually difficult to reconcile. This paragraph was added in the galley as a spacer to keep the various numbers properly aligned in the index at the end of this appendix. 2. Notes about typesetting. At the editors recommendation, the Appendix was reformatted into two column listings. To accomplish this, the entire Appendix was typeset using ]~/EB. Special thanks to Wayne Sewell for providing copies of his supporting programs for MWEB. See Weaving
a Prograra, Literate Prograraraing in WEB, Van Nostrand Reinhold, New York, ISBN 0-442-31946-0 for more details. The task of porting the listings into NWEB was suprisingly easy. The entire learning curve, software acquisition, and modifications only took a few days of effort. 3. Real Valued Matrix definition module. This section provides the definition filesfor MatrixHeal. The implementation filesare omitted for brevity. The definition module specifies the interface between the module and a client program; it consists of only the elements which are visible outside the module.
4 . First there is the scaffolding for the entire program. This includes some ltfi/EB definitions, so that MWEB will work as planned. d e f i n e de.fmod - (*change this to 'definod - ' for definition module *) d e f i n e endde.f-- (* change this to 'endde.f =_' for definition module *) f o r m a t defmod =_ begin f o r m a t endde.f-- end defmod (Definition module of MatrixReal 5) enddef e n d MatrixReal.
5. Here are the actual definitions. (Definition module of MatrixReal 5) = def init i on module Mufti=Real; (*Aubrey McIntosh 5/10/90 c s / u t exas.edu!rpp386!aubrey *) (* Copyright 1990 by Aubrey McIntosh. Permission granted for individuals to use and distribute this source, provided that this comment remain intact, and no changes axe made to the text. *) (* MatrixReal provides simple Matrix arithmetic procedures. The code is written in standard Modula.2, i.e., it is portable. *) import Precise Real; e x p o r t q u a l i f i e d Matrix, Create, Dispose,
ReadMatrix, WriteMatrix, Transpose, Multipllt, Add, ScalarMultipl!/; t y p e Matrix = r e c o r d dimensions: a r r a y [0 . . 1] o f CARDINAL; values: p o i n t e r t o a r r a y [0 1023] o f PreciseReaI.Real; .
.
end ; This code is used in Section 4. 6. ( Procedures 6 ) p r o c e d u r e Create(frows,.fcolurans : CARDINAL; v a r result : Matt/x); procedure Add(pre,post : Matrix; v a t sura : Matrix); procedure SealarMultiply(a : PreciseReaI.Real; ra : Matrix; e a r r : Matrix); procedure Dispose(vat old : Matrix); p r o c e d u r e ReadMatrix( item : Matrix); p r o c e d u r e WriteMatrix( itera : Matrix)
procedure Transpose(rain: Matrix; v a r out : Matrix); procedure Multipl~(pre,post : Matrix; e a r result : Matrix); See also Section 9. This code is used in Section 10. 7. PreciseReal Definition Module. This module supports significant digit calculations in arithmetic operations. ( Precise Real definitions 7 ) -defmod ( Definition module of PreciseReallO) enddef 8. PreciseReal defines a data structure for supporting the number of significant digits in a real number. All procedures in PreciseReal are called in the sequence result := a0 operate al. ( Real number definition 8) type Real = record
value: REAL; lastPosition: I N T E G E R end ;
The natural representation of real numbers 9.
( Procedures 6) + = procedure Add( VARresult : Real; aO,al : Real) p r o c e d u r e Subtract( VARresult : Real; aO,al : Real) procedure Multiply( VARrcsult : Real; aO,al : Real) p r o c e d u r e Divide( VARresult : Real; aO,al : Real) end Divide; 10. This section collects all the procedure heading definitions. ( Definition module of PreciseReal 10) = definition module PreciseReal; ( Procedures 6) end PreclseReal. This code is used in Section 7. 11. Nx3Scanner D e f i n i t i o n N o d u l e . These definitions for the interface for Mx3Scanner. ( Mx3Scanner 11) = definition module Mx3Scanner;, (* Mx3Scalmer supports IO operations for the .rex3 data fornmt used in the Harrison project. July 25 First version. August 1 Remove references to FileSystem, MatrixPreciseReal Add references to Significant Split WriteComment into MoreComment and WriteComment. *) import FileSystem; import PreciseReal; export qualified Setln, SetOut, SetLst, FilePointer, Mx3Elements, mx3set, Which Token, Skip To, SkipSpaceAndConntLines, Line Count, CopyMatri3:,ReadReal, WriteReal, CopyReaI, ReadDimensions, WriteDimensions, CopyDimensions, ReadCard, WriteCard, CopyCard, ReadComment, MoreComment, WriteCommenf, MoreCardComment, MoreReaIComment, CopyComment; t y p e FilePointer --- p o i n t e r t o FileSystem.File, Mx3Elements =(matrix, commcnt, whitespace, dimensions, data, dot, sign, digits, scale,prose,tilde, other, termination,
eof); mx3set = s e t of M~3Elements; (Mx3Procedures 12) end Mx3Scanner. 12. SetIn establishes the input file. (Mx3Procedures 12 ) p r o c e d u r e Setln(J : FilePointer); See also Sections 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37 and 38. This code is used in Section 11. 13. SetOut establishes the output file. (Mx3Procedures 12) + = procedure SetOut(J : FilePointer);
14. SetLst establishes the listing file. (Mx3Procedures 12)+ = p r o c e d u r e SetLst(f : FilePointer);
15. WhichToken identifies the type of token at the current character. (Mx3Proceduresl 2) + = procedure Which Token( ): Mx3Elements; 16. SkipTo skips to a token in the correct category (Mx3Procedures 12) +_= procedure SkipTo(ok : mx3set); 17. SkipConunent eats a comment, including all nested comments. (Mx3Procedures 12) + = procedure Sk•Comment( ); 18. SkipSpaceAndCountLines skips all whitespace, but counts the number of lines as they go by. (Mx3Procedures 12) + = procedure SkipSpaceAndCountLines; 19. LineCount gives the current linecount. (Mx3Procedures 12) +_--p r o c e d u r e LineCount ( ) : CARDINAL; 20. SkipDimensions skips the dimensions header (Mx3Procedures 12) + = procedure SkipDimensions; 21. SkipNumber skips a nmnber. (Mx3Procedures 12) +_-p r o c e d u r e SkipNumber; 22. NextCh reads the next character from the input file. (Mx3Procedures 12) +-procedure NextCh; 23. CopyMatrix copies an entire Matrix from the input file to the output file. (Mx3Procedures 12) + = procedure CopyMatrlx; 24. ReadReal reads a real number and notes the number of significant digits. (Mx3Procedures 12) + = p r o c e d u r e ReadReal( VARr : PreciseReaI.Real);
25. WrlteReal writes a real number and emitts commas, embedded underscores as appropriate. The correct number of significant digits are emitted. (Mx3Procedures 12) + procedure WriteReal( r : PreciseReaLReal); 26. CopyReal copies a real number from input to output. (Mx3Procedures 12) + p r o c e d u r e CopyReal;
27. ReadDimensions reads the dimensions into a matrix. (Mx3Procedures 12) + = procedure ReadDimenslons( VARdm : a r r a y o f CARDINAL);
9
10
A. MCINTOSH, J. BRODBELT
28. WriteDimensions writes the dimensions of a matrix to the output file. (Mx3Procedures 12) + procedure WriteDimensions( dm : array of CARDINAL); 29. CopyDimensions copies the dimensions portion of a matrix to the output file. (Mx3Procedures 12) + ~ procedure Cop~Dimensions;
30. ReadCard reads a cardinal from in. (Mx3Procedures 12) + ~ p r o c e d u r e ReadCard( V A R n : C A R D I N A L ) ; 31. WriteCard writes a cardinal to out. (Mx3Procedures 12) + = p r o c e d u r e WriteCard(x, n : C A R D I N A L ) ;
32. CopyCard copies a cardinal from in to out. (Mx3Procedures 12) + ~ procedure Cop~Card; 33. ReadComment reads a comment to a string. (Mx3Procedures 12) + = p r o c e d u r e R e a d C o m m e n t ( VARmsg : a r r a y o f CHAR); 34. MoreComment appends text to an internal comment. (Mx3Procedures 12) + ~ procedure M o r e C o m m e n t ( m s g : array of CHAR); 35. WriteComrnent emits all the stacked comments to the file. (Mx3Procedures 12) + ~ p r o c e d u r e Writ e C o m m ent ( msg: array of CHAR
36. M o r e C a r d C o m m e n t appends text to an interned comment. (Mx3Procedures 12) + procedure MoreCardComment(c: C A R D I N A L ) ; 37. MoreFtealComment appends text to an internal comment. (Mx3Procedures 12) + = procedure
MoreRealComment( r : PreeiseReaI.Real); 38. CopyCominent copies a comment to out. (Mx3Procedures 12) +-= procedure Cop~Comment; 39. Selected Code Fragments. The definition of the parts in Mx3Elements represent the parts of the matrix fileconcept given in the wishful example. They represent the fundamental concepts in this library. (Define the parts of a matrix file 39 ) = t y p e Mx3Elements=( matrix, comment, whitespace, dimensions, data, dot, sign, digits, scale,prose, tilde, other, termination, eof );
40. The matrix file is constructed so that the next character identifies which of the parts of a matrix file is next. This program takes the character, and gives the matrix file part that follows. (Identify which part of a matrix file comes next 40 ) -procedure Which TokenO: Mx3Elements;
v a t aux: Mx3Elements; begin c a s e ch o f ' ( ' : aux *- comment
I ' { ': aux 4-- dimensions [ ' , ' , ' } ' , ' - ' : ,auz 4.- termination I '+','-': a~x ~- sign [ '0' .. '9': aux ~- digits } '.': a~x *-dot I 'u',A SCII.ht, ASCII.EOL: a~x ~--lvhitespace
I
'-': aux ~-- tilde [ OC: a t , x *- co/ else aux *--- other e n d ; r e t u r n aux end Which Token; 41. This definition of a real number contains its value, as well as its number of significant digits. Together with the procedures to Add, Subtract, and otherwise manipulate the number, this gives the programmer the ability to calculate result in a fuller sense t h a n is common in computer programs. Additional fields may be added here for additional needs. For example, b o t h units and propagation of errors could conceivably be manipulated by the program. (Define a Fteal number41) = t y p e Real = r e c o r d
~l~e: real; lastPosition: integer end ; 42. The matrix file is free form. Embedded comments are allowed, and white space may be placed anywhere. Sometimes it is necessary to skip parts of the file, and stop when any one of several other parts are found. (Skip until the correct part of a matrix file is found 42 ) = p r o c e d u r e Skip To(ok : mx3set);
v a t aux: Mx3Elements; begin loop
a~x *-- WhichToken( ); if ¢uz E ok t h e n exit end ; case ¢~x of
other,col: exit [ comment: S k i p C o m m e n t J whitespaee: SkipSpaeeAndCountLines dimensions: SkipDimensions [ dot, tilde, termination: NextCh [ digits, sign: SkipNumber end end
end Skip To;
l
The natural representation of real numbers 43. Comments may be nested, and anything in commcmts, including the special characters '.' a n d tilde are ignored. Only end-of-file and end-ofcommcmt are recognized. (Skip a comment part of a matrix file 43) ---p r o c e d u r e 5kipComment( );
46. Consume any sign character that may be a part of the number. (Eat Sign) _=
neoatiue *- ch = ' - ' ; i f neoati~e t h e n NeztCh e l s i f ch = % ' t h e n NextCh end ;
v a t level: cardinal; begin
level ~ I; loop
11
This code is used in Section 54.
NextCh; if (level = O)v(ch=OC) t h e n
47. Read in the regular part of the real number, and ignore any embedded commas and underscores. Remember where the decimal point is, though, since it's important. (read mantissa while digits, dots, and termination 47) -digits: delta *- ord(ch); DEC(delta, ord( tOt ));
e x i t end; if ch='(' t h e n
inc( le~el) elsif oh=')' then DEC(level)
elsif ch = A S C I I . E O L then inc( linecount) end end e n d SkipComment; 4 4 . Some parts of the library are written so that the matrix must he square. However, a matrix could be cubic or have higher order. This code accepts an open array for the matrix dimensions, and reads a corresponding number of dimensions separated by comlnas.
(Read the dimensions part of a matrix file 44 )
--
procedttreReadDimensions(var din: a r r a y o f cardinal); v a t iz: cardinal; begin
Skip To(mx3set{ dimensions, eof~); NcxtGh; ix*-- O; loop
Skip To( mx3set{ digits, termination, eof~); c a s e WhichToken( ) o f difits: ReadCard( dm[iz]); i f ix < H I G H (din) t h e n
inc(ix) end
[
termination: i f ch = , I t h e n Next Ch elsif cA = 'y t h e n NeztCh; e x i t e n d I eo~. e x i t end end e n d ReadDimensions; 45. ReadReal reads a real according to: * [ + - ] [digiu][.]Lfractio.][~ [+-] (,.c~e)**3vJul-9o Add metric scale factors. * a atto -18 * f femto -15 * p pico -12 * n nano -9 * u micro -6 * m mill; -3 * K Kilo3*MMega6*GGiga9*TTera12*EeXa 15
auxR *- lO.O*auxR+FLOAT(delta); Ne.tCh; inc(numdioits) [ termination: NextCh{just eat commas ^ errors.}
I
dot: leading *- numdigits; hasdot*- true; NextCh This code is used in Section 54 48. It's really important to keep track of the exponent position for the last digit read in for the number. Here, before we read the scale factor, it's straightforward to calculate this. What happens when we scan +123.456.7897 (remember last position 48) _= i f hasdot t h e n
lastPosition *-- leading; DEC( lastPosition, numdigits ) else
lastPosition ~-- leading *-numdigits end ; This code is used in Section 54 49. Get the unscaled mantissa, and the power of ten scale factor. The value part of the number has to be multiplied or divided by the correct power of ten, and the value of lastPosition must be updated also. An early design choice to use unsigned numbers (cardinals) in many portions of the program has the disadvantage that this code is difficult to read. The convolutions are simply to be sure that no cardinal expression ever attains a negative value.
12
A. MCINTOSH, J. BRODBELT
5 0 . If one of the simple SI units is available, consume it a n d adjust the scale factor. (Consume scale factor 50) = c a s e eh o f 'a': NeztCh; ex~ponent ~ 18; negative 4.- true ,fl: NeztCh; exponent ~ 15; negative ~-- true 'p': NextCh; exponent ~ 12; negative ~ true Inl: NextCh; exponent *-- 9; negative *-- true 'Ut: NextCh; exponent +- 6; negative ~ true 'm': NextCh; exponent *-- 3; negative *-- true 'K': NextCh; exponent *-- 3 J IN': NextCh; exponent ~-- 6 I tG': NextCh; exponent 4-- 9 J ITl: NextCh; exponent *-- 12 I 'E', ' e ' : NextCh; i f WhiehToken( ) 6 m x a s e t {sign, digits}
53. The compiler doesn't know how to manipulate the field lastPosition, so we write a procedure to a d d two Real numbers. Notice t h a t the result will have a lastPosition value equal to the largest value in the two addends. (add real 53) procedure A d d ( v a t result: Real; sO, al : Real);
then
p r o c e d u r e R e a d R e a l ( v a r r : PreciseReaLReal); v a r delta, leading, numdigits, ix: cardinal; lastPosition, auxE: integer; exponent: cardinal; pot, auxR: real; hasdot, negative: boolean; part: (signp, mantissap, scalep); begin SkipTo(mx3set{ sign, digits, eof, t i l d e } ); part *- signp; auxR ~ 0.0; loop c a s e part o f signp: (Eat Sign 46)part 4-- mantissap [ mantissap: numdigits ~-- 0; hasdot ~-- false; loop c a s e Which Token( ) o f (read m a n t i s s a while digits, dots, and termination 47)
negative *-- ch=l--I;
if (ch='-') V (oh=l+ ') then Next Ch end ; ReadCard(exponent) else exponent *- 15 end
else exponent ~ 0; end ; This code is used in Section 54.
5 1 . T h e n u m b e r is adjusted by the power of ten given in the exponent. (Adjust value by power of ten 51) -pot 4.- 1.0; f o r ix . - 1 t o exponent do pot ~ 10.0" pot end ; i f negative t h e n auxR *-- a u x R / p o t else auxR ~-- auxR*pot end ; This code is used in Section 54. 5 2 . First adjust the lastposition. (Adjust lastPosition 52) -auxE *-- exponent; if negative then lastPosition *-- lastPosition - auxE; ine( auxE, n u m d i g i t s - leading); auxE +- -- auxE;
else lastPosition ~- lastPosition +
auxE;
D E C ( a u x E , n u m d i g i t s - leading) end ; i f auxE
else negative *-- false; exponent ~ auxE
end ; This code is used in Section 54.
begin result.value *-- aO.value+ al.value; i f aO.lastPosition<_ al.lastPosition t h e n result.lastPosition *-- al.lastPosition
else result.lastPosition *- aO.lastPosition
end e n d Add; 54. This procedure reads a real n u m b e r from the input file. It notices the exponent of the last digit position in the input number. T h e numbers in the input file may have their digits grouped by commas a n d underscores, for example 1,000,000.111_222 ( r e ~ real s 4 ) -
else
(remember last position 48) part *-- sealep; i f negative t h e n auxR +-- - a u x R end ;
exit end end [ scalep: negative *- false; (Consume scale factor 50) (Adjust lastPosition 52) (Adjust value by power of ten 51) exit end
end ; r.value *- auxR; r.lsstPosition *- lastPosition e n d ReadReal;
The n a t u r a l representation of real numbers 5 5 . We also supply a procedure to multiply two numbers. If we multiply by longhand, it turns out t h a t the lastposition is the sum of the two lastPositions of the multiplicands, adjusted by the n u m b e r of digits in the larger number. (multiply real 55) --p r o c e d u r e Multiply(var result : Real; sO, al : Real); Var aOfirstdigit, alfirstdigit: integer;, begin aOfirstdigit *-- Firstdigit (sO); alfirstdigit ~-- Firstdigit ( a l ) ; i f (aOfirstdigit- aO.lastPosition)< ( al firstdigit - al.lastPosition) t h e n
result.lastPosition ~-alfirstdigit + aO.lastPosition else result.lastPosition *aOfirstdigit + al.lastPosition end ; result.value *-- aO.value* al.value; e n d Multiply; 5 6 . Whew! The primitives are out of the way now, a n d its time to move on to the original goal. Here is how we define a matrix. This definition is not public. T h a t means t h a t I can change my mind later, along with the procedures t h a t know a b o u t matrices. This m i g h t b e convenient, for example, if I want to read the order of a matrix from the d a t a file. (matrix definition 56) _= t y p e Matrix = r e c o r d dimensions: a r r a y [0 .. 1] o f cardinal; values: p o i n t e r t o array [0 .. 1023] of PreeiseReaI.Real; end ;
C~2S:6-8
13
57. This is really misnamed. I ' m reading the Body of the matrix at this point, a n d the input file has to be positioned after the dimensions part. Notice t h a t ReadReal skips whitespace and comments, so t h a t this routine is very simple. (read matrix body 57) p r o c e d u r e ReadMatrix( item : Matrix); v a t ix: cardinal; begin w i t h item do for ix*-Oto ( dimennions[O]* dimensions[1])-I do Mx3Scanner.ReadReal(~aluesT[iz~); end end end ReadMatrir; 58. We make all the procedures t h a t deal with matrices u n d e r s t a n d the PreciseReals.Real arithmetic. (add matrix smc58) --p r o c e d u r e Add(pre,post : Matrix,, v a r s u m : Matrix); v a t ix: cardinal; begin
A .ert( (pre.dimensio~.[1]= post.dimensions[1])A(pre.dimensions[O]= post.dimensions[O]), 'Addu --u not., same., sizeu matrices .'); A ssert( ( pre.dirnensions[1]= sum.dimensions[1])A(pre.dimensions[O]= sum.dimensions[O]), 'lddu--uincorrectusize uresult. '); for ix~-O to pre.dimensiona[O]*pre.dimensions[1]-I do PreciseReaI.A dd( sum. values y[ ix], pre.valu esT[ix],post.valuesT[ix]) end e n d Add;
14
A. MOINTOSH, J. BRODBELT
Add: 5, 6, 9_, 5._.33,5._88. Appendix: 2. ASCII: 40, 43. Assert: 58. au= 40, 42. auxE: 52, 54. auxR: 47, 51, 54. sO: 9, 53, 55. aOfirstdigit: 55. al: 9, 53, 55. alfirstdigit: 55. b e g i n : 4. boolean: 54. cardinal: 43, 44, 54, 56, 57, 58. C A R D I N A L : 5, 6, 19, 27, 28, 30, 31, 36. oh: 40, 43, 44, 46, 47, 50. CHAR: 33, 34, 35. commas: 47. comment: 11, 39, 40, 42. CopyCard: 11, 32. CopyComment: 11, 38. CopyDimensions: 11, 29. CopyMatrix:. 11, 23. CopyReal: 11, 26. Create: 5, 6. data: 11, 39. DEC: 43, 47, 48, 52. de:fmod: 4_. delta: 47, 54. digits: 11, 39, 40, 42, 44, 45, 47, 50, 54. dimensions: 5, 11, 39, 40, 42, 44, 56, 57', 58. Dispose: 5, 6. Divide: 9. din: 27, 28, 44. dot: 11, 39, 40, 42, 47. eat: 47. end: 4. e n d d e f : _4. eofl 11, 39, 40, 42, 44, 54. EOL: 40, 43. errors: 47. exponent: 50, 51, 52, 53. false: 52, 54. /columns: 6. File: 11. FilePointer: 11, 12, 13, 14. FileSystem: 11. Firstdigit: 55. FL OA T: 47. fraction: 45. frows: 6. hasdot: 47, 48, 54. HIGH: 44. ht: 40. inc: 43, 44, 47, 52. I N T E G E R : 8. integer:. 41, 54, 55. item: 6, 57. ix: 44, 51, 54, 57, 58. just: 47. lastPosition: 8, 41, 48, 52, 53, 54, 55. leading: 47, 48, 52, 54. level: 43. LineCount: 11, 19. linecount: 43. Literate: 2. mantissap: 54.
Matrix:. 5, 6, 56, 57, 58. matrix:. 11, 39. MatrixReal: 4, 5. min: 6. MoreCardComment: 11, 36. MoreComment: 11, 34. MoreReaIComment: 11, 37. msg: 33, 34, 35. Multiply: 5, 6_, 9, 55. Mx3Elements: 11, 15, 39, 40, 42. Mx3Scanner. 11, 57. mx3set: 11, 16, 42, 44, 50, 54. negative: 46, 50, 51, 52, 54. NextCh: 22, 42, 43, 44, 46, 47, 50. numdiflits: 47, 48, 52, 54. ok: 16, 42. old: 6. ord: 47. other:. 111, 39, 40, 42. out: 6_. part: 54. post: 6, 58. pot: 51, 54. pre: 6, 58. PreciseReal: 5, 6, 8, 10, 11, 24, 25, 37, 54, 56, 58. Program: 2. Programming: 2. prose: 11, 39. r: 6, ~ 54. ReadCard: I I , 30, 44, 50. ReadComment: 11, 33. ReadDimensions: 11, 27, 44. ReadMatrix:. 5, 6, 57. ReadReal: 11, 24, 54, 57. Real: 5, 6, 8, 9, 24, 25, 37, 41, 53, 54, 55, 56. real: 54. R E A L : 8, 41. result: 6, 9_, 53, 55. SealarMultiply: 5, 6. scale: 11, 39. scalep: 54. Setln: 11, 12. SetLst: 11, 14. SetOut: 11, 13. sign: 11, 39, 40, 42, 50, 54. signp: 54. SkipComment: 17, 42, 43. SkipDimensions: 20, 42. SkipNumber: 21, 42. SkipSpaceAndCountLines: 11, 18, 42. SkipTo: 11, 16, 42, 44, 54. Subtract: 9. s~m: 6, ~ . termination: II, 39, 40, 42, 4d, 47. tilde: II, 39, 40, 42, 54. Transpose: 5, 6. true: 47, 50, 52. value: 8, 41, 53, 54, 55. values: 5, 56, 57, 58. Which Token: 11, 15, 40, 42, 44, 50, 54. whitespace: 11, 39, 40, 42. WriteCard: 11, 31. WriteComment: 11, 35. WriteDimenMons: 11, 28. WriteMatrix: 5, _6. WriteReal: 11, 25.