home *** CD-ROM | disk | FTP | other *** search
- { --------------------------------------------------------------- }
- { File : SPLINE.PAS (gehört zu WERTE.PAS) }
- { Copyright (c) : 1989 Heinz Hagemeyer & TOOLBOX }
- { Sprache : TURBO PASCAL 4.0 (bzw. 3.0) }
- { Ein Programm zur Auswertung von Meßwerten }
- { mit Hilfe von WERTE.PAS }
- { (entstanden aus einer alten CPM Routine) }
- { --------------------------------------------------------------- }
-
- { Ist die Interpolation mit Hilfe von kubischen Splines möglich }
- { wird TRUE zurückgegeben, sonst FALSE }
-
- FUNCTION Spline_Interpolation (n : Index ;
- VAR x,y : Messwerte ;
- VAR Datei : Text ) : BOOLEAN ;
-
- { a_array : hier werden die Koeffizienten des Linearen Gleichungs- }
- { systems gespeichert. }
- { x_array : hier kommen die Lösungen hinein. }
-
- TYPE a_array = ARRAY [1 .. Spline_Max, 1 .. Spline_Max1] OF REAL;
- x_array = ARRAY [0 .. Spline_Max ] OF REAL;
-
- { ------------------------------------------------------------------------ }
- { Löst ein Lineares Gleichungssystem nach dem Gauß'schen Algorithmus. Da }
- { es stets bei diesem Problem eine eindeutige Lösung gibt, kann auf eine }
- { Abfrage daraufhin verzichtet werden. }
-
- PROCEDURE gauss (n : Index ; VAR x : x_array; VAR a : a_array);
-
- VAR i,j,k,l,m : Index ;
- q : REAL ;
-
- BEGIN
- FOR i := 1 TO pred (n) DO
- BEGIN
- { PIVOT }
- { Suchen des groessten Elementes }
-
- m := i;
- FOR k := Succ (i) TO n DO
- IF Abs (a[k,i]) > Abs (a[m,i]) THEN m := k;
-
- { und Tauschen }
- { IF m <> i THEN (* Diese Abfrage ist Geschmaksache *) }
- FOR j := 1 TO Succ (n) DO
- BEGIN
- q := a[i,j]; a[i,j] := a [m,j]; a [m,j] := q;
- END;
-
- { Elimination }
-
- FOR k := Succ (i) TO n DO
- BEGIN
- q := a [k,i] / a [i,i] ;
- FOR j := Succ (i) TO Succ (n) DO
- a [k,j] := a [k,j] - a [i,j] * q;
- END;
- END;
-
- { Berechnen der Loesungen }
-
- FOR i := n DOWNTO 1 DO
- BEGIN
- q := a[i,succ(n)];
- FOR j := Succ (i) TO n DO q := q - a [i,j] * x [j];
- x [i] := q / a [i,i]
- END;
- END; { Gauss }
-
- { -------------------------------------------------------------------------- }
- { Mit dieser Procedure wird die Matrix zur Lösung des Lin. Gleichungssystems }
- { aus den Meßwerten erzeugt. }
-
- PROCEDURE erzeuge_a (n : Index ; VAR a : a_array; VAR x,y : Messwerte);
-
- VAR hi, hi_1 : REAL;
- i,j : INTEGER;
-
- BEGIN
- FOR i := 1 TO n - 2 DO { Anfangswerte setzen }
- FOR j := 1 TO n - 1 DO a [i,j] := 0;
-
- i := 1; { Berechnung der a [i,k] nach }
- hi := x [i + 2] - x [i + 1 ]; { dem im Begleittext angegebe-}
- hi_1 := x [i + 1] - x [i ]; { nen Algorithmus }
-
- a [i,i] := 2 * (hi_1 + hi);
- a [i,i + 1] := hi;
- a [i,n - 1] := 3 * ( (y [i + 2] - y [i + 1])/hi
- - (y [i + 1] - y [i ])/hi_1 );
-
- FOR i := 2 TO n - 2 DO
- BEGIN
- hi := x [i + 2] - x [i + 1];
- hi_1 := x [i + 1] - x [i ];
-
- a [i,i - 1] := hi_1;
- a [i,i] := 2 * (hi_1 + hi);
- a [i,i + 1] := hi;
- a [i,n - 1] := 3 * ( (y [i + 2] - y [i + 1])/hi
- - (y [i + 1] - y [i ])/hi_1 );
-
- END;
-
- i := n - 2;
-
- hi := x [i + 2] - x [i + 1];
- hi_1 := x [i + 1] - x [i ];
-
- a [i,i - 1] := hi_1;
- a [i, i] := 2 * (hi_1 + hi);
- a [i,n - 1] := 3 * ( (y [i + 2] - y [i + 1])/hi
- - (y [i + 1] - y [i ])/hi_1 );
-
- END; { Erzeuge }
-
- { -------------------------------------------------------------------------- }
- { Berechnet die Koeffizienten des i-ten Polynom fi(x) = a + bx + cx^2 + bx^3 }
-
- PROCEDURE Berechne_Polynom (i : Index ;
- x,y : messwerte ;
- ca : x_array ;
- VAR a,b,c,d : REAL) ;
-
- VAR hi : REAL ;
-
- BEGIN
-
- a := y [i + 1];
- hi := x [i+2] - x [i+1];
- c := ca [i];
- b := (y [i + 2] - a)/hi - hi*( ca [i + 1] + 2* c ) / 3;
- d := (ca [i + 1] - c ) / (3*hi);
-
- END;
-
- { -------------------------------------------------------------------------- }
- { Schreibt die Daten x und y in die von WERTE.PAS auszuwertenden Datei und }
- { zwar von xa bis xe. }
-
- PROCEDURE Spline_Zug (xa,xe,x0,a,b,c,d : REAL ;
- VAR t : Text ) ;
-
- VAR x : REAL;
-
- FUNCTION y (x : Real) : Real; { Berechnet f(x) = a + bx + cx^2 + dx^3 }
- BEGIN { nach dem HORNER - Schema zur Vermeidung }
- { von langsamen Potenzfunktionen. }
-
- y := a + x*(b + x*( c + d*x)) ;
- END;
-
- BEGIN { Spline_Zug }
- x := xa ;
-
- WHILE x < xe DO
- BEGIN
- WriteLn (t,x,' ',y (x - x0) );
- x := x + Step ;
- END;
- WriteLn (t,x,' ',y (x - xa) ) ; { Letzter Zug, nicht vergessen ! }
- END;
-
- { -------------------------------------------------------------------------- }
- { Sotiert nach der Methode der "aufsteigenden Blasen" die Array's x und y. }
- { Ist die langsamste Methode zur Sortierung eines Array's, dafür aber ein- }
- { fach zu programmieren und zu durchschauen. Schnell genug für diesen Zweck. }
- { Überprüft gleichzeitig ob ein x - Wert doppelt ist. Dann kann es sich bei }
- { eingegebenen Daten um keine Funktion handeln. Demnach ist eine Interpola- }
- { lation mittels kubischer Splines nicht möglich. }
-
- FUNCTION bubblesort (n : Index ; VAR x,y : Messwerte) : BOOLEAN;
-
- VAR i : Index ;
- Merker : REAL ;
- Sortiert,
- Gleich : BOOLEAN;
-
- BEGIN
- REPEAT
- Sortiert := TRUE;
- FOR i := 2 TO n DO
- IF x [i] < x [i - 1] THEN
- BEGIN
- Sortiert := FALSE;
- Merker := x [i];
- x [i] := x [i - 1];
- x [i - 1] := Merker;
- Merker := y [i];
- y [i] := y [i - 1];
- y [i - 1] := Merker;
- END;
- UNTIL sortiert;
-
- Gleich := TRUE;
- FOR i := 2 TO n DO Gleich := Gleich AND ( x[i] = x[i - 1] );
- Bubblesort := NOT Gleich;
- END; { bubblesort }
-
- { ------------------------------------------------------------------------ }
-
- VAR cc : ^x_array ; { Als Zeiger definiert. Spart Platz im Memory }
- aa : ^a_array ; { Bei MS DOS nicht unbedingt erforderlich. Bei }
- i : Index ; { CP/M mit 64k Hauptspeicher war's sehr nötig !}
- a,b,c,d : REAL;
-
- BEGIN { Spline_Interpolation }
- IF n > Spline_Max THEN
- BEGIN
- Spline_Interpolation := FALSE;
- EXIT;
- END;
- IF (bubblesort (n,x,y)) AND (n>2) THEN
- BEGIN
- Spline_Interpolation := TRUE;
- New (cc); New (aa);
-
- Erzeuge_a (n,aa^,x,y);
- Gauss (n-2,cc^,aa^);
-
- cc^ [0] := 0;
- cc^ [n - 1] := 0;
-
- FOR i := 0 TO n - 2 DO
- BEGIN
- Berechne_Polynom (i,x,y,cc^,a,b,c,d);
- Spline_Zug (x [i + 1] , x [i + 2], x [i + 1],a,b,c,d,Datei);
- END;
- WriteLn (Datei);
- Dispose (cc);
- Dispose (aa);
- END ELSE Spline_Interpolation := FALSE ;
- END; { Spline_Regression }
- { ------------------------------------------------------------------------- }
- { Ende von SPLINE.PAS }