Beruflich Dokumente
Kultur Dokumente
linux_c
linux_c
Matrixoperationen A + B, A − B, A ∗ B
(1) Implementation als ein einziges C-Programm mit allen Komponenten
// matrix_prog.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// Prototypen
laMatrix laMatrixNeu(int n, int m);
void laVernichte(laMatrix A);
void laDim(laMatrix A, int *n, int *m);
void laMatEinlesen(laMatrix *A);
void laMatAusgeben(laMatrix A);
void laAdd(laMatrix A, laMatrix B, laMatrix *C);
void laMult(laMatrix A, laMatrix B, laMatrix *C);
void laSub(laMatrix A, laMatrix B, laMatrix *C);
int main()
{
int n,m;
laMatrix A,B,C,S,D,P;
char kont,ret;
1
printf("Programm\n");
printf("Matrixoperationen\n");
printf("-----------------\n\n");
printf("Matrix A\n");
laMatEinlesen(&A);
//scanf("%c",&ret); // fflush(stdin);
printf("Kontrollausgabe A (j/n)? ");
scanf("%c%c",&kont,&ret);
if(kont==’j’)
{
laDim(A,&n,&m);
printf("\nDimension A(n,m): n=%i, m=%i\n",n,m);
printf("\nA\n");
laMatAusgeben(A);
printf("-----------------------------------------------------------------------------\n");
scanf("%c",&ret);
}
printf("Matrix B\n");
laMatEinlesen(&B);
//scanf("%c",&ret); // fflush(stdin);
printf("Kontrollausgabe B (j/n)? ");
scanf("%c%c",&kont,&ret); // fflush(stdin);
if(kont==’j’)
{
laDim(A,&n,&m);
printf("\nDimension B(n,m): n=%i, m=%i\n",n,m);
printf("\nB\n");
laMatAusgeben(B);
printf("-----------------------------------------------------------------------------\n");
scanf("%c",&ret);
}
printf("Matrix C\n");
laMatEinlesen(&C);
//scanf("%c",&ret); // fflush(stdin);
printf("Kontrollausgabe C (j/n)? ");
scanf("%c%c",&kont,&ret);
if(kont==’j’)
{
laDim(A,&n,&m);
printf("\nDimension C(n,m): n=%i, m=%i\n",n,m);
printf("\nC\n");
laMatAusgeben(C);
printf("-----------------------------------------------------------------------------\n");
scanf("%c",&ret);
}
printf("\nErgebnisse");
laAdd(A,B,&S);
printf("\nS=A+B\n");
laMatAusgeben(S);
laSub(A,B,&D);
printf("\nD=A-B\n");
laMatAusgeben(D);
laMult(A,C,&P);
printf("\nP=A*C\n");
laMatAusgeben(P);
scanf("%c",&ret);
laVernichte(A);
laVernichte(B);
laVernichte(C);
laVernichte(D);
laVernichte(S);
laVernichte(P);
return 0;
}
/*----------------------------------------------------------------------------*/
2
laMatrix laMatrixNeu(int n, int m)
{
unsigned i;
char ret;
laMatrix A;
if((A = malloc(sizeof(double*)*n+2*sizeof(int)))==NULL)
{
fprintf(stderr,"\nzu wenig Speicher\n");
scanf("%c",&ret);
exit(EXIT_FAILURE);
}
*((int*)A) = n;
*(((int*)A)+1) = m;
A = (double**)(((int*)A)+2);
for(i=0;i<n;i++)
if((*(A+i) = malloc(sizeof(double)*m))==NULL)
{
fprintf(stderr,"\nzu wenig Speicher\n");
scanf("%c",&ret);
exit(EXIT_FAILURE);
}
return(A);
}
/*----------------------------------------------------------------------------*/
void laVernichte(laMatrix A)
{
unsigned i,n;
n = *(((int*)A)-2);
for(i=0;i<n;i++)
free(*(A+i));
free(((int*)A)-2);
}
/*----------------------------------------------------------------------------*/
void laMatAusgeben(laMatrix A)
{
int i,j,n,m;
laDim(A,&n,&m);
3
for(i=0;i<n;i++)
{
for(j=0;j<m;j++) printf(" %10.6lf ",A[i][j]);
printf("\n");
}
}
/*----------------------------------------------------------------------------*/
laDim(A,&n,&m);
laDim(B,&r,&s);
if((n!=r)||(m!=s))
{
printf("\nFehler: Matrizen sind nicht von gleicher Dimension\n");
scanf("%c",&ret);
exit(EXIT_FAILURE);
}
else
{
*C = laMatrixNeu(n,m);
for(i=0;i<n;i++)
for(j=0;j<m;j++)
(*C)[i][j] = A[i][j]+B[i][j];
}
}
/*----------------------------------------------------------------------------*/
laDim(A,&n,&m);
laDim(B,&k,&l);
if ((n!=k)||(m!=l))
{
printf("\nFehler: Matrixdimension(en) nicht gleich\n");
scanf("%c",&ret);
exit(EXIT_FAILURE);
}
*C = laMatrixNeu(n,m);
for(i=0;i<n;i++)
for(j=0;j<m;j++)
(*C)[i][j] = A[i][j]-B[i][j];
}
/*----------------------------------------------------------------------------*/
laDim(A,&n,&m);
laDim(B,&r,&s);
if(m!=r)
{
printf ("\nFehler: innere Dimensionen unzulaessig\n");
scanf("%c",&ret);
exit(EXIT_FAILURE);
}
*C = laMatrixNeu(n,s);
for(i=0;i<n;i++)
for(j=0;j<s;j++)
{
h = 0;
for(k=0;k<m;k++) h += A[i][k]*B[k][j];
(*C)[i][j] = h;
}
}
4
Man klickt nun auf das Programm matrix_prog.c und kommt zum Menüpunkt Ausführen
⇒ Kompilieren u. Ausführen
Es folgen Informationen zum Übersetzen und im Kompilier Log steht
Fuehrt gcc.exe... aus
gcc.exe "C:\d\Neundorf\nwptexte\tech_phy\05\dev_cpp\projekt0\matrix_prog.c" -o
"C:\d\Neundorf\nwptexte\tech_phy\05\dev_cpp\projekt0\matrix_prog.exe" -s
-I"C:\Dev-Cpp\include"
-I"c:\d\neundorf\nwptexte\tech_phy\05\dev_cpp\projekt0"
-L"C:\Dev-Cpp\lib"
Ausfuehrung beendet
Kompilierung erfolgreich
Die Beispiele werden als ASCII-Dateien in der Datenreihenfolge n, m, A(1..n, 1..m), b(1..n), ...
bereitgestellt. Der Dateiname für die Daten zur Matrix usw. wird eingelesen.
Zum Test nehmen wir die (3×3)- Matrizen aus den Dateien matrix23, matrix57, matrix58
matrix3
------------------
2 2
1.441969 1.040807
1.040807 0.751250
0.401162
0.289557
Loesung:
1
-1
EW:
2.193218999999544
4.5595081932092e-13
5
Eingabe- und Ergebnisfenster
2 C:\d\Neundorf\nwptexte\tech phy\05\dev cpp\projekt0\matrix prog.exe
Programm
Matrixperationen
————————–
Matrix A
Dateiname fuer Daten zur Matrix : matrix23
Kontrollausgabe A (j/n)? j
Dimension A(n,m): n=3, m=3
A
1.000000 -2.000000 2.000000
-1.000000 1.000000 -1.000000
-2.000000 -2.000000 1.000000
——————————————————————————————————–
Matrix B
Dateiname fuer Daten zur Matrix : matrix57
Kontrollausgabe B (j/n)? j
Dimension B(n,m): n=3, m=3
B
1.000000 -2.000000 2.000000
-1.000000 2.000000 -1.000000
-2.000000 4.000000 1.000000
——————————————————————————————————–
Matrix C
Dateiname fuer Daten zur Matrix : matrix58
Kontrollausgabe C (j/n)? j
Dimension C(n,m): n=3, m=3
C
2.000000 2.000000 2.000000
1.000000 3.000000 0.000000
2.000000 4.000000 1.000000
——————————————————————————————————–
Ergebnisse
S=A+B
2.000000 -4.000000 4.000000
-2.000000 3.000000 -2.000000
-4.000000 2.000000 2.000000
D=A-B
0.000000 0.000000 0.000000
0.000000 -1.000000 0.000000
0.000000 -6.000000 0.000000
P=A*C
4.000000 4.000000 4.000000
-3.000000 -3.000000 -3.000000
-4.000000 -6.000000 -3.000000
6
(2) Implementation als ein einziges C++-Programm mit allen Komponenten
Im Vergleich zum Programm matrix_prog.c sind an zwei Stellen der dynamischen Reser-
vierung von Speicherplatz in der Funktion laMatrixNeu Veränderungen vorzunehmen. Alles
andere kann übernommen werden.
// matrix_prog.cpp
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// Prototypen
laMatrix laMatrixNeu(int n, int m);
void laVernichte(laMatrix A);
void laDim(laMatrix A, int *n, int *m);
void laMatEinlesen(laMatrix *A);
void laMatAusgeben(laMatrix A);
void laAdd(laMatrix A, laMatrix B, laMatrix *C);
void laMult(laMatrix A, laMatrix B, laMatrix *C);
void laSub(laMatrix A, laMatrix B, laMatrix *C);
int main()
{
int n,m;
laMatrix A,B,C,S,D,P;
char kont,ret;
...
}
/*----------------------------------------------------------------------------*/
laMatrix laMatrixNeu(int n, int m)
{
unsigned i;
char ret;
laMatrix A;
// if((A = malloc(sizeof(double*)*n+2*sizeof(int)))==NULL) // C
if(((void*)A = malloc(sizeof(double*)*n+2*sizeof(int)))==NULL) // C++
{
fprintf(stderr,"\nzu wenig Speicher\n");
scanf("%c",&ret);
exit(EXIT_FAILURE);
}
*((int*)A) = n;
*(((int*)A)+1) = m;
A = (double**)(((int*)A)+2);
for(i=0;i<n;i++)
// if((*(A+i) = malloc(sizeof(double)*m))==NULL) // C
if(((void*)(*(A+i)) = malloc(sizeof(double)*m))==NULL) // C++
{
fprintf(stderr,"zu wenig Speicher\n\r");
scanf("%c",&ret);
exit(EXIT_FAILURE);
}
return(A);
}
/*----------------------------------------------------------------------------*/
...
7
(3) Implementation als ein Projekt in C
Alle Vorwärtsdeklarationen und eine Sammlung von Prototypen befinden sich im Header-
File la.h und sind im Wesentlichen selbstkommentierend.
Gebraucht werden davon nur die Funktionen laMatrixNeu, laVernichte, laDim,
laMatEinlesen, laMatAusgeben, laAdd, laMult, laSub.
// la.h, Header-File fuer eine Bibliothek fuer lineare Algebra
#include <stdio.h>
#include <stdlib.h>
8
laMatrix laTransponiere(laMatrix A);
/* Transponiert die Matrix A. Da die Matrix i. Allg. nicht quadratisch
ist, muss auch der Speicher umorganisiert werden.
A zeigt also nach dem Aufruf auf einen anderen Speicherbreich,
der urspruengliche Speicherbereich wird freigegeben. */
/*----------------------------------------------------------------------------*/
laMatrix laMatrixNeu(int n, int m)
{
unsigned i;
char ret;
laMatrix A;
if((A = malloc(sizeof(double*)*n+2*sizeof(int)))==NULL)
{
fprintf(stderr,"\nzu wenig Speicher\n");
scanf("%c",&ret);
exit(EXIT_FAILURE);
}
*((int*)A) = n;
*(((int*)A)+1) = m;
A = (double**)(((int*)A)+2);
for(i=0;i<n;i++)
if((*(A+i) = malloc(sizeof(double)*m))==NULL)
{
fprintf(stderr,"\nzu wenig Speicher\n");
scanf("%c",&ret);
exit(EXIT_FAILURE);
}
return(A);
}
/*----------------------------------------------------------------------------*/
9
void laVernichte(laMatrix A)
{
unsigned i,n;
n = *(((int*)A)-2);
for(i=0;i<n;i++) free(*(A+i));
free(((int*)A)-2);
}
/*----------------------------------------------------------------------------*/
void laDim(laMatrix A, int *n, int *m)
{
*n = *(((int*)A)-2);
*m = *(((int*)A)-1);
}
/*----------------------------------------------------------------------------*/
laMatrix laTransponiere(laMatrix A)
{
int n,m,i,j;
laMatrix B;
laDim(A,&n,&m);
B = laMatrixNeu(m,n);
for(i=0;i<=n;++i)
for(j=0;j<=m;++j)
B[j][i] = A[i][j];
laVernichte(A);
return(B);
}
Die beiden Funktionen für die Ein- und Ausgabe sind problemangepasst und extra Quell-
texte. Darin aufgerufen werden auch die Funktionen laMatrixNeu, laDim.
// laMatEinlesen.c
#include <stdlib.h>
#include "la.h"
void laMatAusgeben(laMatrix A)
{
int i,j,n,m;
laDim(A,&n,&m);
for(i=0;i<n;i++)
{
for(j=0;j<m;j++) printf(" %10.6lf ",A[i][j]);
printf("\n");
}
}
10
Dazu kommen noch die Quellen der eigentlichen Matrixoperationen laAdd, laMult, laSub.
// laAdd.c, C = A+B
#include <stdlib.h>
#include "la.h"
laDim(A,&n,&m);
laDim(B,&r,&s);
if((n!=r)||(m!=s))
{
printf("\nFehler: Matrizen sind nicht von gleicher Dimension\n");
scanf("%c",&ret); exit(EXIT_FAILURE);
}
else
{
*C = laMatrixNeu(n,m);
for(i=0;i<n;i++)
for(j=0;j<m;j++) (*C)[i][j] = A[i][j]+B[i][j];
}
}
/*----------------------------------------------------------------------------*/
// laMult.c, C = AB algebraisch
#include <stdlib.h>
#include "la.h"
laDim(A,&n,&m);
laDim(B,&r,&s);
if(m!=r)
{
printf ("\nFehler: innere Dimensionen unzulaessig\n");
scanf("%c",&ret); exit(EXIT_FAILURE);
}
*C = laMatrixNeu(n,s);
for(i=0;i<n;i++)
for(j=0;j<s;j++)
{
h = 0;
for(k=0;k<m;k++) h += A[i][k]*B[k][j];
(*C)[i][j] = h;
}
}
/*----------------------------------------------------------------------------*/
// laSub.c, C = A-B
#include <stdlib.h>
#include "la.h"
laDim(A,&n,&m);
laDim(B,&k,&l);
if((n!=k)||(m!=l))
{
printf("\nFehler: Matrixdimension(en) nicht gleich\n");
scanf("%c",&ret); exit(EXIT_FAILURE);
}
*C = laMatrixNeu(n,m);
for(i=0;i<n;i++)
for(j=0;j<m;j++) (*C)[i][j] = A[i][j]-B[i][j];
}
11
Nun fehlt nur noch der Quelltext (Rahmenprogramm) matrix_main.c mit der main-Funktion.
In ihm befinden sich die notwendigen include-Anweisungen, die Eingaben, Berechnungen
und Ausgaben.
// matrix_main.c
// Projekt: main-Funktion
// sonstige Komponenten: la.c, laMatEinlesen.c, laMatAusgeben.c, laAdd.c, laSub.c, laMult.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "la.h"
int main()
{
int n,m;
laMatrix A,B,C,S,D,P;
char kont,ret;
printf("Projekt\n");
printf("Matrixoperationen\n");
printf("-----------------\n\n");
printf("Matrix A\n");
laMatEinlesen(&A);
// scanf("%c",&ret); // fflush(stdin);
printf("Kontrollausgabe A (j/n)? ");
scanf("%c%c",&kont,&ret);
if(kont==’j’)
{
laDim(A,&n,&m);
printf("\nDimension A(n,m): n=%i, m=%i\n",n,m);
printf("\nA\n");
laMatAusgeben(A);
printf("-----------------------------------------------------------------------------\n");
scanf("%c",&ret);
}
printf("Matrix B\n");
laMatEinlesen(&B);
// scanf("%c",&ret); // fflush(stdin);
printf("Kontrollausgabe B (j/n)? ");
scanf("%c%c",&kont,&ret); // fflush(stdin);
if(kont==’j’)
{
laDim(A,&n,&m);
printf("\nDimension B(n,m): n=%i, m=%i\n",n,m);
printf("\nB\n");
laMatAusgeben(B);
printf("-----------------------------------------------------------------------------\n");
scanf("%c",&ret);
}
printf("Matrix C\n");
laMatEinlesen(&C);
// scanf("%c",&ret); // fflush(stdin);
printf("Kontrollausgabe C (j/n)? ");
scanf("%c%c",&kont,&ret);
if(kont==’j’)
{
laDim(A,&n,&m);
printf("\nDimension C(n,m): n=%i, m=%i\n",n,m);
printf("\nC\n");
laMatAusgeben(C);
printf("-----------------------------------------------------------------------------\n");
scanf("%c",&ret);
}
printf("\nErgebnisse");
laAdd(A,B,&S);
printf("\nS=A+B\n");
laMatAusgeben(S);
laSub(A,B,&D);
printf("\nD=A-B\n");
12
laMatAusgeben(D);
laMult(A,C,&P);
printf("\nP=A*C\n");
laMatAusgeben(P);
scanf("%c",&ret);
laVernichte(A);
laVernichte(B);
laVernichte(C);
laVernichte(D);
laVernichte(S);
laVernichte(P);
return 0;
}
Klickt man den Schalter Klassen an, so erscheint im Projektfenster eine umfangreiche Liste
von Klassen und Funktionen zum Projekt.
Man klickt nun auf das Projekt matrix0 und kommt zum Menüpunkt Ausführen
⇒ Kompilieren u. Ausführen
Es folgen Informationen zum Übersetzen und im Kompilier Log steht
Building Makefile: "C:\d\Neundorf\nwptexte\tech_phy\05\dev_cpp\projekt0\Makefile.win"
Fuehrt make... aus
Ausfuehrung beendet
Kompilierung erfolgreich
13
Im Verzeichnis stehen dann die Projektdatei matrix0.dev
[Project]
FileName=matrix0.dev
Name=matrix0
UnitCount=7
Type=1
Ver=1
ObjFiles=
Includes=
Libs=
PrivateResource=
ResourceIncludes=
MakeIncludes=
Resources=
Compiler=
Linker=
IsCpp=0
Icon=
ExeOutput=
ObjectOutput=
OverrideOutput=0
OverrideOutputName=
Folders=
CommandLine=
Focused=6
Order=0,1,2,3,5,4,-1,6
[Unit2]
FileName=laAdd.c
Open=1
Folder=
Top=0
CursorCol=2
CursorRow=2
TopLine=1
LeftChar=1
[Unit3]
FileName=laMatAusgeben.c
Open=1
Folder=
Top=0
CursorCol=1
CursorRow=2
TopLine=1
LeftChar=1
[Unit4]
FileName=laMatEinlesen.c
Open=1
Folder=
Top=0
CursorCol=1
CursorRow=2
TopLine=1
LeftChar=1
[Unit5]
FileName=laMult.c
Open=1
Folder=
Top=0
CursorCol=3
CursorRow=26
TopLine=6
LeftChar=1
[Unit6]
FileName=laSub.c
Open=1
Folder=
Top=0
CursorCol=3
CursorRow=20
14
TopLine=1
LeftChar=1
[Unit7]
FileName=matrix_main.c
Open=0
Folder=
Top=0
CursorCol=3
CursorRow=23
TopLine=4
LeftChar=1
[Views]
ProjectView=1
[Unit1]
FileName=la.c
Open=1
Folder=
Top=0
CursorCol=1
CursorRow=2
TopLine=1
LeftChar=1
Im Verzeichnis stehen dann die ausführbare Datei matrix0.exe sowie alle Objektdateien
*.o der Projektquellen.
Dazu kommt zum Projekt noch das sogenannte Makefile Makefile.win.
# Project: matrix0
# Makefile created by Dev-C++ 4.9.6.0
CC = gcc.exe
WINDRES = windres.exe
RES =
OBJ = la.o laAdd.o laMatAusgeben.o laMatEinlesen.o laMult.o laSub.o matrix_main.o $(RES)
LIBS = -L"C:/Dev-Cpp/lib"
INCS = -I"C:/Dev-Cpp/include" -I"c:/d/neundorf/nwptexte/tech_phy/05/dev_cpp/projekt0"
BIN = matrix0.exe
CFLAGS = $(INCS) -s
$(BIN): $(OBJ)
$(CC) $(OBJ) -o "matrix0.exe" $(LIBS) $(CFLAGS)
la.o: la.c
$(CC) -c la.c -o la.o $(CFLAGS)
laAdd.o: laAdd.c
$(CC) -c laAdd.c -o laAdd.o $(CFLAGS)
laMatAusgeben.o: laMatAusgeben.c
$(CC) -c laMatAusgeben.c -o laMatAusgeben.o $(CFLAGS)
laMatEinlesen.o: laMatEinlesen.c
$(CC) -c laMatEinlesen.c -o laMatEinlesen.o $(CFLAGS)
laMult.o: laMult.c
$(CC) -c laMult.c -o laMult.o $(CFLAGS)
laSub.o: laSub.c
$(CC) -c laSub.c -o laSub.o $(CFLAGS)
matrix_main.o: matrix_main.c
$(CC) -c matrix_main.c -o matrix_main.o $(CFLAGS)
Eingaben und Ergebnisse sind nun als Projekt wie im Teil (1).
15
2 C und C++ unter Linux 9.0
Auf der Oberfläche stehen die Compiler cc und c++ sowie gcc und g++ (GNU-Compiler)
zur Verfügung. Zwischen den beiden C-Compilern lässt sich kein Unterschied feststellen, ge-
nauso bei den Compilern für C++.
Die Entwicklungsumgebung basiert auf einer Kommandosprache und die Einstellungen können
dort erfolgen. Im Vergleich mit der Entwicklungsumgebung von Dev-C++ ist der Umgang
nicht ganz so bequem. Außerdem gibt es zur Windows-Umgebung kleine Unterschiede bez.
der Benutzung bestimmter Anweisungen und Header-Files.
Die Arbeit soll an einfachen Beispielen erläutert werden. Die Numerik dazu sowie die Pro-
grammstruktur befinden sich im Skript DEV CPP.TEX(PS). Nach diesem Muster können
andere Programme gleichfalls erstellt und abgearbeitet werden.
16
2.2 Erzeugung einer Bibliothek
Zu jedem Quelltext kann man seine Objektdatei erzeugen.
Manchmal ist es jedoch sinnvoller und überschaubarer, zunächst einige Quelltexte (z. B.
Funktionen) in einem Verbund als Bibliothek zusammen zu stellen. Dabei kann es jedoch
passieren, dass die einzelnen Quellen dieselben Include-Anweisungen verwenden. Da die
Bibliothek nur eine davon braucht, sind die sich wiederholenden Includes zu entfernen bzw.
heraus zu kommentieren.
Danach kann aus der Bibliothek wiederum eine Objektdatei erzeugt werden.
Zum Erzeugen einer Bibliothek und Anhängen von weiteren Dateien an diese gibt es das
Kommando cat.
cat quelle1.c > laLib.c --> Erzeugen einer Bibliothek mit dem Namen laLib.c
cat quelle2.c >> laLib.c --> Anhaengen an diese
cat quelle3.c >> laLib.c
...
gcc -c laLib.c --> Erzeugung der Objektdatei laLib.o (i. Allg. kein selbstaendiger Aufruf)
17
Um das abzukürzen, kann man die Module vorher zusammenfassen zu einer Bibliothek.
cat la.c > laLib1.c --> Erzeugen einer Bibliothek mit dem Namen laLib1.c
cat laAdd.c >> laLib1.c --> Anhaengen an diese
cat laMult.c >> laLib1.c
cat laSub.c >> laLib1.c
cat laMatEinlesen.c >> laLib1.c
cat laMatAusgeben.c >> laLib1.c --> laLib1.c "saeubern"
---------------------------------------------------------------------------------------------------
gcc -c laLib1.c --> Erzeugung der Objektdatei laLib1.o
Würde man in laLib1.c nicht die sich wiederholenden include-Anweisungen löschen, ergäbe
sich bei gcc -c laLib1.c folgende Fehlermeldung.
05/make0> gcc -c laLib1.c
In file included from laLib1.c:67:
la.h:5: error: redefinition of ‘laMatrix’
la.h:5: error: ‘laMatrix’ previously declared here
In file included from laLib1.c:93:
la.h:5: error: redefinition of ‘laMatrix’
la.h:5: error: ‘laMatrix’ previously declared here
In file included from laLib1.c:121:
la.h:5: error: redefinition of ‘laMatrix’
la.h:5: error: ‘laMatrix’ previously declared here
In file included from laLib1.c:145:
la.h:5: error: redefinition of ‘laMatrix’
la.h:5: error: ‘laMatrix’ previously declared here
In file included from laLib1.c:171:
la.h:5: error: redefinition of ‘laMatrix’
la.h:5: error: ‘laMatrix’ previously declared here
Die elegante Version verwendet jedoch ein Makefile, dass alle Schritte und Dateien zusam-
menfasst und mittels make aufgerufen wird. Heißt das Makefile standardmäßig makefile
oder Makefile, so erfolgt sein Aufruf einfach mit make. Hat es einen anderen Namen, so
notieren wir make -f makefile_name.
Hier ist die Erstellung eines Makefiles notwendig. In Dev-C++ wurde dies beim Kompilieren
automatisch erzeugt.
Wir demonstrieren die stufenweise Entwicklung der Version.
Stufe 1
Dabei kann es jedoch wie oben passieren, dass ursprünglich die einzelnen Quellen dieselben
include-Anweisungen verwenden. Folgende Version ist also fehlerhaft.
# makefile0
Alles:
cat $(Dir)la.c > laLib.c
cat $(Dir)laAdd.c >> laLib.c
cat $(Dir)laMult.c >> laLib.c
cat $(Dir)laSub.c >> laLib.c
cat $(Dir)laMatEinlesen.c >> laLib.c
cat $(Dir)laMatAusgeben.c >> laLib.c
gcc -c laLib.c
gcc -c matrix_main.c
gcc -o mein_prog4 matrix_main.o laLib.o
18
Da die Bibliothek zu jedem Header-File nur eine include-Anweisung braucht, sind die sich
wiederholenden Includes zu entfernen bzw. heraus zu kommentieren.
Deshalb werden in den beiden ersten Stufen diese include-Anweisungen aus den Quel-
len laAdd.c, laMult.c, laSub.c, laMatEinlesen.c, laMatAusgeben.c herausgenom-
men. Die veränderten Quellen sind laAdd_.c, laMult_.c, laSub_.c, laMatEinlesen_.c,
laMatAusgeben_.c.
# makefile0_
Alles:
cat $(Dir)la.c > laLib.c
cat $(Dir)laAdd_.c >> laLib.c
cat $(Dir)laMult_.c >> laLib.c
cat $(Dir)laSub_.c >> laLib.c
cat $(Dir)laMatEinlesen_.c >> laLib.c
cat $(Dir)laMatAusgeben_.c >> laLib.c
gcc -c laLib.c
gcc -c matrix_main.c
gcc -o mein_prog4 matrix_main.o laLib.o
Stufe 2
Ähnlich zu Stufe 1 mit Weglassen der Kommentarzeilen und Verzeichniseinstellung
(mein_prog4 hat 13128 Byte).
# makefile0_kurz_
Alles:
cat la.c > laLib.c
cat laAdd_.c >> laLib.c
cat laMult_.c >> laLib.c
cat laSub_.c >> laLib.c
cat laMatEinlesen_.c >> laLib.c
cat laMatAusgeben_.c >> laLib.c
gcc -c laLib.c
gcc -c matrix_main.c
gcc -o mein_prog4 matrix_main.o laLib.o
Stufe 3
Diese Langform soll angegeben werden, um die Arbeit in einem aktuellen Verzeichnis zu-
sammen mit der Kopie von Dateien aus einem fernen Verzeichnis zu zeigen. Da hier alles im
aktuellen Verzeichnis stattfindet, vereinfacht sich die Situation. So muss die Datei la.h im
aktuellen Verzeichnis nicht kopiert werden. Der Kopierbefehl cp $(Dir)$(la).h . wird
als Kommentar notiert oder gelöscht.
Macht man es nicht, erfolgt wegen der nicht möglichen Kopie einer Datei auf sich selbst die
Fehlermeldung und Warnung
cp /export/home/neundorf/tech_phy/05/make0/la.h .
cp: /export/home/neundorf/tech_phy/05/make0/la.h und ./la.h sind die gleiche Datei
make: *** [libla.a] Fehler 1
Die Quelltexte müssen also nicht wie in den Stufen 1 und 2 bezüglich der Kopfzeilen
(include-Anweisungen) verändert werden.
19
# makefile
#
CC = gcc
CFlags = -g -c
#DFlags = -O -c
#
# fuer Physik ("roadrunner")
#Dir = /home/Studenten/neundorf/make0/
#Dir = /home/Studenten/Austausch/
#
la = la
Add = laAdd
Mult = laMult
Sub = laSub
Ein = laMatEinlesen
Aus = laMatAusgeben
#
mein_prog5: matrix_main.o libla.a
$(CC) -g -o mein_prog5 matrix_main.o -lm -lla -L./
#
matrix_main.o: matrix_main.c
$(CC) $(CFlags) matrix_main.c
#
libla.a: $(la).o $(Add).o $(Mult).o $(Sub).o $(Ein).o $(Aus).o
20
Stufe 4
Genauso kann man auf die anderen Kommandozeilen verzichten wie
$(la).c: $(Dir)$(la).c
cp $(Dir)$(la).h .
cp $(Dir)$(la).c .
Alle Quellen befinden sich im aktuellen Verzeichnis, so dass man diese nicht erst von woan-
ders dahin kopieren muss. Kommentarzeilen sind dabei meistens weggelassen worden. Das
verkürzte Makefile ist damit makefile_kurz (mein_prog5 hat 20198 Byte).
# makefile_kurz
#
CC = gcc
CFlags = -g -c
#
la = la
Add = laAdd
Mult = laMult
Sub = laSub
Ein = laMatEinlesen
Aus = laMatAusgeben
#
mein_prog5: matrix_main.o libla.a
$(CC) -g -o mein_prog5 matrix_main.o -lm -lla -L./
#
matrix_main.o: matrix_main.c
$(CC) $(CFlags) matrix_main.c
#
libla.a: $(la).o $(Add).o $(Mult).o $(Sub).o $(Ein).o $(Aus).o
ar r libla.a $(la).o $(Add).o $(Mult).o $(Sub).o $(Ein).o $(Aus).o
ar s libla.a
#
$(la).o: $(la).c
$(CC) $(CFlags) $(la).c
#
$(Add).o: $(Add).c
$(CC) $(CFlags) $(Add).c
#
$(Mult).o: $(Mult).c
$(CC) $(CFlags) $(Mult).c
#
$(Sub).o: $(Sub).c
$(CC) $(CFlags) $(Sub).c
#
$(Ein).o: $(Ein).c
$(CC) $(CFlags) $(Ein).c
#
$(Aus).o: $(Aus).c
$(CC) $(CFlags) $(Aus).c
21
2.5 Implementation von Algorithmen in C und Makefiles
Wir demonstrieren den Umgang mit Makefiles anhand von weiteren Beispielen und werden
dabei schrittweise vorgehen.
In den Demoprogrammen werden der Gauß-Algorithmus, das Newton-Verfahren und die
Vektoriteration in verschiedenen Versionen und Ausbaustufen implementiert.
Beispiel 1
Einzelnes Demoprogramm gauss1.c zum Gauß-Algorithmus.
Unter der Linux-Oberfläche ist im Programm das Header-File conio.h nicht vorhanden,
also die include-Anweisung #include <conio.h> nicht möglich und zu entfernen sowie
der getch()-Befehl durch char ret ... scanf("%c",&ret) zu ersetzen.
Dann genügt es, den Compiler aufzurufen und danach das Programm auszuführen.
gcc gauss1.c --> ausfuehrbare Datei ist standardmaessig a.out
gcc gauss1.c -lm Aufruf: a.out
gcc -o gauss1 gauss1.c -lm --> Aufruf: gauss1
Beispiel 2
Demoprogramm tgauss.c zum Gauß-Algorithmus mit zusätzlichen Quellen und Berechnun-
gen. In den Quellen ist die include-Anweisung #include <conio.h> zu entfernen, die pri-
vaten Header-File wie basis.h, vmblock.h, u_proto.h mittels #include "name" an-
stelle von #include <name> einzubinden und der getch-Befehl durch scanf("%c",&ret)
zu ersetzen.
Da wir im Verzeichnis arbeiten, wo alle Dateien zur Verfügung stehen, erstellt man folgendes
Makefile (Langform).
# makefile
#
CC = gcc
CFlags = -g -c
#
Dir = export/home/neundorf/tech_phy/05/make2/
# Dir = /home/Studenten/neundorf/make2/
# Dir = /home/Studenten/Austausch/
#
basis = basis
fgauss = fgauss
vmblock = vmblock
#
tgauss: tgauss.o libla.a
$(CC) -g -o tgauss tgauss.o -lm -lla -L./
#
tgauss.o: tgauss.c
$(CC) $(CFlags) tgauss.c
#
libla.a: $(basis).o $(fgauss).o $(vmblock).o
# Quellen aus dem Verzeichnis Dir holen.
# Anders, falls diese im aktuellen Verzeichnis sind.
# cp $(Dir)$(basis.h) .
# cp $(Dir)$(u_proto.h) .
# cp $(Dir)$(vmblock.h) .
ar r libla.a $(basis).o $(fgauss).o $(vmblock).o
ar s libla.a
#
$(basis).o: $(basis).c
$(CC) $(CFlags) $(basis).c
#
$(fgauss).o: $(fgauss).c
$(CC) $(CFlags) $(fgauss).c
#
$(vmblock).o: $(vmblock).c
$(CC) $(CFlags) $(vmblock).c
#
22
Seine Kurzform ohne Aliasnamen und Verzeichnisbezug ist
# makefile_kurz
#
CC = gcc
CFlags = -g -c
#
#Dir = export/home/neundorf/tech_phy/05/make2/
#
tgauss: tgauss.o libla.a
$(CC) -g -o tgauss tgauss.o -lm -lla -L./
#
tgauss.o: tgauss.c
$(CC) $(CFlags) tgauss.c
#
libla.a: basis.o fgauss.o vmblock.o
ar r libla.a basis.o fgauss.o vmblock.o
ar s libla.a
#
basis.o: basis.c
$(CC) $(CFlags) basis.c
#
fgauss.o: fgauss.c
$(CC) $(CFlags) fgauss.c
#
vmblock.o: vmblock.c
$(CC) $(CFlags) vmblock.c
#
Beispiel 3
Unter analogen Gesichtspunkten wie in Beispiel 2 verfährt man beim Programm tnewton.c
zum Newton-Verfahren. Wir notieren wieder die beiden Formen des Makefiles.
# makefile
#
CC = gcc
CFlags = -g -c
#
Dir = export/home/neundorf/tech_phy/05/make3/
# Dir = /home/Studenten/neundorf/make2/
# Dir = /home/Studenten/Austausch/
#
basis = basis
fnewton = fnewton
tfunc1 = tfunc1
#
tnewton: tnewton.o libla.a
$(CC) -g -o tnewton tnewton.o -lm -lla -L./
#
tnewton.o: tnewton.c
$(CC) $(CFlags) tnewton.c
#
libla.a: $(basis).o $(fnewton).o $(tfunc1).o
# Quellen aus dem Verzeichnis Dir holen.
# Anders, falls diese im aktuellen Verzeichnis sind.
# cp $(Dir)$(basis.h) .
# cp $(Dir)$(u_proto.h) .
# cp $(Dir)$(tfunc1.h) .
ar r libla.a $(basis).o $(fnewton).o $(tfunc1).o
ar s libla.a
#
$(basis).o: $(basis).c
23
$(CC) $(CFlags) $(basis).c
#
$(fnewton).o: $(fnewton).c
$(CC) $(CFlags) $(fnewton).c
#
$(tfunc1).o: $(tfunc1).c
$(CC) $(CFlags) $(tfunc1).c
#
------------------------------------------------------------------
# makefile_kurz
#
CC = gcc
CFlags = -g -c
#
#Dir = export/home/neundorf/tech_phy/05/make3/
#
tnewton: tnewton.o libla.a
$(CC) -g -o tnewton tnewton.o -lm -lla -L./
#
tnewton.o: tnewton.c
$(CC) $(CFlags) tnewton.c
#
libla.a: basis.o fnewton.o tfunc1.o
ar r libla.a basis.o fnewton.o tfunc1.o
ar s libla.a
#
basis.o: basis.c
$(CC) $(CFlags) basis.c
#
fnewton.o: fnewton.c
$(CC) $(CFlags) fnewton.c
#
tfunc1.o: tfunc1.c
$(CC) $(CFlags) tfunc1.c
#
Beispiel 4
Für das Demoprogramm meinprog.c mit der Funktion gauss4c.c zum Gauß-Algorithmus
und zahlreichen Quelltexten hat man folgendes ursprüngliche Makefile.
Version 1
# makefile
#
CC = gcc
CFlags = -g -c
#DFlags = -O -c
#
# fuer Physik ("roadrunner")
#Austausch = /home/Studenten/neundorf/austausch/
#Austausch = /home/Studenten/Austausch/
24
meinprog.o: meinprog.c
$(CC) $(CFlags) meinprog.c
#
libla.a: $(la).o $(IO).o $(Add).o $(Eins).o $(Null).o $(Mult).o \
$(ElMu).o $(KrPr).o $(SkPr).o $(SkMu).o $(VerSp).o \
$(VerZe).o
# Quellen aus dem Verzeichnis Austausch holen.
# Anders, falls diese im aktuellen Verzeichnis sind
cp $(Austausch)$(la).h .
ar r libla.a $(la).o $(IO).o $(Add).o $(Eins).o $(Null).o $(Mult).o \
$(ElMu).o $(KrPr).o $(SkPr).o $(SkMu).o $(VerSp).o \
$(VerZe).o
ar s libla.a
#
$(la).o: $(la).c
$(CC) $(CFlags) $(la).c
$(la).c: $(Austausch)$(la).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(la).c .
#
$(IO).o: $(IO).c
$(CC) $(CFlags) $(IO).c
$(IO).c: $(Austausch)$(IO).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(IO).c .
#
$(Add).o: $(Add).c
$(CC) $(CFlags) $(Add).c
$(Add).c: $(Austausch)$(Add).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(Add).c .
#
$(Eins).o: $(Eins).c
$(CC) $(CFlags) $(Eins).c
$(Eins).c: $(Austausch)$(Eins).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(Eins).c .
#
$(Null).o: $(Null).c
$(CC) $(CFlags) $(Null).c
$(Null).c: $(Austausch)$(Null).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(Null).c .
#
$(Mult).o: $(Mult).c
$(CC) $(CFlags) $(Mult).c
$(Mult).c: $(Austausch)$(Mult).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(Mult).c .
#
$(ElMu).o: $(ElMu).c
$(CC) $(CFlags) $(ElMu).c
$(ElMu).c: $(Austausch)$(ElMu).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(ElMu).c .
#
$(KrPr).o: $(KrPr).c
$(CC) $(CFlags) $(KrPr).c
$(KrPr).c: $(Austausch)$(KrPr).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(KrPr).c .
#
$(SkPr).o: $(SkPr).c
$(CC) $(CFlags) $(SkPr).c
$(SkPr).c: $(Austausch)$(SkPr).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(SkPr).c .
#
$(SkMu).o: $(SkMu).c
$(CC) $(CFlags) $(SkMu).c
$(SkMu).c: $(Austausch)$(SkMu).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(SkMu).c .
25
#
$(VerSp).o: $(VerSp).c
$(CC) $(CFlags) $(VerSp).c
$(VerSp).c: $(Austausch)$(VerSp).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(VerSp).c .
#
$(VerZe).o: $(VerZe).c
$(CC) $(CFlags) $(VerZe).c
$(VerZe).c: $(Austausch)$(VerZe).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(VerZe).c .
CFlags = -g -c
#
la = la
IO = laInOut
Add = laAdd
Eins = laEins
Null = laNull
Mult = laMult
ElMu = laElemMult
Kop = laKopiere
KrPr = laKreuzProd
SkPr = laSkalProd
SkMu = laSkMult
VerSp = laVertauscheSp
VerZe = laVertauscheZe
#
meinprog: meinprog.o libla.a
$(CC) -g -o meinprog meinprog.o -lm -lla -L./
#
meinprog.o: meinprog.c
$(CC) $(CFlags) meinprog.c
#
libla.a: $(la).o $(IO).o $(Add).o $(Eins).o $(Null).o $(Mult).o \
$(ElMu).o $(Kop).o $(KrPr).o $(SkPr).o $(SkMu).o $(VerSp).o \
$(VerZe).o
ar r libla.a $(la).o $(IO).o $(Add).o $(Eins).o $(Null).o $(Mult).o \
$(ElMu).o $(Kop).o $(KrPr).o $(SkPr).o $(SkMu).o $(VerSp).o \
$(VerZe).o
26
ar s libla.a
#
$(la).o: $(la).c
$(CC) $(CFlags) $(la).c
#
$(IO).o: $(IO).c
$(CC) $(CFlags) $(IO).c
#
$(Add).o: $(Add).c
$(CC) $(CFlags) $(Add).c
#
$(Eins).o: $(Eins).c
$(CC) $(CFlags) $(Eins).c
#
$(Null).o: $(Null).c
$(CC) $(CFlags) $(Null).c
#
$(Mult).o: $(Mult).c
$(CC) $(CFlags) $(Mult).c
#
$(ElMu).o: $(ElMu).c
$(CC) $(CFlags) $(ElMu).c
#
$(Kop).o: $(Kop).c
$(CC) $(CFlags) $(Kop).c
#
$(KrPr).o: $(KrPr).c
$(CC) $(CFlags) $(KrPr).c
#
$(SkPr).o: $(SkPr).c
$(CC) $(CFlags) $(SkPr).c
#
$(SkMu).o: $(SkMu).c
$(CC) $(CFlags) $(SkMu).c
#
$(VerSp).o: $(VerSp).c
$(CC) $(CFlags) $(VerSp).c
#
$(VerZe).o: $(VerZe).c
$(CC) $(CFlags) $(VerZe).c
05/austausch> meinprog
A | b
1.000000 -2.000000 2.000000 1.000000
-1.000000 1.000000 -1.000000 -1.000000
-2.000000 -2.000000 1.000000 -3.000000
-----------------------------------------------------------------------------
27
Loesungsvektor x
1.000000 1.000000 1.000000
-----------------------------------------------------------------------------
Ergebnisprotokoll (j/n)? j
-----------------------------------------------------------------------------
Dimension A(n,m): n=3, m=3
A | b
1.000000 -2.000000 2.000000 1.000000
-1.000000 1.000000 -1.000000 -1.000000
-2.000000 -2.000000 1.000000 -3.000000
Loesungsvektor x
1.000000 1.000000 1.000000
Permutationsvektor perm
3 1 2
Zerlegung PA=L\U
-2.000000 -2.000000 1.000000
-0.500000 -3.000000 2.500000
0.500000 -0.666667 0.166667
-----------------------------------------------------------------------------
Version 2
Im Vergleich zu Version 1 gibt es zusätzlich die Quellen
laKopiere_, laKopiere1_, laNorm_.
# makefile
#
CC = gcc
CFlags = -g -c
#
Austausch = export/home/neundorf/tech_phy/05/make4b/
# Austausch = /home/Studenten/neundorf/make4a/
# Austausch = /home/Studenten/Austausch/
#
la = la_
IO = laInOut_
Add = laAdd_
Eins = laEins_
Null = laNull_
Mult = laMult_
ElMu = laElemMult_
KrPr = laKreuzProd_
SkPr = laSkalProd_
SkMu = laSkMult_
VerSp = laVertauscheSp_
VerZe = laVertauscheZe_
Kop = laKopiere_
Kop1 = laKopiere1_
Norm = laNorm_
#
meinprog: meinprog_.o libla.a
$(CC) -g -o meinprog_ meinprog_.o -lm -lla -L./
#
meinprog_.o: meinprog_.c
$(CC) $(CFlags) meinprog_.c
28
libla.a: $(la).o $(IO).o $(Add).o $(Eins).o $(Null).o $(Mult).o \
$(ElMu).o $(KrPr).o $(SkPr).o $(SkMu).o $(VerSp).o \
$(VerZe).o $(Kop).o $(Kop1).o $(Norm).o
# Quellen aus dem Verzeichnis Austausch holen.
# Anders, falls diese im aktuellen Verzeichnis sind.
# cp $(Austausch)la.h .
ar r libla.a $(la).o $(IO).o $(Add).o $(Eins).o $(Null).o $(Mult).o \
$(ElMu).o $(KrPr).o $(SkPr).o $(SkMu).o $(VerSp).o \
$(VerZe).o $(Kop).o $(Kop1).o $(Norm).o
ar s libla.a
#
$(la).o: $(la).c
$(CC) $(CFlags) $(la).c
$(la).c: $(Austausch)$(la).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(la).c .
#
$(IO).o: $(IO).c
$(CC) $(CFlags) $(IO).c
$(IO).c: $(Austausch)$(IO).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(IO).c .
#
$(Add).o: $(Add).c
$(CC) $(CFlags) $(Add).c
$(Add).c: $(Austausch)$(Add).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(Add).c .
#
$(Eins).o: $(Eins).c
...
#
$(Null).o: $(Null).c
...
#
$(Mult).o: $(Mult).c
...
#
$(ElMu).o: $(ElMu).c
...
#
$(KrPr).o: $(KrPr).c
...
#
$(SkPr).o: $(SkPr).c
...
#
$(SkMu).o: $(SkMu).c
...
#
$(VerSp).o: $(VerSp).c
...
#
$(VerZe).o: $(VerZe).c
...
#
$(Kop).o: $(Kop).c
$(CC) $(CFlags) $(Kop).c
$(Kop).c: $(Austausch)$(Kop).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(Kop).c .
#
$(Kop1).o: $(Kop1).c
$(CC) $(CFlags) $(Kop1).c
$(Kop1).c: $(Austausch)$(Kop1).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(Kop1).c .
#
$(Norm).o: $(Norm).c
$(CC) $(CFlags) $(Norm).c
$(Norm).c: $(Austausch)$(Norm).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(Norm).c .
29
Im Vergleich zu meinprog sind hier die Dateiarbeit flexibel gehandhabt, die Ausgabeformate
besser angepasst sowie Kontrollrechnungen ergänzt worden.
05/make4b> meinprog_
A | b
1.000000 -2.000000 2.000000 | 1.000000
-1.000000 1.000000 -1.000000 | -1.000000
-2.000000 -2.000000 1.000000 | -3.000000
-----------------------------------------------------------------------------
Loesungsvektor x
1.000000 1.000000 1.000000
-----------------------------------------------------------------------------
Ergebnisprotokoll (j/n)? j
-----------------------------------------------------------------------------
Dimension A(n,m): n=3, m=3
A | b
1.000000 -2.000000 2.000000 | 1.000000
-1.000000 1.000000 -1.000000 | -1.000000
-2.000000 -2.000000 1.000000 | -3.000000
Loesungsvektor x
1.000000 1.000000 1.000000
Permutationsvektor perm
3 1 2
Zerlegung PA=L\U
-2.000000 -2.000000 1.000000
-0.500000 -3.000000 2.500000
0.500000 -0.666667 0.166667
-----------------------------------------------------------------------------
Kontrollrechnungen (j/n)? j
C1 = LU mittels laKopiere_
-2.000000 -2.000000 1.000000
-0.500000 -3.000000 2.500000
0.500000 -0.666667 0.166667
30
C2 = LU mittels laKopiere1_
-2.000000 -2.000000 1.000000
-0.500000 -3.000000 2.500000
0.500000 -0.666667 0.166667
C3 = A+C2
-1.000000 -4.000000 3.000000
-1.500000 -2.000000 1.500000
-1.500000 -2.666667 1.166667
Normen von b
1.000000 -1.000000 -3.000000
||b||_u= 3.000000, ||b||_1= 5.000000, ||b||_2= 3.316625
Normen von A
1.000000 -2.000000 2.000000
-1.000000 1.000000 -1.000000
-2.000000 -2.000000 1.000000
||A||_u= 5.000000, ||A||_1= 5.000000, ||A||_F= 4.582576
Auf den Test von Versionen in C++ verzichten wir an dieser Stelle.
Beispiel 5
Wir betrachten nun das Demoprogramm meinprog .c zum Algorithmus der Vektoriteration
und inversen Vektoriteration.
Die neuen Funktionen des Projekts sind im Rahmenprogramm enthalten, während die an-
deren Projektkomponenten vom Gauß-Algorithmus stammen.
Die Lang- und Kurzversionen des Makefiles sind wie folgt.
# makefile
#
CC = gcc
CFlags = -g -c
#
Austausch = /export/home/neundorf/tech_phy/05/make5/
#Austausch = /home/Studenten/neundorf/make5/
#Austausch = /home/Studenten/Austausch/
#
la = la_
IO = laInOut_
Add = laAdd_
Eins = laEins_
Null = laNull_
Mult = laMult_
ElMu = laElemMult_
KrPr = laKreuzProd_
SkPr = laSkalProd_
SkMu = laSkMult_
VerSp = laVertauscheSp_
VerZe = laVertauscheZe_
Kop = laKopiere_
Kop1 = laKopiere1_
Norm = laNorm_
#
meinprog_: meinprog_.o libla.a
$(CC) -g -o meinprog_ meinprog_.o -lm -lla -L./
#
meinprog_.o: meinprog_.c
$(CC) $(CFlags) meinprog_.c
31
#
libla.a: $(la).o $(IO).o $(Add).o $(Eins).o $(Null).o $(Mult).o \
$(ElMu).o $(KrPr).o $(SkPr).o $(SkMu).o $(VerSp).o \
$(VerZe).o $(Kop).o $(Kop1).o $(Norm).o
# Quellen aus dem Verzeichnis Austausch holen.
# Anders, falls diese im aktuellen Verzeichnis sind.
# cp $(Austausch)$(la).h .
ar r libla.a $(la).o $(IO).o $(Add).o $(Eins).o $(Null).o $(Mult).o \
$(ElMu).o $(KrPr).o $(SkPr).o $(SkMu).o $(VerSp).o \
$(VerZe).o $(Kop).o $(Kop1).o $(Norm).o
ar s libla.a
#
$(la).o: $(la).c
$(CC) $(CFlags) $(la).c
$(la).c: $(Austausch)$(la).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(la).c .
#
$(IO).o: $(IO).c
$(CC) $(CFlags) $(IO).c
$(IO).c: $(Austausch)$(IO).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(IO).c .
#
$(Add).o: $(Add).c
...
#
$(Eins).o: $(Eins).c
...
#
$(Null).o: $(Null).c
...
#
$(Mult).o: $(Mult).c
...
#
$(ElMu).o: $(ElMu).c
...
#
$(KrPr).o: $(KrPr).c
...
#
$(SkPr).o: $(SkPr).c
...
#
$(SkMu).o: $(SkMu).c
...
#
$(VerSp).o: $(VerSp).c
...
#
$(VerZe).o: $(VerZe).c
...
#
$(Kop).o: $(Kop).c
...
#
$(Kop1).o: $(Kop1).c
...
#
$(Norm).o: $(Norm).c
$(CC) $(CFlags) $(Norm).c
$(Norm).c: $(Austausch)$(Norm).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(Norm).c .
---------------------------------------------------------------------------------------
# makefile_kurz
#
CC = gcc
CFlags = -g -c
#
32
la = la_
IO = laInOut_
Add = laAdd_
Eins = laEins_
Null = laNull_
Mult = laMult_
ElMu = laElemMult_
KrPr = laKreuzProd_
SkPr = laSkalProd_
SkMu = laSkMult_
VerSp = laVertauscheSp_
VerZe = laVertauscheZe_
Kop = laKopiere_
Kop1 = laKopiere1_
Norm = laNorm_
#
meinprog_: meinprog_.o libla.a
$(CC) -g -o meinprog_ meinprog_.o -lm -lla -L./
#
meinprog_.o: meinprog_.c
$(CC) $(CFlags) meinprog_.c
#
libla.a: $(la).o $(IO).o $(Add).o $(Eins).o $(Null).o $(Mult).o \
$(ElMu).o $(KrPr).o $(SkPr).o $(SkMu).o $(VerSp).o \
$(VerZe).o $(Kop).o $(Kop1).o $(Norm).o
ar r libla.a $(la).o $(IO).o $(Add).o $(Eins).o $(Null).o $(Mult).o \
$(ElMu).o $(KrPr).o $(SkPr).o $(SkMu).o $(VerSp).o \
$(VerZe).o $(Kop).o $(Kop1).o $(Norm).o
ar s libla.a
#
$(la).o: $(la).c
$(CC) $(CFlags) $(la).c
#
$(IO).o: $(IO).c
$(CC) $(CFlags) $(IO).c
#
$(Add).o: $(Add).c
$(CC) $(CFlags) $(Add).c
#
$(Eins).o: $(Eins).c
$(CC) $(CFlags) $(Eins).c
#
$(Null).o: $(Null).c
$(CC) $(CFlags) $(Null).c
#
$(Mult).o: $(Mult).c
$(CC) $(CFlags) $(Mult).c
#
$(ElMu).o: $(ElMu).c
$(CC) $(CFlags) $(ElMu).c
#
$(KrPr).o: $(KrPr).c
$(CC) $(CFlags) $(KrPr).c
#
$(SkPr).o: $(SkPr).c
$(CC) $(CFlags) $(SkPr).c
#
$(SkMu).o: $(SkMu).c
$(CC) $(CFlags) $(SkMu).c
#
$(VerSp).o: $(VerSp).c
$(CC) $(CFlags) $(VerSp).c
#
$(VerZe).o: $(VerZe).c
$(CC) $(CFlags) $(VerZe).c
#
$(Kop).o: $(Kop).c
$(CC) $(CFlags) $(Kop).c
#
$(Kop1).o: $(Kop1).c
$(CC) $(CFlags) $(Kop1).c
#
$(Norm).o: $(Norm).c
$(CC) $(CFlags) $(Norm).c
33
In meinprog_ sind hier die Dateiarbeit flexibel gehandhabt und sowohl Vektoriteration als
auch inverse Vektoriteration ausgeführt.
05/make5> meinprog_
Vektoriteration
Betragsgroesster Eigenwert la = 1.0002000600739880e+00
Zugehoeriger skalierter Eigenvektor x
-0.577408 0.577350 0.577293
Iterationsanzahl iter = 10000
-------------------------------------------------------------------------------
Inverse Vektoriteration
Betragskleinster Eigenwert la = 9.9980003788891614e-01
Zugehoeriger skalierter Eigenvektor x
-0.577293 0.577350 0.577408
Iterationsanzahl iter = 10000
-------------------------------------------------------------------------------
34