#pagenr("%",1)##setcount(1)##block##pageblock# #headeven# #center#EUMEL-Benutzerhandbuch #center#____________________________________________________________ #end# #headodd# #center#TEIL 6 : Das Archiv 'std.zusatz' #center#____________________________________________________________ #end# #bottomeven# #center#____________________________________________________________ 6 - % #right#GMD #end# #bottomodd# #center#____________________________________________________________ GMD #right#6 - % #end# TEIL 6: Das Archiv 'std.zusatz' Das Archiv 'std.zusatz' enthält Pakete, die nur bei Bedarf insertiert werden sollen. Eine Einbindung in das EUMEL Grundsystem würde dieses ungebührlich unfangreich machen. Das Archiv enthält zusätzliche Software für: - mathematische Operationen : complex , longint , vector , matrix - Analyse : reporter , referencer - Taschenrechnerfunktion zur Editor-Erweiterung : TeCal , TeCal Auskunft #page# 6.1. Erweiterungen um Mathematische Operationen 6.1.1 COMPLEX Das Packet COMPLEX erweitert das System um den Datentyp COMPLEX (komplexe Zahlen) und Operationen auf komplexen Zahlen. Folgende Operationen stehen für COMPLEX zur Verfügung: - Einfache Operatoren : := , = , <> , + ,- , * - Eingabe/Ausgabe : get , put - Denotierungsprozedur : complex , complex i , complex one , com­ plex zero - Komponenten : real part , imag part - bes. Funktionen : ABS , CONJ , phi , dphi , sqrt #page# COMPLEX Operationen 'TYPE COMPLEX' Komplexe Zahl, bestehend aud Realteil 're' und Imaginärteil 'im'. ':=' #on("b")#OP := (COMPLEX VAR a, COMPLEX CONST b) #off("b")# Zuweisung. '=' #on("b")#BOOL OP = (COMPLEX CONST a, b) #off("b")# Vergleich von 'a' und 'b' auf Gleichheit. '<>' #on("b")#BOOL OP <> (COMPLEX CONST a, b) #off("b")# Vergleich von 'a' und 'b' auf Ungleichheit. '+' #on("b")#COMPLEX OP + (COMPLEX CONST a, b) #off("b")# Summe von 'a' und 'b'. '-' #on("b")#COMPLEX OP - (COMPLEX CONST a, b) #off("b")# Differenz von 'a' und 'b'. '*' #on("b")#COMPLEX OP * (COMPLEX CONST a, b) #off("b")# Multiplikation von 'a' mit 'b'. '/' #on("b")#COMPLEX OP / (COMPLEX CONST a, b) #off("b")# Division von 'a' mit 'b'. #page# 'get' #on("b")#PROC get (COMPLEX VAR a) #off("b")# Einlesen eines komplexen Wertes vom Bildschirm in der Form zweier REAL-De­ noter. Die Eingabe kann editiert werden. 'put' #on("b")#PROC put (COMPLEX CONST a) #off("b")# Ausgabe eines komplexen Wertes auf dem Bildschirm in Form zweier REAL- Werte. Hinter jedem REAL-Wert wird ein Leerzeichen angefügt. 'complex' #on("b")#COMPLEX PROC complex (REAL CONST re, im) #off("b")# Denotierungsprozedur. Angabe in kartesischen Koordinaten. 'complex i' #on("b")#COMPLEX PROC complex i #off("b")# Denotierungsprozedur für den komplexen Wert '0.0 + i 1.0'. 'complex one' #on("b")#COMPLEX PROC complex one #off("b")# Denotierungsprozedur für den komplexen Wert '1.0 + i 0.0'. 'complex zero' #on("b")#COMPLEX PROC complex zero #off("b")# Denotierungsprozedur für den komplexen Wert '0.0 + i 0.0'. 'imag part' #on("b")#REAL PROC imag part (COMPLEX CONST number) #off("b")# Liefert den Imaginärteil des komplexen Wertes 'number'. 'real part' #on("b")#REAL PROC real part (COMPLEX CONST number) #off("b")# Liefert den Real-Teil des komplexen Wertes 'number'. 'ABS' #on("b")#REAL OP ABS (COMPLEX CONST x) #off("b")# REAL-Betrag von 'x'. 'CONJ' #on("b")#COMPLEX OP CONJ (COMPLEX CONST number) #off("b")# Liefert den konjugiert komplexen Wert von 'number'. 'dphi' #on("b")#REAL PROC dphi (COMPLEX CONST x) #off("b")# Winkel von 'x' (Polardarstellung). 'phi' #on("b")#REAL PROC phi (COMPLEX CONST x) #off("b")# Winkel von 'x' (Polardarstellung) in Radiant. 'sqrt' #on("b")#COMPLEX PROC sqrt (COMPLEX CONST x) #off("b")# Wurzelfunktion für komplexe Werte. #page# 6.1.2 LONGINT LONGINT ist ein Datentyp, für den (fast) alle Prozeduren und Operatoren des Daten­ typs INT implementiert wurden. LONGINT unterscheidet sich von INT dadurch, daß erheblich größere Werte darstellbar sind. Für den Datentyp LONGINT stehen folgende Operationen zur Verfügung: - Operatoren : := , = , <> , < , <= ,> , >= , + , - , * , ** , ABS , DECR , DIV , INCR , MOD , SIGN - Eingabe/Ausgabe : get , put - Math. Prozeduren : abs , int , longint , max , max logint , min , random , sign , text , zero LONGINT-Operationen 'TYPE LONGINT' Datentyp ':=' #on("b")#OP := (LONGINT VAR links, LONGINT CONST rechts) : #off("b")# Zuweisungsoperator '= ' #on("b")#BOOL OP = (LONGINT CONST links, rechts) #off("b")# Vergleichen zweier LONGINTs auf Gleichheit. '<>' #on("b")#BOOL OP <> (LONGINT CONST links, rechts) #off("b")# Vergleichen zweier LONGINTs auf Ungleichheit. '< ' #on("b")#BOOL OP < (LONGINT CONST links, rechts) #off("b")# Vergleichen zweier LONGINTs auf kleiner. '<=' #on("b")#BOOL OP <= (LONGINT CONST links, rechts) #off("b")# Vergleichen zweier LONGINTs auf kleiner gleich. '> ' #on("b")#BOOL OP > (LONGINT CONST links, rechts) #off("b")# Vergleichen zweier LONGINTs auf größer. '>=' #on("b")#BOOL OP >= (LONGINT CONST links, rechts) #off("b")# Vergleichen zweier LONGINTs auf größer gleich. '+ ' #on("b")#LONGINT OP + (LONGINT CONST argument) #off("b")# Monadischer Operator. Ohne Wirkung. #on("b")#LONGINT OP + (LONGINT CONST links, rechts) #off("b")# Addition zweier LONGINTs. '- ' #on("b")#LONGINT OP - (LONGINT CONST argument) #off("b")# Vorzeichenumkehrung. #on("b")#LONGINT OP - (LONGINT CONST links, rechts) #off("b")# Subtraktion zweier LONGINTs. '* ' #on("b")#LONGINT OP * (LONGINT CONST links, rechts) #off("b")# Multiplikation von zwei LONGINTs. '**' #on("b")#LONGINT OP ** (LONGINT CONST argument, exponent) #off("b")# Exponentiation zweier LONGINTs mit positivem Exponenten. FEHLER : LONGINT OP ** : negative exponent Der 'exponent' muß >= 0 sein. 0 ** 0 is not defined 'argument' und 'exponent' dürfen nicht gleich 0 sein. #on("b")#LONGINT OP ** (LONGINT CONST argument, INT CONST exponent)#off("b")# Exponentiation eines LONGINT mit positiven INT Exponenten. FEHLER : LONGINT OP ** : negative exponent Der 'exponent' muß >= 0 sein. 0 ** 0 is not defined 'argument' und 'exponent' dürfen nicht gleich 0 sein. 'ABS' #on("b")#LONGINT OP ABS (LONGINT CONST argument) #off("b")# Absolutbetrag eines LONGINT. 'DECR' #on("b")#OP DECR (LONGINT VAR resultat, LONGINT CONST ab) #off("b")# resultat := resultat - ab 'DIV' #on("b")#LONGINT OP DIV (LONGINT CONST links, rechts) #off("b")# Division zweier LONGINTs. FEHLER : Division durch 0 'rechts' muß <> 0 sein. 'INCR' #on("b")#LONGINT OP INCR (LONGINT VAR resultat, LONGINT CONST dazu)#off("b")# resultat := resultat + dazu 'MOD' #on("b")#LONGINT OP MOD (LONGINT CONST links, rechts) #off("b")# Modulo-Funktion für LONGINTs. Der Rest einer LONGINT-Division wird ermit­ telt. FEHLER : text (links) + 'MOD 0' 'rechts' muß ungleich null sein. 'SIGN' #on("b")#INT OP SIGN (LONGINT CONST longint) #off("b")# Feststellen des Vorzeichens von 'longint'. Liefert: 0 wenn 'longint' = 0, 1 wenn 'longint' > 0, -1 wenn 'longint' < 0. #page# 'get' #on("b")#PROC get (LONGINT VAR zahl) #off("b")# Eingabe eines LONGINTs vom Terminal. #on("b")#PROC get (FILE VAR file, LONGINT VAR zahl) #off("b")# Einlesen von 'zahl' aus der sequentiellen Datei 'file'. Die Datei muß mit 'input' assoziiert sein (vergl. 'sequential file'). FEHLER : Datei zu Leseversuch nach Daateiende Leseversuch auf output-FILE 'put' #on("b")#PROC put (LONGINT CONST longint) #off("b")# Ausgabe eines LONGINTs auf dem Bildschirm. Anschließend wird ein Leerzeichen ausgegeben. Hardwareabhängig sind die Aktionen, wenn eine Ausgabe über die Bildschirmzeilengrenze vorgenommen wird. Meist wird jedoch die Ausgabe auf der nächsten Zeile fortgesetzt. #on("b")#PROC put (FILE VAR file, LONGINT CONST zahl) #off("b")# Ausgabe von 'zahl' in die sequentielle Datei 'file'. 'file' muß mit 'output' assoziiert sein. FEHLER : Datei zu Schreibversuch auf input-FILE #page# 'abs' #on("b")#LONGINT PROC abs (LONGINT CONST argument) #off("b")# Absolutbetrag eines LONGINT. 'int' #on("b")#INT PROC int (LONGINT CONST longint) #off("b")# Konvertierung von LONGINT nach INT. FEHLER : integer overflow 'longint' ist größer als 'maxint'. 'longint' #on("b")#LONGINT PROC longint (INT CONST int) #off("b")# Konvertierung von 'int' nach LONGINT. #on("b")#LONGINT PROC longint (TEXT CONST text) #off("b")# Konvertierung von 'text' nach LONGINT. 'max' #on("b")#LONGINT PROC max (LONGINT CONST links, rechts) #off("b")# Liefert das Maximum zweier LONGINTs. 'maxlongint' #on("b")#LONGINT PROC max longint #off("b")# Liefert größten LONGINT Wert. 'min' #on("b")#LONGINT PROC min (LONGINT CONST links, rechts) #off("b")# Liefert das Minimum zweier LONGINTs. 'random' #on("b")#LONGINT PROC random (LONGINT CONST lower bound, upper bound)#off("b")# Pseudo-Zufallszahlen-Generator im Intervall 'lower bound' und 'upper bound' einschließlich. Es handelt sich hier um den 'LONGINT Random Generator'. 'sign' #on("b")#INT PROC sign (LONGINT CONST longint) #off("b")# Feststellen des Vorzeichens von 'longint'. Liefert: 0 wenn 'longint' = 0, 1 wenn 'longint' > 0, -1 wenn 'longint' < 0. 'text' #on("b")#TEXT PROC text (LONGINT CONST longint) #off("b")# Konvertierung von 'longint' nach TEXT. #on("b")#TEXT PROC text (LONGINT CONST longint, INT CONST laenge) #off("b")# Konvertierung von 'longint' nach TEXT. Die Anzahl der Zeichen soll 'laenge' betragen. Für LENGTH (text (longint)) < laenge werden die Zeichen rechtsbündig in einen Text mit der Länge 'laenge' eingetra­ gen. Ist der daraus entstehende TEXT kleiner als 'laenge', werden die an 'laenge' fehlenden Zeichen im TEXT mit Leerzeichen aufgefüllt. Für LENGTH (text (longint)) > laenge wird ein Text mit der Länge 'laenge' geliefert, der mit '*'-Zeichen gefüllt ist. 'zero' #on("b")#LONGINT PROC zero #off("b")# Liefert LONGINT Wert Null. #page# 6.1.3 VECTOR Der Datentyp VECTOR erlaubt Operationen auf Vektoren aus Elementen vom Typ REAL. Im Gegensatz zur Struktur 'ROW m REAL' muß die Anzahl der Elemente nicht zur Übersetzungszeit deklariert werden, sondern kann zur Laufzeit festgelegt werden. Somit kann eine zur Übersetzungszeit unbekannte Anzahl von REALs bearbeitet werden, wobei nur soviel Speicherplatz wie nötig verwendet wird. Die maximale Größe eines VECTOR beträgt 4000 Elemente. Der in den Operationen ':=', 'idn' und 'vector' benutzte Datentyp INITVECTOR wird nur intern gehalten. Er dient der Speicherplatzersparnis bei der Initialisierung. - Operatoren : := , = , <> , + , - , * , / LENGTH , SUB - Eingabe/Ausgabe : get , put - Besondere Vector- : length , nilvector , norm , vector , replace Operationen #page# ':=' #on("b")#OP := (VECTOR VAR ziel, VECTOR CONST quelle) #off("b")# Zuweisung. Nach der Zuweisung gilt auch length (quelle) = length (ziel) d.h. der linke Operand besitzt nach der Zuweisung genauso viele Elemente wie 'quelle', unabhängig davon, ob 'ziel' vor der Zuweisung mehr oder weniger Ele­ mente als 'quelle' besaß. Beispiel: VECTOR VAR y :: vector (10, 1.0), z :: vector (15, 2.0); ... y := z; (* length (y) liefert nun 15 ! *) #on("b")#OP := (VECTOR VAR ziel, INITVECTOR CONST quelle) #off("b")# Dient zur Initialisierung eines VECTORs. Beispiel: VECTOR VAR x :: vector (17); 'vector' erzeugt ein Objekt vom Datentyp INITVECTOR. Dieses Objekt braucht nicht soviel Speicherplatz wie ein VECTOR-Objekt. Dadurch wird vermieden, daß nach erfolgter Zuweisung nicht ein durch 'vector' erzeugtes Objekt auf dem Heap unnötig Speicherplatz verbraucht. '=' #on("b")#BOOL OP = (VECTOR CONST a, b) #off("b")# Vergleich zweier Vektoren. Der Operator liefert FALSE, wenn die Anzahl der Elemente von 'a' und 'b' ungleich ist oder wenn zwei Elemente mit gleichem Index ungleich sind. Beispiel: VECTOR VAR x :: vector (10, 1.0), y :: vector (15, 2.0), z :: vector (10, 1.0); ... x = y ... (* FALSE *) ... x = z ... (* TRUE *) '<>' #on("b")#BOOL OP <> (VECTOR CONST a, b) #off("b")# Vergleich zweier Vektoren auf Ungleichheit (NOT (a = b)). '+' #on("b")#VECTOR OP + (VECTOR CONST a) #off("b")# Monadisches '+' für VECTOR. Keine Auswirkung. #on("b")#VECTOR OP + (VECTOR CONST a, b) #off("b")# Elementweise Addition der Vektoren 'a' und 'b'. Beispiel: VECTOR VAR x, (* 'x' hat undefinierte Länge *) a :: vector (10, 1.0), b :: vector (10, 2.0); ... x := a + b; (* 'x' hat nun 10 Elemente mit Werten'3.0' *) FEHLER : VECTOR OP + : LENGTH a <> LENGTH b 'a' und 'b' haben nicht die gleiche Anzahl von Elementen. '-' #on("b")#VECTOR OP - (VECTOR CONST a) #off("b")# Monadisches '-'. #on("b")#VECTOR OP - (VECTOR CONST a, b) #off("b")# Elementweise Subtraktion der Vektoren 'a' und 'b'. FEHLER : VECTOR OP - : LENGTH a <> LENGTH b 'a' und 'b' haben nicht die gleiche Anzahl von Elementen. '*' #on("b")#REAL OP * (VECTOR CONST a, b) #off("b")# Skalarprodukt zweier Vektoren. Liefert die Summe der elementweisen Multiplika­ tion der Vektoren 'a' und 'b'. Beachte eventuelle Rundungsfehler! Beispiel: REAL VAR a; VECTOR VAR b :: vector (10, 2.0), c :: vector (10, 2.0); ... a := b * c; (* 40.0 *) FEHLER : REAL OP * : LENGTH a <> LENGTH b 'a' und 'b' haben nicht die gleiche Anzahl von Elementen. #on("b")#VECTOR OP * (VECTOR CONST a, REAL CONST s) #off("b")# Multiplikation des Vektors 'a' mit dem Skalar 's'. #on("b")#VECTOR OP * (REAL CONST s, VECTOR CONST a) #off("b")# Multiplikation des Skalars 's' mit dem Vektor 'a'. '/' #on("b")#VECTOR OP / (VECTOR CONST a, REAL CONST s) #off("b")# Division des Vektors 'a' durch den Skalar 's'. Beispiel: VECTOR VAR a, (* 'a' hat undefinierte Laenge *) b :: vector (10, 4.0); ... a := b / 2.0; (* 'a' hat nun 10 Elemente mit Werten '2.0' *) 'LENGTH' #on("b")#INT OP LENGTH (VECTOR CONST a) #off("b")# Liefert die Anzahl der Elemente von 'a'. 'SUB' #on("b")#REAL OP SUB (VECTOR CONST v, INT CONST i) #off("b")# Liefert das 'i'-te Element von 'v'. FEHLER : OP SUB : subscript overflow Der Index 'i' liegt außerhalb des Vektors (i > LENGTH v). OP SUB : subscript underflow Der Index 'i' liegt außerhalb des Vektors (i < 1). #page# 'get' #on("b")#PROC get (VECTOR VAR a, INT CONST l) #off("b")# Einlesen der Elemente von 'a' vom Terminal, wobei 'l' die Anzahl der Elemente angibt. FEHLER : PROC get : size <= 0 Die angeforderte Elementanzahl 'l' muß > 0 sein. 'put' #on("b")#PROC put (VECTOR CONST v) #off("b")# Ausgabe der Werte der Elemente von 'v' auf dem Terminal. #page# 'length' #on("b")#INT PROC length (VECTOR CONST a) #off("b")# Liefert die Anzahl der Elemente von 'a'. Beispiel: VECTOR VAR a :: vector (10, 1.0), b :: vector (15, 2.0); ... ... length (a) ... (* 10 *) ... length (b) ... (* 15 *) 'nilvector' #on("b")#INITVECTOR PROC nilvector #off("b")# Erzeugen eines Vektors mit einem Element mit dem Wert '0.0'. 'norm' #on("b")#REAL PROC norm (VECTOR CONST v) #off("b")# Euklidische Norm (Wurzel aus der Summe der Quadrate der Elemente). 'replace' #on("b")#PROC replace (VECTOR VAR v, INT CONST i, REAL CONST r)#off("b")# Zuweisung des i-ten Elementes von 'v' mit dem Wert von 'r'. Beispiel: VECTOR VAR v :: ...; ... replace (v, 13, 3.14); (* Das 13. Element von 'v' bekommt den Wert '3.14' *) FEHLER : PROC replace : subscript overflow Der Index 'i' liegt außerhalb des Vektors (i > LENGTH v). PROC replace : subscript underflow Der Index 'i' liegt außerhalb des Vektors (i < 1). 'vector' #on("b")#INITVECTOR PROC vector (INT CONST l) #off("b")# Erzeugen eines Vektors mit 'l' Elementen. Ein INITVECTOR-Objekt benötigt nicht soviel Speicherplatz wie ein VECTOR-Objekt. Die Elemente werden mit dem Wert '0.0' initialisiert. FEHLER : PROC vector : size <= 0 Die angeforderte Elementanzahl 'l' muß > 0 sein. #on("b")#INITVECTOR PROC vector (INT CONST l, REAL CONST value)#off("b")# Erzeugen eines Vektors mit 'l' Elementen. Ein INITVECTOR-Objekt benötigt nicht soviel Speicherplatz wie ein VECTOR-Objekt. Die Elemente werden mit dem Wert 'value' initialisiert. Beispiel: VECTOR VAR v := vector (17, 3.14159); (* 'v' hat 17 Elemente mit den Wert '3.14159' *) FEHLER : PROC vector : size <= 0 Die angeforderte Elementanzahl 'l' muß > 0 sein. #page# 6.1.4 MATRIX Der Datentyp MATRIX erlaubt Operationen auf m x n Matrizen. Im Gegensatz zur Struktur 'ROW m ROW n REAL' muß die Anzahl der Elemente nicht zur Überset­ zungszeit deklariert werden, sondern kann zur Laufzeit festgelegt werden. Somit kann eine zur Übersetzungszeit unbekannte Anzahl von REALs bearbeitet werden, wobei nur soviel Speicherplatz wie nötig verwendet wird. Die maximale Größe einer MATRIX beträgt 4000 Elemente. Der in den Operationen ':=', 'idn' und 'matrix' benutzte Datentyp INITMATRIX wird nur intern gehalten. Er dient der Speicherplatzersparnis bei der Initialisierung. - Operatoren : := , = , <> , + , - , * COLUMNS , DET , INV , ROWS , TRANSP , - Eingabe/Ausgabe : get , put - Besondere Matrix- : column , idn , matrix , row , sub Operationen transp , replace column , replace element , replace row #page# ':=' #on("b")#OP := (MATRIX VAR l, MATRIX CONST r) #off("b")# Zuweisung von 'r' auf 'l'. Die MATRIX 'l' bekommt u.U. eine neue Anzahl von Elementen. Beispiel: MATRIX VAR a :: matrix (3, 4, 0.0), b :: matrix (5, 5, 3.0); ... a := b; (* 'a' hat jetzt 5 x 5 Elemente *) #on("b")#OP := (MATRIX VAR l, INITMATRIX CONST r) #off("b")# Dient zur Initialisierung einer Matrix. Beispiel: MATRIX VAR x :: matrix (17, 4); 'matrix' erzeugt ein Objekt vom Datentyp INITMATRIX. Dieses Objekt braucht nicht soviel Speicherplatz wie ein MATRIX-Objekt. Dadurch wird vermieden, daß nach erfolgter Zuweisung nicht ein durch 'matrix' erzeugtes Objekt auf dem Heap unnötig Speicherplatz verbraucht. '=' #on("b")#BOOL OP = (MATRIX CONST l, r) #off("b")# Vergleich zweier Matrizen. Der Operator '=' liefert FALSE, wenn die Anzahl Spalten oder Reihen der Matrizen 'l' und 'r' ungleich ist und wenn mindestens ein Element mit gleichen Indizes der zwei Matrizen ungleiche Werte haben. Beispiel: MATRIX VAR a :: matrix (3, 3), b :: matrix (3, 3, 1.0), c :: matrix (4, 4); ... a = b ... (* FALSE wegen ungleicher Werte *) ... a = c ... (* FALSE wegen ungleicher Groesse *) ... b = c ... (* FALSE wegen ungleicher Groesse *) '<>' #on("b")#BOOL OP <> (MATRIX CONST l, r) #off("b")# Vergleich der Matrizen 'l' und 'r' auf Ungleichheit. '+' #on("b")#MATRIX OP + (MATRIX CONST m) #off("b")# Monadisches '+'. Keine Auswirkungen. #on("b")#MATRIX OP + (MATRIX CONST l, r) #off("b")# Addition zweier Matrizen. Die Anzahl der Reihen und der Spalten muß gleich sein. Beispiel: MATRIX VAR a :: matrix (3, 43, 1.0), b :: matrix (3, 43, 2.0), summe; summe := a + b; (* Alle Elemente haben den Wert '3.0' *) FEHLER: MATRIX OP + : COLUMNS l <> COLUMNS r Die Anzahl der Spalten von 'l' und 'r' sind nicht gleich. MATRIX OP + : ROWS l <> ROWS r Die Anzahl der Zeilen von 'l' und 'r' sind nicht gleich. '-' #on("b")#MATRIX OP - (MATRIX CONST m) #off("b")# Monadisches Minus. Beispiel: MATRIX VAR a :: matrix (3, 4, 10.0) a := - a; (* Alle Elemente haben den Wert '- 10.0' *) #on("b")#MATRIX OP - (MATRIX CONST l, r) #off("b")# Subtraktion zweier Matrizen. Die Anzahl der Reihen und Spalten muß gleich sein. FEHLER: MATRIX OP - : COLUMNS l <> COLUMNS r Die Anzahl der Spalten von 'l' und 'r' sind nicht gleich. MATRIX OP - : ROWS l <> ROWS r Die Anzahl der Zeilen von 'l' und 'r' sind nicht gleich. '*' #on("b")#MATRIX OP * (REAL CONST r, MATRIX CONST m) #off("b")# Multiplikation einer Matrix 'm' mit einem Skalar 'r'. Beispiel: MATRIX VAR a :: matrix (3, 4, 2.0); ... a := 3 * a; (* Alle Elemente haben den Wert '6.0' *) #on("b")#MATRIX OP * (MATRIX CONST m, REAL CONST r) #off("b")# Multiplikation einer Matrix 'm' mit einem Skalar 'r'. #on("b")#MATRIX OP * (MATRIX CONST l, r) #off("b")# Multiplikation zweier Matrizen. Die Anzahl der Spalten von 'l' und die Anzahl der Zeilen von 'r' müssen gleich sein. Beispiel: MATRIX VAR a :: matrix (3, 4, 2.0), b :: matrix (4, 2, 3.0), produkt; produkt := a * b; (* Alle Elemente haben den Wert '24.0' *) FEHLER : MATRIX OP * : COLUMNS l <> ROWS r Die Anzahl der Spalten von 'l' muß mit der Anzahl der Zeilen von 'r' übereinstimmen. #on("b")#VECTOR OP * (VECTOR CONST v, MATRIX CONST m) #off("b")# Multiplikation des Vektors 'v' mit der Matrix 'm'. FEHLER : VECTOR OP * : LENGTH v <> ROWS m Die Anzahl der Elemente von 'v' stimmt nicht mit den Anzahl der Zeilen von 'm' überein. #on("b")#VECTOR OP * (MATRIX CONST m, VECTOR CONST v) #off("b")# Multiplikation der Matrix 'm' mit dem Vektor 'v'. FEHLER : VECTOR OP * : COLUMNS m <> LENGTH v Die Anzahl der Spalten von 'm' stimmt nicht mit der Anzahl der Ele­ menten von 'v' überein. 'COLUMNS' #on("b")#INT OP COLUMNS (MATRIX CONST m) #off("b")# Liefert die Anzahl der Spalten von 'm'. Beispiel: MATRIX VAR a :: matrix (3, 4), b :: matrix (7, 10); put (COLUMNS a); (* 4 *) put (COLUMNS b); (* 10 *) 'DET' #on("b")#REAL OP DET (MATRIX CONST m) #off("b")# Es wird der Wert der Determinanten von 'm' geliefert. FEHLER : OP DET : no square matrix Die Matrix ist nicht quadratisch, d.h. ROWS m <> COLUMNS m 'INV' #on("b")#MATRIX OP INV (MATRIX CONST m) #off("b")# Liefert als Ergebnis die Inverse von 'm' (Achtung: starke Rundungsfehler möglich). FEHLER: OP INV : no square matrix Die Matrix 'm' ist nicht quadratisch, d.h. ROWS m <> COLUMNS m OP INV : singular matrix Die Matrix ist singulär. 'ROWS' #on("b")#INT OP ROWS (MATRIX CONST m) #off("b")# Liefert die Anzahl der Zeilen von 'm'. Beispiel: MATRIX VAR a :: matrix (3, 4), b :: matrix (7, 10); ... put (ROWS a); (* 3 *) put (ROWS b); (* 7 *) 'TRANSP' #on("b")#MATRIX OP TRANSP (MATRIX CONST m) #off("b")# Liefert als Ergebnis die transponierte Matrix 'm'. #page# 'get' #on("b")#PROC get (MATRIX VAR m, INT CONST rows, columns) #off("b")# Einlesen von Werten für die Matrix 'm' vom Terminal mit 'rows'-Zeilen und 'columns'-Spalten. 'put' #on("b")#PROC put (MATRIX CONST m) #off("b")# Ausgabe der Werte einer Matrix auf dem Terminal. #page# 'column' #on("b")#VECTOR PROC column (MATRIX CONST m, INT CONST i) #off("b")# Die 'i'-te Spalte von 'm' wird als VECTOR mit 'ROWS m' Elementen geliefert. Beispiel: MATRIX CONST a :: matrix (3, 4); VECTOR VAR b :: column (a, 1); (* 'b' hat drei Elemente mit den Werten '0.0' *) FEHLER: PROC column : subscript overflow Der Index 'i' liegt außerhalb der Matrix 'm' (i > COLUMNS m). PROC column : subscript underflow Der Index 'i' liegt außerhalb der Matrix 'm' (i < 1). 'idn' #on("b")#INITMATRIX PROC idn (INT CONST size) #off("b")# Erzeugen einer Einheitsmatrix vom Datentyp INITMATRIX. Beispiel: MATRIX VAR a :: idn (10); (* Erzeugt eine Matrix mit 10 x 10 Elementen, deren Werte '0.0' sind, mit der Ausnahme der Diagonalele­ mente, die den Wert '1.0' haben.*) FEHLER : PROC idn : size <= 0 Die angeforderte 'size' Anzahl Spalten oder Zeilen muß > 0 sein. 'matrix' #on("b")#INITMATRIX PROC matrix (INT CONST rows, columns) #off("b")# Erzeugen eines Datenobjekts vom Datentyp INITMATRIX mit 'rows' Zeilen und 'columns' Spalten. Alle Elemente werden mit dem Wert '0.0' initialisiert. Beispiel: MATRIX CONST :: matrix (3, 3); FEHLER: PROC matrix : rows <= 0 Die angeforderte Zeilenanzahl 'rows' muß > 0 sein. PROC matrix : columns <= 0 Die angeforderte Spaltenanzahl 'columns' muß > 0 sein. #on("b")#INITMATRIX PROC matrix (INT CONST rows, columns, REAL CONST value)#off("b")# Erzeugen eines Datenobjekts vom Datentyp MATRIX mit 'rows' Zeilen und 'co­ lumns' Spalten. Alle Elemente der erzeugten MATRIX werden mit dem Wert 'value' initialisiert. Beispiel: MATRIX CONST :: matrix (3, 3, 3.14); FEHLER: PROC matrix : rows <= 0 Die angeforderte Zeilenanzahl 'rows' muß > 0 sein. PROC matrix : columns <= 0 Die angeforderte Spaltenanzahl 'columns' muß > 0 sein. 'row' #on("b")#VECTOR PROC row (MATRIX CONST m, INT CONST i) #off("b")# Die 'i'-te Reihe von 'm' wird als VECTOR mit 'COLUMNS m' Elementen gelie­ fert. Beispiel: MATRIX CONST a :: matrix (3, 4); VECTOR VAR b :: row (a, 1); (* 'b' hat vier Elemente mit den Werten '0.0'*) FEHLER: PROC row : subscript overflow Der Index 'i' liegt außerhalb der Matrix 'm' (i > ROWS m). PROC row : subscript underflow Der Index 'i' liegt außerhalb der Matrix 'm' (i < 1). 'sub' #on("b")#REAL PROC sub (MATRIX CONST m, INT CONST row, column) #off("b")# Liefert den Wert eines Elementes von 'm', welches durch die Indizes 'row' und 'column' bestimmt wird. Beispiel: MATRIX VAR m :: matrix (5, 10, 1.0); put (sub (m, 3, 7)); FEHLER: PROC sub : row subscript overflow Der Index 'row' liegt außerhalb von 'm' (row > ROWS m). PROC sub : row subscript underflow Der Index 'row' liegt außerhalb von 'm' (row < 1). PROC sub : column subscript overflow Der Index 'column' liegt außerhalb von 'm' (column > ROWS m). PROC sub : row subscript underflow Der Index 'column' liegt außerhalb von 'm' (column < 1). 'transp' #on("b")#PROC transp (MATRIX VAR m) #off("b")# Transponieren der Matrix 'm', wobei kaum zusätzlicher Speicherplatz benötigt wird. #page# 'replace column' #on("b")#PROC replace column (MATRIX VAR m, INT CONST column index, VECTOR CONST column value) #off("b")# Ersetzung der durch 'column index' definierten Spalte in der MATRIX 'm' durch den VECTOR 'column value'. Beispiel: MATRIX VAR a :: matrix (3, 5, 1.0); VECTOR VAR b :: vector (3, 2.0); ... replace column (a, 2, b); (* Die zweite Spalte von 'a' wird durch die Werte von 'b' ersetzt *) FEHLER: PROC replace column : LENGTH columnvalue <> ROWS m Die Anzahl der Zeilen der MATRIX 'm' stimmt nicht mit der Anzahl der Elemente von 'columnvalue' überein. PROC replace column : column subscript overflow Der Index 'columnindex' liegt außerhalb von 'm' (columnindex > COLUMNS m). PROC sub : column subscript underflow Der Index 'columnindex' liegt außerhalb von 'm' (columnindex < 1). 'replace element' #on("b")#PROC replace element (MATRIX VAR m , INT CONST row, column, REAL CONST value) #off("b")# Ersetzung eines Elementes von 'm' in der 'row'-ten Zeile und 'column'-ten Spalte durch den Wert 'value'. Beispiel: MATRIX VAR a :: matrix (5, 5); ... replace element (1, 1, 3.14159); FEHLER: PROC replace element : row subscript overflow Der Index 'row' liegt außerhalb von 'm' (row > ROWS m). PROC replace element : row subscript underflow Der Index 'row' liegt außerhalb von 'm' (row < 1). PROC replace element : column subscript overflow Der Index 'column' liegt außerhalb von 'm' (column > COLUMNS m). PROC replace element : row subscript underflow Der Index 'column' liegt außerhalb von 'm' (column < 1). 'replace row' #on("b")#PROC replace row (MATRIX VAR m, INT CONST rowindex, VECTOR CONST rowvalue) #off("b")# Ersetzung der Reihe 'rowindex' in der MATRIX 'm' durch den VECTOR 'rowvalue'. Beispiel: MATRIX VAR a :: matrix (3, 5, 1.0); VECTOR VAR b :: vector (5, 2.0); ... replace row (a, 2, b); (* Die 2. Reihe von 'a' wird durch Werte von 'b'ersetzt *) FEHLER: PROC replace row : LENGTH rowvalue <> COLUMNS m Die Anzahl der Spalten der MATRIX 'm' stimmt nicht mit der Anzahl der Elemente von 'rowvalue' überein. PROC replace row : row subscript overflow Der Index 'rowindex' liegt außerhalb von 'm' (rowindex > ROWS m). PROC sub : row subscript underflow Der Index 'rowindex' liegt außerhalb von 'm' (rowindex < 1). 6.2 Programmanalyse Das Packet 'reporter' ermöglicht: a) Ablaufinformationen ("trace"); b) #ib#Häufigkeitszählung#ie# ("frequency count"); c) Programmunterbrechung bei Nichterfüllung einer Bedingung ("#ib#assertion#ie#"). 'Installation' Das Programm befindet sich in der Datei 'reporter' und kann wie üblich insertiert werden. Jedoch muß es mit 'check off' übersetzt werden, damit keine Zeilennummern für 'reporter' generiert werden. Dies ist notwendig, damit die Zeilennummern des zu testenden Programms nicht mit den Zeilennummern des Programms 'reporter' ver­ wechselt werden können. Beispiel: check off; insert ("reporter"); check on Mit dem Kommando #ib#generate reports#ie# ("testdatei") werden die oben erwähnten Prozeduraufrufe ('#ib#report#ie#') in das zu testende Programm, welches in der Datei 'testdatei' steht, geschrieben. Die Prozeduraufrufe werden nach jedem Prozedur-, Operator- oder Refinement-Kopf eingefügt und erhalten den entsprechenden Namen als Parameter. Diese Prozeduraufrufe werden gekennzeichnet, damit sie von der Prozedur eliminate reports ("testdatei") automatisch wieder entfernt werden können. Beispiel (für die eingefügten Prozedurauf­ rufe): ... PROC beispiel (INT CONST mist): \#\#report ("PROC beispiel");\#\# ... 'Automatische Ablaufinformation' Ist ein Programm mit 'generate reports' mit 'report'-Aufrufen versehen worden, kann es wie gewohnt übersetzt werden. Wird das Programm vom ELAN-Compiler kor­ rekt übersetzt und dann gestartet, wird bei jedem Antreffen eines 'report'-Aufrufs der Parameter (Name der Prozedur, Operator oder Refinement) in eine Datei, die TRACE-Datei geschrieben. Die TRACE-Datei wird beim Programmlauf automatisch von 'reporter' unter dem Namen 'TRACE' eingerichtet. Mit Hilfe dieser Datei kann der Programmablauf verfolgt werden. Es ist damit auch möglich festzustellen, wo eine "Endlos-Rekursion" auftritt. Die Ablaufinformationen bestehen nur aus den Namen der angetroffenen Prozeduren und Refinements. Trotz­ dem können die Anzahl der Informationen sehr umfangreich werden. Deshalb gibt es die Möglichkeit, die Erzeugung der Ablaufinformationen ab- bzw. wieder anzuschal­ ten. Dazu gibt es die Möglichkeit, in das zu testende Programm die Prozeduren #ib#report on#ie# #ib#report off#ie# einzufügen und das zu testende Programm mit diesen Prozeduraufrufen (erneut) zu übersetzen. 'Benutzereigene Ablaufinformation' Zusätzlich zu den von 'generate reports' eingefügten 'report'-Aufrufen kann ein Benutzer eigene Aufrufe an geeigneten Stellen in ein Programm schreiben. Dafür werden weitere 'report'-Prozeduren zur Verfügung gestellt, die als ersten Parameter ein TEXT-Objekt (meist Name des Objekts oder der Ausdruck selbst) und als zwei­ ten ein INT/REAL/TEXT/ BOOL-Objekt (der zu überprüfende Wert oder Ausdruck) enthalten. Beispiel: ... PROC beispiel (INT CONST mist): \#\#report ("beispiel");\#\# (* automatisch eingefuegte *) INT VAR mist :: ...; ... \#\#report ("mist:", mist);\#\# (* vom Benutzer per Hand einge­ fuegt *) ... Folgende 'report'-Routinen stehen zur Verfügung, damit man sie "von Hand" in ein zu testendes Programm einfügen kann: PROC report on PROC report off PROC report (TEXT CONST message) PROC report (TEXT CONST message, INT CONST value) PROC report (TEXT CONST message, REAL CONST value) PROC report (TEXT CONST message, TEXT CONST value) PROC report (TEXT CONST message, BOOL CONST value) Wichtig: Hier - wie bei allen anderen "von Hand eingefügten" Aufrufen - sollte ein Nutzer sich an die Konvention halten, diese in "\#\#" einzuklammern. Mit 'eliminate reports' werden diese Einfügungen automatisch entfernt. Sollen diese Aufrufe aber immer im Programm erhalten bleiben (jedoch nicht wirksam sein), sollten sie a) vor 'generate reports'-Aufruf mit jeweils '\#\#\#' eingefaßt werden. Beispiel: \#\#\# report ("...") \#\#\# So steht das 'report'-Statement in einem Kommentar. 'generate reports' wandelt '\#\#\#' --> '\#\#\#\#' um, so daß ein solches Statement wirksam wird. 'eliminate reports' wandelt ein '\#\#\#\#' --> '\#\#\#' zurück. b) nach 'generate reports' in '\#\#\#\#' eingefaßt werden. 'Häufigkeitszählung' Eine Häufigkeitszählung erhält man, in dem man in das zu testende Programm die Aufrufe count on count off einfügt. Ist die Häufigkeitszählung eingeschaltet, merkt sich 'reporter' die Anzahl der Durchläufe für jede Prozedur bzw. Refinement. Mit der Prozedur #ib#generate counts#ie# ("zu testende datei") werden die vermerkten Häufigkeiten in das zu testende Programm direkt eingefügt. Die Häufigkeiten werden wie oben beschrieben gekennzeichnet, so daß sie mit 'elimi­ nate reports' entfernt werden können. 'Assertions' Zusätzlich zu den oben erwähnten Möglichkeiten bietet 'reporter' noch die Prozedur #ib#assert#ie# an. Diese Prozedur kann von einem Programmierer an einer Stelle in das zu testende Programm eingefügt werden, an der bestimmte Bedingungen erfüllt sein müssen. Die Prozedur 'assert' steht in zwei Formen zur Verfügung: PROC #ib#assert#ie# (BOOL CONST zusicherung) PROC assert (TEXT CONST message, BOOL CONST zusicherung) Ist der Wert von 'zusicherung' nicht TRUE, wird der Programmlauf abgebrochen. reporter - Kommandos 'count on' #on("b")#PROC count on #off("b")# Schaltet die Häufigkeitszählung ein. 'count off' #on("b")#PROC count off #off("b")# Schaltet die Häufigkeitszählung aus. 'eliminate reports' #on("b")#PROC eliminate reports (TEXT CONST datei) #off("b")# Entfernt gekennzeichnete 'report'-Aufrufe aus der Datei 'datei'. 'generate reports' #on("b")#PROC generate reports (TEXT CONST datei) #off("b")# Fügt 'report'-Aufrufe in die Datei 'datei' ein und kennzeichnet diese mit '\#\#'. 'report on' #on("b")#PROC report on #off("b")# Schaltet die Ablaufinformationen in die Datei 'TRACE' ein. 'report off' #on("b")#PROC report off #off("b")# Schaltet die Ablaufinformationen wieder aus. 'generate counts' #on("b")#PROC generate counts (TEXT CONST datei) #off("b")# Bringt die Häufigkeitszählung (wie oft eine Prozedur oder Refinement durchlaufen wurde) in die Programmdatei 'datei'. Mit 'eliminate reports' werden diese wieder automatisch entfernt. 'assert' #on("b")#PROC assert (TEXT CONST message, BOOL CONST value) #off("b")# Schreibt 'message' und den Wert von 'value' in die TRACE-Datei. Ist 'value' FALSE, wird angefragt, ob das Programm fortgesetzt werden soll. #page# Referencer 'referencer' wird durch referencer ("ref datei", "referenz liste") aufgerufen, wobei die Datei 'referenz liste' nicht existieren darf. 'referenz liste' enthält nach Ablauf des Programms die gewünschte Liste, die sogenannte #ib# Referenzliste#ie#. #ub#Achtung#ue#: 'referencer' arbeitet ausschließlich mit Namen und verarbeitet nur wenige syntaktische Konstrukte. Darum ist es nur erlaubt, ein PACKET auf einmal von 'refe­ rencer' verarbeiten zu lassen. Verarbeitet man mehrere PACKETs auf einmal, kann es geschehen, daß gleichnamige Objekte in unterschiedlichen Paketen zu Warnungen (vergl. die unten beschriebenen Überprüfungen) führen. In der Referenzliste sind - alle Objekte mit ihrem Namen (in der Reihenfolge ihres Auftretens im Programm) - alle Zeilennummern, in der das Objekt angesprochen wird - die Zeilennummern, in der das Objekt deklariert wurde ('L' für ein lokales und 'G' für ein globales Objekt, 'R' für ein Refinement) verzeichnet. Die Referenzliste kann u.a. dazu dienen, zu kontrollieren, ob und wie (bzw. wo) ein Objekt angesprochen wird. Dies lohnt sich selbstverständlich nur bei etwas umfan­ greicheren Programmen (bei "Mini"-Programmen kann man dies sofort sehen). Bei der Erstellung der Referenzliste nimmt das Programm 'referencer' gleichzeitig einige Überprüfungen vor, die helfen können, ein Programm zu verbessern: 1. Warnung bei mehrzeiligen Kommentaren. 2. Überdeckungsfehler. Wird ein Objekt global (auf PACKET-Ebene) und nochmals lokal in einer Prozedur deklariert, ist das globale Objekt nicht mehr ansprechbar. Überdeckungen sind nach der gültigen Sprachdefinition z.Zt. noch erlaubt, werden aber bei einer Revision des Sprachstandards verboten sein. 3. Mehrmaliges Einsetzen von Refinements. Wird ein Refinement mehrmals einge­ setzt (das ist völlig legal), sollte man überlegen, ob sich dieses Refinement nicht zu einer Prozedur umgestalten läßt. 4. Nicht angewandte Refinements. Wird ein Refinement zwar deklariert, aber nicht "aufgerufen", erfolgt eine Warnung. 5. Nicht angesprochene Daten-Objekte. Werden Daten-Objekte zwar deklariert, aber im folgenden nicht angesprochen, wird eine Warnung ausgegeben. Hinweis: Alle Objekte, die nur wenig angesprochen werden, also nur wenige Zeilennum­ mern in der Referenzliste besitzen, sind verdächtig (Ausnahmen: importierte Prozeduren, LET-Objekte u.a.m.). referencer - Kommandos 'referencer' #on("b")#PROC referencer (TEXT CONST check file, dump file) #off("b")# Überprüft 'check file'. In 'dump file' steht nach Abschluß die Referenzliste. #page# 6.3 Rechnen im Editor Das Programm TeCal ermöglicht einfache Rechnungen (ähnlich wie mit einem Ta­ schenrechner) unter der Benutzung des Editors. Gleichzeitig stehen dem Benutzer aber alle Fähigkeiten des Editors zur Verfügung. TeCal ermöglicht Rechnungen auf einfache Weise zu erstellen oder Tabellenspalten zu berechnen. Zur Benutzung müssen 'TeCal' und 'TeCal Auskunft' insertiert werden. TeCal wird aus dem Editor heraus durch 'ESC t' oder durch das Editor-Kommando tecal aktiviert. Dadurch wird in der untersten Zeile des Bildschirms eine Informationszeile aufgebaut, in der die (Zwischen-) Ergebnisse einer Rechnung zur Kontrolle fest­ gehalten werden. Arbeitsweise Wenn TeCal insertiert ist, kann die Taschenrechnerfunktion jederzeit durch aufgerufen werden. Aus der editierten Datei werden Werte mit gelesen, durch <+> (bzw. -,*,/) verknüpft und mit an die aktuelle Cursor­ position geschrieben werden. Der von TeCal errechnete Wert wird durch derart ausgegeben, daß an der Stelle an der der Cursor steht die letzte Stelle vor dem Dezimalpunkt geschrieben wird. Die Eingabe von Klammern geschieht durch <(> <)>. Durch die Hilfsfunktion lassen sich die TeCal Funktionen auflisten. Der Prozentoperator <%> erlaubt einfache Rechnungen der Form: 'zahl' <+> <%> <=> . Derartige Folgen können natürlich mit der bekannten Editor-Lernfunktion auch ge­ lernt werden, so daß sich z.B. die Mehrwertsteuerberechnung auf wenige Tasten reduziert. Spalten können summiert werden, indem auf der #on("u")#untersten#off("u")# Zahl einer Spalte eingegeben wird. Daraufhin werden alle darüberliegende Zahlen addiert, bis ein Zeichen auftritt, das nicht in einer Zahl auftritt (Leerzeichen stören nicht!). ____________________________________________________________________________ ............ 55.00 66.99 123.45 99.99 9876.54 ........... Anzeige: 0.00 14.00% Memory: 0.00 ____________________________________________________________________________ TeCal Prozeduren 'evaluate' #on("b")#evaluate (TEXT CONST zeile, INT CONST von) #off("b")# Ausdruck 'zeile' ab der Stelle 'von' berechnen. #on("b")#evaluate (TEXT CONST zeile) #off("b")# Ausdruck 'zeile' ab Stelle 1 berechnen. 'kommastellen' #on("b")#kommastellen (INT CONST stellen) #off("b")# Berechnungen auf 'stellen' Zahlen hinter dem Komma einstellen. 'merke' #on("b")#PROC merke (INT CONST zahl)#off("b")# Integer 'zahl' im Merkregister abspeichern. #on("b")#PROC merke (REAL CONST zahl)#off("b")# Real 'zahl' im Merkregister abspeichern. 'prozentsatz' #on("b")#PROC prozentsatz (INT CONST zahl) #off("b")# Prozentsatz von 'zahl' Prozent einstellen. Der Wert wird automatisch konvertiert. #on("b")#PROC prozentsatz (REAL CONST zahl) #off("b")# Prozentsatz von 'zahl' Prozent einstellen. 'tecal' #on("b")#PROC tecal (FILE VAR f) #off("b")# Datei 'f', die mit 'sequential file' assoziiert ist, mit TeCal editieren. #on("b")#PROC tecal (TEXT VAR datei) #off("b")# 'datei' mit TeCal editieren. #on("b")#PROC tecal #off("b")# Zuletzt editierte Datei mit TeCal editieren. 'tecalauskunft' #on("b")#PROC tecalauskunft #off("b")# Auskunft zeigen. #on("b")#PROC tecalauskunft (TEXT CONST zeichen) #off("b")# Auskunft zu 'zeichen' zeigen.