home *** CD-ROM | disk | FTP | other *** search
/ Dream 57 / Amiga_Dream_57.iso / Amiga / Programmation / c / Docs / cweb33p11a.lha / cweb / examples / matrix.wpp < prev    next >
Encoding:
Text File  |  1994-11-09  |  18.0 KB  |  484 lines

  1. %
  2. % CWEB $VER: matrix.wpp 1.2 (3.1.1994)
  3. %
  4. % BESCHREIBUNG: Dieses CWEB Programm soll als Beispiel fⁿr einige
  5. %               Erweiterungen dienen, die erst mit der neuen Version 3
  6. %               des CWEB-Systems verfⁿgbar sind.  Es liest die Datei
  7. %               `Matrix.input', die in vier Zeilen jeweils vier EintrΣge
  8. %               der Form `(Realteil,ImaginΣrteil)' enthalten, und berechnet
  9. %               zu der so definierten komplexen Matrix die Inverse.  Ist
  10. %               die Eingabedatei nicht vorhanden, werden die entsprechenden
  11. %               Werte vom Benutzer angefordert.  Als Besonderheiten fⁿr
  12. %               CWEB-Interessierte m÷chte ich zwei Punkte anfⁿhren.  Zuerst
  13. %               und vor allem ist es ein deutsches Programm, sowohl die Ein-
  14. %               als auch die Ausgabe ist fⁿr diese Sprache gedacht.  Fⁿr die
  15. %               TeXnische Weiterverarbeitung wird also `gcwebmac.tex'
  16. %               ben÷tigt, da dort die entsprechende Anpassung bezⁿglich
  17. %               der Umlaute und Anfⁿhrungszeichen enthalten ist.
  18. %               Zweitens ist es ein C++ Programm und mu▀ deshalb mit
  19. %               CWEB 3.0 verarbeitet werden; Σltere Versionen ohne
  20. %               die Change-Datei von Hans-Hermann Bode werden ihre
  21. %               Schwierigkeiten haben.  Au▀erdem mu▀ zur ▄bersetzung ein
  22. %               C++-Compiler benutzt werden.
  23. %
  24. % ERSTELLUNGSDATUM: 21.11.1993 (V1.0)
  25. %
  26. % AUTOR: Andreas Scherer
  27. %         Abt-Wolf-Stra▀e 17
  28. %         96215 Lichtenfels
  29. %         Germany
  30. %
  31. % ─NDERUNGEN: 26.11.1993: <stdlib.h> mu▀ *nach* <complex.h> eingebunden
  32. %                         werden, sonst meckert SAS/C++ 6.50 (V1.1)
  33. %             03.01.1994: Version als konstanter Zeiger (V1.2)
  34. %
  35. % URHEBERRECHT: (c) 1993 Andreas Scherer
  36. %
  37. % Die Anfertigung und Verteilung von unverΣnderten Kopien der
  38. % elektronischen Form dieses Dokumentes ist erlaubt, sofern der
  39. % Urheberrechtshinweis und dieser Berechtigungshinweis bei allen
  40. % Kopien erhalten bleibt.
  41. %
  42. % Die Anfertigung und Verteilung von verΣnderten Versionen dieses
  43. % Dokumentes ist erlaubt unter den Bedingungen fⁿr unverΣnderte Kopien,
  44. % sofern das gesamte hiervon abgeleitete Werk unter den Bedingungen eines
  45. % mit diesem vergleichbaren Berechtigungshinweises verteilt wird.
  46.  
  47. % Spezielle Fonts fⁿr Teile der Dokumentation.
  48. %
  49. \font\ams=msbm10
  50.  
  51. % Ein kleiner Trick zur Darstellung der Determinantenschreibweise, da
  52. % der senkrechte Strich in \.{CWEB} eine besondere Bedeutung besitzt.
  53. %
  54. \def\leftbar{\left|}
  55. \def\rightbar{\right|}
  56.  
  57. % Wir brauchen kein Inhaltsverzeichnis, da nur zwei Kapitel existieren.
  58. %
  59. \nocon
  60.  
  61. @i ecma94.w
  62.  
  63. @* Matrizeninversion. Dieses Programm dient zur Invertierung einer
  64. vorgegebenen $4$-reihigen |Matrix|
  65. $$
  66.   A=\left(
  67.     \matrix{
  68.       a_{11}&\cdots&a_{14}\cr
  69.       \vdots&\ddots&\vdots\cr
  70.       a_{41}&\cdots&a_{44}\cr}
  71.   \right)
  72. $$
  73. mit EintrΣgen $a_{ij}$ aus dem K÷rper der komplexen Zahlen~{\ams C}.
  74. Ursprⁿnglich wurde es auf einem {\mc PC} mit dem Borland~\CPLUSPLUS/
  75. Compiler entwickelt.  Ein Vorteil dieses Sprachdialektes ist die
  76. Bereitstellung des Datentypes \glqq komplexe Zahl\grqq.  Nach einem
  77. Zwischenstadium als {\mc ANSI-C}-Programm, das ich mit dem {\mc
  78. SAS/C}-6.3 aus der ursprⁿnglichen Form entwickelte, erfolgt nun die
  79. Rⁿckportierung nach \CPLUSPLUS/ mit der neuen Version~6.50 des {\mc
  80. SAS/C}-Systems.  Der Aufbau des Programmes selbst gliedert sich in
  81. folgende Teile:
  82.  
  83. @c
  84. @<Globale \#|include|s  @>@/
  85. @<Versionsnummer       @>@/
  86. @<Funktionsprototypen  @>@/
  87. @<Funktionen           @>@/
  88. @<Die |main|-Funktion  @>
  89.  
  90. @ Den mathematischen Hintergrund fⁿr das angewandte Verfahren liefert
  91. das \glqq Taschenbuch der Mathematik\grqq\ von I.~N.~Bronstein und
  92. K.~A.~Semendjajew (B.~G.~Teubner Verlagsgesellschaft Stuttgart und
  93. Leipzig, 25.~Auf\-lage 1991, {\mc ISBN}~3--8154--2000--8).
  94. Auf Seite~154 wird die Berechnung einer inversen Matrix nach der Formel
  95. $$
  96.   Inverse = Matrix^{-1} = {1\over\det Matrix}\left(\matrix{
  97.     A_{11}&\cdots&A_{1n}\cr
  98.           &\cdots&      \cr
  99.     A_{n1}&\cdots&A_{nn}\cr}\right)^{T}
  100. $$
  101. hergeleitet.  Ausgangspunkt ist eine |Dimension|-reihigen |Matrix|, zu der
  102. in den folgenden Schritten die |Determinante| und die |Adjunkte| berechnet
  103. werden.  Bei der Berechnung der |Inverse|n anhand dieser Formel ist zu
  104. beachten, da▀ die Transposition der |Adjunkte|n einfach durch
  105. Vertauschung der Zeilen- und Spaltenindizes geschieht.
  106. @^Taschenbuch der Mathematik@>
  107. @^Bronstein, Ilja N.@>
  108. @^Semendjajew, K. A.@>
  109.  
  110. @<Berechne die |Inverse|@>=
  111.    for(i=0; i<Dimension; i++) {
  112.       for(j=0; j<Dimension; j++)
  113.          Inverse[i][j] = Adjunkte[j][i]/Determinante;
  114.       }
  115.  
  116. @ Der aufwendigste Teil dieser Formel steckt in der Berechnung der
  117. |Adjunkte|n zur $4$-reihigen komplexen |Matrix|.  (Die Dimension spielt
  118. mathematisch keine Rolle, programmtechnisch mu▀ aber fⁿr andere
  119. |Dimension|en eine Anpassung vorgenommen werden.)  Diese setzt sich zusammen
  120. aus den algebraischen Komplementen~$A_{ij}$ der Elemente~$a_{ij}$ der
  121. |Matrix|, die sich nach der Formel
  122. $$
  123.   A_{ij} = (-1)^{i+j}\leftbar\matrix{
  124.     a_{11}   &\cdots&a_{1,j-1}  &a_{1,j+1}  &\cdots&a_{1n}   \cr
  125.     \ldots   &      &\ldots     &\ldots     &      &\ldots   \cr
  126.     a_{i-1,1}&\cdots&a_{i-1,j-1}&a_{i-1,j+1}&\cdots&a_{i-1,n}\cr
  127.     a_{i+1,1}&\cdots&a_{i+1,j-1}&a_{i+1,j+1}&\cdots&a_{i+1,n}\cr
  128.     \ldots   &      &\ldots     &\ldots     &      &\ldots   \cr
  129.     a_{n1}   &\cdots&a_{n,j-1}  &a_{n,j+1}  &\cdots&a_{nn}  \cr}
  130.   \rightbar
  131. $$
  132. berechnen (Bronstein, Seite~149, |n==Dimension|).  Fⁿr die
  133. Implementierung ben÷tigen wir die $3$-reihige |Hilfsmatrix| und die
  134. Variable |Faktor|, die die Potenz von $-1$ reprΣsentiert.
  135. @^Taschenbuch der Mathematik@>
  136. @^BeschrΣnkung der Allgemeinheit@>
  137.  
  138. @s complex int
  139.  
  140. @<Funktionen@>=
  141. void AdjunkteMatrix(complex **Matrix,complex **Adjunkte)
  142.    {
  143.    int i,j,corralloc = 1;
  144.    complex **Hilfsmatrix,Faktor;
  145.  
  146.    @<Allokiere die |Hilfsmatrix|@>@;
  147.  
  148.    if(corralloc) {
  149.       for(i=0; i<4; i++) {
  150.          @<Setze den Vorfaktor fⁿr die adjunkte Determinante@>@;
  151.  
  152.          for(j=0; j<4; j++) {
  153.             @<Streiche Zeile |i| und Spalte |j|               @>@;
  154.             @<Berechne die Determinante der |Hilfsmatrix|     @>@;
  155.             @<Multipliziere die Determinante mit dem Vorfaktor@>@;
  156.  
  157.             Faktor *= complex(-1.); /* |Faktor| wechselt spaltenweise */
  158.             }
  159.          }
  160.       }
  161.  
  162.    @<Gib den Speicher der |Hilfsmatrix| wieder frei@>@;
  163.    }
  164.  
  165. @ Der Vorfaktor in dieser allgemeinen Formel bestimmt sich aus der Potenz
  166. von~$-1$ nach der Summe aus Spaltennummer und Zeilennummer des gerade
  167. betrachteten |Matrix|elementes~$a_{ij}$.  Zu beachten ist dabei, da▀ in
  168. \CEE/ Vektoren und damit auch Matrizen nicht bei~$1$ sondern bei~$0$ beginnend
  169. indiziert werden.  Da es sich aber um ein zweidimensionales Objekt handelt,
  170. hebt sich die quadratische Potenz von~$-1$ wieder auf.
  171.  
  172. @<Setze den Vorfaktor fⁿr die adjunkte Determinante@>=
  173.    for(Faktor=complex(1.),j=0; j<i; j++)
  174.       Faktor *= complex(-1.);
  175.  
  176. @ Die angegebene Determinantendarstellung besagt, da▀ man die
  177. Ausgangsmatrix um die Zeile~|i| und die Spalte~|j| des gerade betrachteten
  178. Elementes \glqq reduzieren\grqq\ mu▀, bevor man die Determinante
  179. berechnen darf.  Im Programm wird dazu aus der Ausgangsmatrix die
  180. entsprechend verkleinerte |Hilfsmatrix| gebildet.
  181.  
  182.  @<Streiche Zeile |i| und Spalte |j|@>=
  183.    MatrixReduktion(4,Matrix,Hilfsmatrix,i,j);
  184.  
  185. @ Die Reduktion der |Matrix| zur |Dimension-1|-reihigen |Hilfsmatrix|
  186. geschieht durch Streichen der Zeile~|i| und der Spalte~|j|.  Da dieser
  187. Vorgang fⁿr jedes der |Dimension|$^2$ Elemente der |Matrix|
  188. durchgefⁿhrt werden mu▀, wird dazu eine elementare Funktion
  189. definiert, die sogar mit einer anderen |Dimension| als~$4$ eingesetzt
  190. werden kann.  Die ZΣhlvariablen |k| und~|l| bezeichnen die
  191. Zeilen beziehungsweise die Spalten der Ausgangs-|Matrix|, |m|~und~|n|
  192. die der |Hilfsmatrix|.
  193.  
  194. @<Funktionen@>=
  195. void MatrixReduktion(int Dimension,complex **Matrix,@|
  196. complex **Hilfsmatrix,int i,int j)
  197.    {
  198.    int k,l,m,n;
  199.  
  200.    for(k=0,m=0; k<Dimension; k++) {
  201.       if(k!=i) { /* Zeile wird ausgelassen fⁿr |k==i| */
  202.          for(l=0,n=0; l<Dimension; l++) {
  203.             if(l!=j) { /* Spalte wird ausgelassen fⁿr |l==j| */
  204.                Hilfsmatrix[m][n] = Matrix[k][l];
  205.                n++; /* NΣchste Spalte der |Hilfsmatrix| */
  206.                }
  207.             }
  208.          m++; /* NΣchste Zeile der |Hilfsmatrix| */
  209.          }
  210.       }
  211.    }
  212.  
  213. @ Als Zwischenschritt folgt nun die Berechnung der Determinante der
  214. |Hilfsmatrix|.  Diese wird bereits in das entsprechende Feld der
  215. |Adjunkte|n gestellt, das aber noch mit dem getrennt berechneten Faktor
  216. multipliziert werden mu▀.
  217.  
  218. @<Berechne die Determinante der |Hilfsmatrix|@>=
  219.    Adjunkte[i][j] = ComplexDet(Hilfsmatrix);
  220.  
  221. @ Im vorliegenden Programm zur Berechnung einer |Inverse|n der
  222. |Dimension|~$4$ haben wir es stets mit einer $3$-dimensionalen
  223. |Hilfsmatrix| zu tun.  Deren Determinante (beachte die Schreibweise) wird
  224. nach der Beispielformel~2 von Seite~149 aus Bronstein berechnet (Regel von
  225. Sarrus)
  226. $$
  227.   \leftbar\matrix{
  228.     a_{11}&a_{12}&a_{13}\cr
  229.     a_{21}&a_{22}&a_{23}\cr
  230.     a_{31}&a_{32}&a_{33}\cr}\rightbar=
  231.   (a_{11}a_{22}a_{33} + a_{12}a_{23}a_{31} + a_{13}a_{21}a_{32})-
  232.   (a_{13}a_{22}a_{31} + a_{11}a_{23}a_{32} + a_{12}a_{21}a_{33}).
  233. $$
  234. @^Taschenbuch der Mathematik@>
  235. @^BeschrΣnkung der Allgemeinheit@>
  236.  
  237. @d ComplexDet(H) @/
  238.   (H[0][0]*H[1][1]*H[2][2]+H[0][1]*H[1][2]*H[2][0]+H[0][2]*H[1][0]*H[2][1])-@/
  239.   (H[0][2]*H[1][1]*H[2][0]+H[0][0]*H[1][2]*H[2][1]+H[0][1]*H[1][0]*H[2][2])
  240.  
  241. @ Der berechnete Zwischenwert mu▀ noch mit dem vorher definierten 
  242. |Faktor| multipliziert werden, damit das endgⁿltige algebraische
  243. Komplement~$A_{ij}$ entsteht.
  244.  
  245. @<Multipliziere die Determinante mit dem Vorfaktor@>=
  246.    Adjunkte[i][j] *= Faktor;
  247.  
  248. @ Nach der Aufstellung der |Adjunkte|n zur |Matrix| ben÷tigen wir jetzt
  249. noch die |Determinante|.  Erfreulicherweise ist dazu nun kein gro▀er
  250. Aufwand mehr n÷tig, da diese nach dem Laplaceschen Entwicklungssatz
  251. $$
  252.   Determinante=\sum_{i=1}^{n}a_{ij}A_{ij}=\sum_{j=1}^{n}a_{ij}A_{ij}
  253. $$
  254. aus den Elementen der |Matrix| und der zugeh÷rigen |Adjunkte|n berechnet
  255. werden kann (Bronstein, Seite~150).  Dabei ist es egal, nach welcher Zeile
  256. oder Spalte die Entwicklung durchgefⁿhrt wird.  Wir verwenden die erste
  257. Spalte.
  258. @^Taschenbuch der Mathematik@>
  259.  
  260. @<Laplace-Entwicklung der |Determinante|n@>=
  261.    Determinante = complex(0.);
  262.    for(i=0; i<Dimension; i++)
  263.       Determinante += Matrix[i][0]*Adjunkte[i][0];
  264.  
  265. @ Nach der Darlegung des mathematischen Formelwerkes und dessen Umsetzung
  266. in \CEE/-Routinen folgt nun das Hauptprogramm, das den Rahmen fⁿr die
  267. Anwendung der beschriebenen Funktionen bildet.  ZusΣtzlich verwendet es
  268. weitere Unterroutinen, die rein programmiertechnischer Natur sind und
  269. im folgenden unabhΣngig vom mathematischen Problem beschrieben werden.
  270.  
  271. @<Die |main|-Funktion@>=
  272. int main()
  273.    {
  274.    complex **Matrix,**Adjunkte,**Inverse;
  275.    complex Determinante;
  276.    int i,j,Dimension=4,corralloc=1;
  277.  
  278.    @<Allokiere die zu invertierende |Matrix|@>@;
  279.    @<Allokiere die |Adjunkte|               @>@;
  280.    @<Allokiere die |Inverse|                @>@;
  281.  
  282.    if(corralloc) {
  283.       MatrixInit(Dimension,Matrix);
  284.       MatrixDisplay(Dimension,Matrix);
  285.       AdjunkteMatrix(Matrix,Adjunkte);
  286.       @<Laplace-Entwicklung der |Determinante|n@>@;
  287.       @<Berechne die |Inverse|                 @>@;
  288.       MatrixDisplay(Dimension,Inverse);
  289.       }
  290.  
  291.    @<Gib den Speicher wieder frei@>@;
  292.    return(corralloc);
  293.    }
  294.  
  295. @ Fⁿr die formatierte Ein- und Ausgabe, die dynamische Speicherverwaltung
  296. sowie die mathematischen Funktionen ben÷tigen wir die
  297. Standarddeklarationen, wie sie in den Include-Dateien zu finden sind.
  298.  
  299. @<Globale \#|include|s@>=
  300. #include <math.h>
  301. #include <complex.h>
  302. #include <stdio.h>
  303. #include <stdlib.h>
  304. @<ZusΣtzliche Deklarationen fⁿr den Coprozessor@>
  305.  
  306. @ Bei der Benutzung des mathematischen Coprozessors sollten zusΣtzlich zu
  307. {\tt math.h} die speziellen Funktionsdeklarationen eingebunden werden.
  308. Dies gilt in diesem Fall speziell fⁿr den Commodore Amiga und den {\mc
  309. ANSI-C}-Compiler von {\mc SAS}~Institute, Cary (North Carolina).
  310.  
  311. @<ZusΣtzliche Deklarationen fⁿr den Coprozessor@>=
  312. #ifdef _M68881
  313. #include <m68881.h>
  314. #endif
  315. @^SystemabhΣngigkeiten@>
  316.  
  317. @ Die aktuelle Versionsnummer dieses Programmes wird nach dem \glqq Style
  318. Guide\grqq\ von Commodore in einer globalen Formatzeichenkette abgelegt und
  319. kann mit der Systemroutine {\tt version Matrix} abgefragt werden.
  320.  
  321. @<Versionsnummer@>=
  322. const char *Version = "$VER: MATRIXINVERTIERUNG 2.0 (20.11.1993)";
  323. @^SystemabhΣngigkeiten@>
  324.  
  325. @ Die meisten Routinen dieses Programmes sind unabhΣngig von der
  326. gewΣhlten |Dimension| des Problems.  Alle aber stellen nur minimale
  327. Forderungen an die Gestalt der verwendeten Matrizen, da sie lediglich mit
  328. Zeigern auf entsprechende Felder versorgt werden mⁿssen.  Damit
  329. lΣ▀t sich aber auch die Eingabe des Ausgangsproblems fast beliebig
  330. gestalten.  Bei dieser allgemeinen Implementierung kann dies auf zwei
  331. verschiedene Weisen geschehen.  Standardeingabe ist die Datei
  332. \glq{\tt Matrix.input}\grq, falls diese im aktuellen Verzeichnis vorhanden
  333. ist.  Falls nicht, wird der Benutzer zur elementweisen Eingabe der
  334. komplexen Elemente der |Matrix| aufgefordert.  Wird eine andere
  335. Verfahrensweise gewⁿnscht, so mu▀ lediglich diese Funktion zur Eingabe
  336. und die weiter unten beschriebene Funktion zur Ausgabe der Problemstellung
  337. geΣndert oder angepa▀t werden.
  338.  
  339. @<Funktionen@>=
  340. void MatrixInit(int Dimension,complex **Matrix)
  341.    {
  342.    int i,j;
  343.    double Realteil,Imagteil;
  344.    FILE *fp;
  345.  
  346.    if(fp = fopen("Matrix.input","r")) {
  347.       for(i=0; i<Dimension; i++) {
  348.          for(j=0; j<Dimension; j++) {
  349.             fscanf(fp,"(%lf,%lf)",&Realteil,&Imagteil);
  350.             Matrix[i][j] = complex(Realteil,Imagteil);
  351.             }
  352.          }
  353.       fclose(fp);
  354.       }
  355.    else {
  356.       for(i=0; i<Dimension; i++) {
  357.          for(j=0; j<Dimension; j++) {
  358.             printf("Real A[%d][%d] = ",i+1,j+1);
  359.             scanf("%lf",&Realteil);
  360.             printf("Imag A[%d][%d] = ",i+1,j+1);
  361.             scanf("%lf",&Imagteil);
  362.             Matrix[i][j] = complex(Realteil,Imagteil);
  363.             }
  364.          fputc('\n',stdout);
  365.          }
  366.       }
  367.    }
  368. @^BeschrΣnkung der Allgemeinheit@>
  369. @^SystemabhΣngigkeiten@>
  370.  
  371. @ Ebenso einfach wie die Eingabe ist auch die Ausgaberoutine gestaltet.
  372. Sie zeigt eine quadratische |Dimension|-reihige |Matrix| mit komplexen
  373. EintrΣgen zum einen am Bildschirm an und schreibt gleichzeitig das
  374. Ergebnis im gleichen Format in die Datei \glq{\tt Matrix.output}\grq, das
  375. beim Einlesen aus \glq{\tt Matrix.input}\grq\ erwartet wird.
  376.  
  377. @<Funktionen@>=
  378. void MatrixDisplay(int Dimension,complex **Matrix)
  379.    {
  380.    int i,j;
  381.    FILE *fp;
  382.  
  383.    fp = fopen("Matrix.output","w");
  384.    for(i=0; i<Dimension; i++) {
  385.       for(j=0; j<Dimension; j++) {
  386.          if(fp) fprintf(fp,"(%lf,%lf)",real(Matrix[i][j]),imag(Matrix[i][j]));
  387.          printf("(%lf,%lf) ",real(Matrix[i][j]),imag(Matrix[i][j]));
  388.          }
  389.       if(fp) fputc('\n',fp);
  390.       fputc('\n',stdout);
  391.       }
  392.    fputc('\n',stdout);
  393.    fclose(fp);
  394.    }
  395. @^BeschrΣnkung der Allgemeinheit@>
  396. @^SystemabhΣngigkeiten@>
  397.  
  398. @ Was ein echtes \CEE/-Programm sein will, das verwendet so wenig wie
  399. m÷glich feste Gr÷▀en bei der Definition von SpeicherflΣchen.
  400. Zwar sind in diesem Fall alle Dimensionen bekannt und bei jedem Lauf immer
  401. gleich, aber trotzdem ist es eine nette ▄bung, den ben÷tigten
  402. Speicherplatz \glqq dynamisch\grqq\ anzufordern und nach seiner Benutzung
  403. wieder ordnungsgemΣ▀ freizugeben.  Die |Matrix|, ihre |Adjunkte| und
  404. die zu berechnende |Inverse| werden lokal in |main| als Zeigervariablen
  405. definiert und erhalten auch lokal ihren Speicherplatz zugewiesen.
  406.  
  407. @<Allokiere die zu invertierende |Matrix|@>=
  408.    if(Matrix = (complex **)calloc(Dimension,sizeof(complex *))) {
  409.       for(i=0; i<Dimension; i++)
  410.          if(!(Matrix[i] = (complex *)calloc(Dimension,sizeof(complex))))
  411.             corralloc = 0;
  412.       }
  413.    else corralloc = 0;
  414.  
  415. @ @<Allokiere die |Adjunkte|@>=
  416.    if(Adjunkte = (complex **)calloc(Dimension,sizeof(complex *))) {
  417.       for(i=0; i<Dimension; i++)
  418.          if(!(Adjunkte[i] = (complex *)calloc(Dimension,sizeof(complex))))
  419.             corralloc = 0;
  420.       }
  421.    else corralloc = 0;
  422.  
  423. @ @<Allokiere die |Inverse|@>=
  424.    if(Inverse = (complex **)calloc(Dimension,sizeof(complex *))) {
  425.       for(i=0; i<Dimension; i++)
  426.          if(!(Inverse[i] = (complex *)calloc(Dimension,sizeof(complex))))
  427.             corralloc = 0;
  428.       }
  429.    else corralloc = 0;
  430.  
  431. @ Nach der erfolgreichen Durchfⁿhrung aller Berechnungsschritte mu▀ vor
  432. Beendigung des Programmes der angeforderte Speicher wieder freigegeben werden.
  433. Dies geschieht in umgekehrter Reihenfolge zur Allokierung.
  434.  
  435. @d FreeObject(A) if(A) free(A);
  436.  
  437. @<Gib den Speicher wieder frei@>=
  438.    for(i=Dimension-1; i>=0; i--) {
  439.       FreeObject(Inverse[i]);
  440.       FreeObject(Adjunkte[i]);
  441.       FreeObject(Matrix[i]);
  442.       }
  443.  
  444.    FreeObject(Inverse);
  445.    FreeObject(Adjunkte);
  446.    FreeObject(Matrix);
  447.  
  448. @ Noch radikaler als bei den genannten Matrizen erfolgt die Lokalisierung
  449. der |Hilfsmatrix|.  Sie wird erst innerhalb der Funktion |AdjunkteMatrix|
  450. definiert und mit Speicherplatz besorgt.
  451.  
  452. @<Allokiere die |Hilfsmatrix|@>=
  453.    if(Hilfsmatrix = (complex **)calloc(3,sizeof(complex *))) {
  454.       for(i=0; i<3; i++)
  455.          if(!(Hilfsmatrix[i] = (complex *)calloc(3,sizeof(complex))))
  456.             corralloc = 0;
  457.       }
  458.    else corralloc = 0;
  459. @^BeschrΣnkung der Allgemeinheit@>
  460.  
  461. @ @<Gib den Speicher der |Hilfsmatrix| wieder frei@>=
  462.    for(i=0; i<3; i++) FreeObject(Hilfsmatrix[i]);
  463.    FreeObject(Hilfsmatrix);
  464. @^BeschrΣnkung der Allgemeinheit@>
  465.  
  466. @ Als letztes Modul im Programmflu▀ angelegt, jedoch in der
  467. endgⁿltigen \CEE/-Quelldatei sehr weit vorne, stehen hier die Prototypen
  468. aller verwendeten Funktionen.  Die Beschreibung der Parameterliste und die
  469. Angabe des Rⁿckgabewertes erm÷glicht es dem Compiler, eventuelle
  470. Programmierfehler festzustellen und zu melden.
  471.  
  472. @<Funktionsprototypen@>=
  473. void MatrixInit(int,complex **);                        @/
  474. void MatrixReduktion(int,complex **,complex **,int,int);@/
  475. void MatrixDisplay(int,complex **);                     @/
  476. void AdjunkteMatrix(complex **,complex **);             @/
  477. int main(void);
  478.  
  479. @* Index.  Zum Abschlu▀ der Dokumentation folgen noch das
  480. Stichwortverzeichnis mit sΣmtlichen verwendeten Bezeichnern sowie eine
  481. Zusammenfassung aller Programmodule.  Zu beachten sind insbesondere die
  482. EintrΣge \glqq BeschrΣnkung der Allgemeinheit\grqq\ und \glqq
  483. SystemabhΣngigkeiten\grqq.
  484.