示例#1
0
void main()  {
  
  printf("\n Input data file name: "); scanf("%s", filename);
  fp = fopen(filename, "r");

  //read size of linear system
  fscanf(fp,"%d", &m);
  fscanf(fp,"%d", &n);

//allocate memory
  vmblock = vminit();
  A  = (REAL **) vmalloc(vmblock, MATRIX, m+1, n+1);
  U  = (REAL **) vmalloc(vmblock, MATRIX, m+1, n+1);
  V  = (REAL **) vmalloc(vmblock, MATRIX, n+1, n+1);
  B  = (REAL *)  vmalloc(vmblock, VEKTOR, m+1, 0);
  W  = (REAL *)  vmalloc(vmblock, VEKTOR, n+1, 0);
  X  = (REAL *)  vmalloc(vmblock, VEKTOR, n+1, 0);

// read matrix A
  for (i=1; i<=m; i++)
    for (j=1; j<=n; j++)
      fscanf(fp,"%lf", &A[i][j]);
// read vector B
  for (i=1; i<=m; i++)
    fscanf(fp,"%lf", &B[i]);
  fclose(fp);
  
  fp = fopen("tsvbksb.lst", "w");
  fprintf(fp,"\n  M = %d\n", m);
  fprintf(fp,"  N = %d\n", n);
  WriteMat("  Matrix A:",A,m,n);
  WriteVec("  Vector B:",B,m);
// Save A in U
  for (i=1; i<=m; i++)
    for (j=1; j<=n; j++)
      U[i][j]=A[i][j];
//call singular value decomposition subroutine
  SVDCMP(U,m,n,W,V);
  WriteMat("  Matrix U:",U,m,n);
  WriteVec("  Vector W:",W,n);
  WriteMat("  Matrix V:",V,m,n);
//seek highest value of W's and set near-zero
//values to exactly zero (for near-singular cases)
  WMAX=0.0;
  for (j=1; j<=n; j++)
    if (W[j] > WMAX)  WMAX=W[j];
  WMIN=WMAX*1e-6;
  for (j=1; j<=n; j++)
    if (W[j] < WMIN)  W[j]=0.0;
//call solver for SVD matrix
  SVBKSB(U,W,V,m,n,B,X);
//print solution
  WriteVec("  Solution:",X,n);
// free memory  
  vmfree(vmblock);
  fclose(fp);
  printf("\n Results in file tsvbksb.lst.\n\n");

}
示例#2
0
/*.BE*/
int spline                                        /* nichtparametrischer kubischer Polynomspline .......*/
/*.BA*/
/*.IX{spline}*/
/*.BE*/
(
int  m,                                           /* Anzahl der Stuetzstellen ............*/
REAL x[],                                         /* Stuetzstellen .......................*/
REAL y[],                                         /* Stuetzwerte .........................*/
int  marg_cond,                                   /* Art der Randbedingung ...............*/
REAL marg_0,                                      /* linke Randbedingung .................*/
REAL marg_n,                                      /* rechte Randbedingung ................*/
int  save,                                        /* dynamische Hilfsfelder sichern? .....*/
REAL b[],                                         /* Splinekoeffizienten von (x-x[i]) ....*/
REAL c[],                                         /* Splinekoeffizienten von (x-x[i])^2 ..*/
REAL d[]                                          /* Splinekoeffizienten von (x-x[i])^3 ..*/
)                                                 /* Fehlercode ..........................*/
/*.BA*/

/***********************************************************************
 * zu den vorgegebenen Wertepaaren                                      *
 *                  (x[i], y[i]), i = 0(1)m-1                           *
 * die Koeffizienten eines nichtparametrischen interpolierenden         *
 * kubischen Polynomplines berechnen.                                   *
.BE*)
* Die Art der Randbedingung wird durch den Parameter marg_cond         *
* festgelegt. Die x[i] muessen streng monoton wachsen.                 *
* Bei wiederholten Aufrufen mit gleichen Stuetzstellen, aber verschie- *
* denen Stuetzwerten besteht die Moeglichkeit, die erneute Aufstellung *
* und Zerlegung der Matrix des Gleichungssystems zu vermeiden, indem   *
* man den Parameter save von Null verschieden waehlt und so die Be-    *
* schreibung der Zerlegungsmatrizen fuer den naechsten Aufruf rettet.  *
* Wichtig: Damit der Speicher fuer die Hilfsfelder wieder frei wird    *
* -------- und bei weiteren Aufrufen nicht mit falschen Zerlegungs-    *
*          matrizen gearbeitet wird, muss der letzte Aufruf einer      *
 *          zusammengehoerigen Aufruffolge mit save = 0 statt mit       *
 *          save = 1 ausgefuehrt werden!                                *
 *                                                                      *
 * Eingabeparameter:                                                    *
 * =================                                                    *
 * m:          Anzahl der Stuetzstellen (mindestens 3)                  *
 * x:          [0..m-1]-Vektor mit den x-Koordinaten der Wertepaare     *
 *             (wird nicht benoetigt, falls der vorige Aufruf mit       *
 *              save != 0 stattfand)                                    *
 * y:          [0..m-1]-Vektor mit den y-Koordinaten der Wertepaare     *
 * marg_cond:  = 0: not-a-knot-Bedingung (=> marg_0, marg_n ohne        *
 *                                           Bedeutung)                 *
 *             = 1: marg_0, marg_n sind 1. Ableitungen.                 *
 *             = 2: marg_0, marg_n sind 2. Ableitungen.                 *
 *                  (Fuer marg_0 = marg_n = 0 erhaelt man einen         *
 *                  natuerlichen Spline.)                               *
 *             = 3: marg_0, marg_n sind 3. Ableitungen.                 *
 *             = 4: periodischer Spline (=> marg_0, marg_n ohne         *
 *                                          Bedeutung)                  *
 * marg_0:     Randbedingung in x[0]                                    *
 * marg_n:     Randbedingung in x[m-1]                                  *
 * save:       Flagge, die anzeigt, ob der Speicher fuer die Hilfsfel-  *
 *             der mit den Zerlegungsmatrizen fuer den naechsten Aufruf *
 *             aufbewahrt werden soll. Im Normalfall ist save = 0 zu    *
 *             setzen. Wenn man mehrere Splinefunktionen mit denselben  *
 *             Stuetzstellen x[i], aber anderen y[i] berechnen will     *
 *             (z. B. bei parametrischen Splines), kann man ab dem      *
 *             zweiten Aufruf Rechenzeit sparen, indem man beim ersten  *
 *             Aufruf save = 1 setzt. Dann wird naemlich die neuerliche *
 *             Aufstellung und Zerlegung der Tridiagonalmatrix umgangen *
 *             (=> ca. 4*m Punktoperationen weniger).                   *
 *             Im letzten Aufruf muss man save = 0 waehlen, damit der   *
 *             von den Hilfsfeldern beanspruchte dynamische Speicher    *
 *             fuer andere Programmteile wieder verfuegbar wird.        *
 *                                                                      *
 * Ausgabeparameter:                                                    *
 * =================                                                    *
 * b: \  [0..m-2]-Vektoren mit den Splinekoeffizienten nach dem Ansatz  *
 * c:  >     s(x)  =  a[i] + b[i] * (x - x[i]) + c[i] * (x - x[i]) ^ 2  *
 * d: /                    + d[i] * (x - x[i]) ^ 3.                     *
 *       a entspricht y,                                                *
 *       c hat (wie a) noch ein zusaetzliches Element c[m-1].           *
 *                                                                      *
 * Funktionswert:                                                       *
 * ==============                                                       *
 * =  0: kein Fehler                                                    *
 * = -i: Monotoniefehler: x[i-1] >= x[i]                                *
 * =  1: falscher Wert fuer marg_cond                                   *
 * =  2: m < 3                                                          *
 * =  3: nicht genuegend Heapspeicher fuer die Hilfsfelder              *
 * =  4: marg_cond = 4: Eingabedaten nichtperiodisch                    *
 * >  4: Fehler in trdiag() oder tzdiag()                               *
 * Im Fehlerfall sind die Werte der Ausgabeparameter unbestimmt, und    *
 * der Speicher fuer die Hilfsfelder wird freigegeben.                  *
 *                                                                      *
 * benutzte globale Namen:                                              *
 * =======================                                              *
 * REAL, vminit, vmalloc, vmcomplete, vmfree, VEKTOR, trdiag, tzdiag,   *
 * NULL, ZERO, THREE, HALF, TWO                                         *
.BA*)
***********************************************************************/
/*.BE*/

{

#define ciao(fehler)          /* dafuer sorgen, dass vor dem Beenden */\
{ \
/* von spline() aufgeraeumt wird       */\
vmfree(vmblock); /* Speicherplatz fuer die Hilfsfelder freigeben */\
vmblock = NULL;  /* und dies auch anzeigen                       */\
return fehler;   /* den Fehlercode an den Aufrufer weiterreichen */\
}

   static
      void *vmblock = NULL;                       /* Liste der dynamisch vereinbarten Vek- */
   /* toren. Der Wert NULL zeigt an, dass   */
   /* noch keine Hilfsvektoren aus eventu-  */
   /* ellen frueheren Aufrufen existieren,  */
   /* dass dies also der erste Aufruf einer */
   /* zusammengehoerenden Folge mit glei-   */
   /* chen Stuetzstellen ist.               */
   static
      REAL *h,                                    /* [0..m-2]-Vektor mit den Laengen der Stuetz-   */
   /* stellenintervalle                             */
      *lower,                                     /* [0..m-2]-Vektor mit der unteren Nebendiago-   */
   /* nale der Matrix, spaeter Zerlegungsmatrix     */
   /* von trdiag() bzw. tzdiag()                    */
      *diag,                                      /* [0..m-2]-Vektor mit der Hauptdiagonale der    */
   /* Matrix, spaeter Zerlegungsmatrix von          */
   /* trdiag() bzw. tzdiag()                        */
      *upper,                                     /* [0..m-2]-Vektor mit der oberen Nebendiago-    */
   /* nale der Matrix, spaeter Zerlegungsmatrix     */
   /* von trdiag() bzw. tzdiag()                    */
      *lowrow,                                    /* [0..m-4]-Vektor mit der unteren Zeile der     */
   /* Matrix, spaeter Zerlegungsmatrix von tzdiag() */
      *ricol;                                     /* [0..m-4]-Vektor mit der rechten Spalte der    */
   /* Matrix, spaeter Zerlegungsmatrix von tzdiag() */
   int  n,                                        /* m - 1, Index der letzten Stuetzstelle */
      fehler,                                     /* Fehlercode von trdiag() bzw. tzdiag() */
      i,                                          /* Laufvariable                          */
      erster_aufruf;                              /* Flagge, die anzeigt, dass gerade der  */
   /* erste Aufruf einer Folge stattfindet  */

   n = m - 1;

   if (n < 2)                                     /* zu kleinen Wert fuer n abfangen */
      ciao(2);

   if (marg_cond < 0 || marg_cond > 4)            /* falsches marg_cond abfangen */
      ciao(1);

   if (marg_cond == 4)                            /* periodischer Spline?       */
      if (y[n] != y[0])                           /* Periodizitaet ueberpruefen */
         ciao(4);

   /* 1. Aufruf: Speicher fuer die Hilfsfelder anfordern: 4 [0..n-1]-  */
   /* Vektoren (im periodischen Fall noch 2 [0..n-3]-Vektoren)         */

   if (vmblock == NULL)                           /* erster Aufruf einer Folge? */
   {
      erster_aufruf = 1;
#define MYALLOC(l)  (REAL *)vmalloc(vmblock, VEKTOR, (l), 0)
      vmblock = vminit();                         /* Speicherblock initialisieren */
      h     = MYALLOC(n);                         /* Speicher fuer die       */
      lower = MYALLOC(n);                         /* Hilfsvektoren anfordern */
      diag  = MYALLOC(n);
      upper = MYALLOC(n);
      if (marg_cond == 4)                         /* periodischer Spline mit  */
         if (n > 2)                               /* genuegend Stuetzstellen? */
            lowrow = MYALLOC(n - 2),              /* auch die zusaetzlichen   */
               ricol  = MYALLOC(n - 2);           /* Vektoren versorgen       */
#undef MYALLOC
   }
   else
      erster_aufruf = 0;
   if (! vmcomplete(vmblock))                     /* Ging eine der Speicheranforderungen */
      ciao(3);                                    /* fuer den Block schief?              */

   if (erster_aufruf)
      for (i = 0; i < n; i++)                     /* Schrittweiten berechnen und dabei die */
   {                                              /* Stuetzstellen auf Monotonie pruefen   */
      h[i] = x[i + 1] - x[i];                     /* Schrittweiten berechnen */
      if (h[i] <= ZERO)                           /* Stuetzstellen nicht monoton wachsend? */
         ciao(-(i + 1));
   }

   for (i = 0; i < n - 1; i++)                    /* das Gleichungssystem aufstellen */
   {
                                                  /* rechte Seite */
      c[i] = THREE * ((y[i + 2] - y[i + 1]) / h[i + 1]
         - (y[i + 1] - y[i])     / h[i]);
      if (erster_aufruf)
         diag[i] = TWO * (h[i] + h[i + 1]),       /* Hauptdiagonale   */
            lower[i + 1] = upper[i] = h[i + 1];   /* untere und obere */
   }                                              /* Nebendiagonale   */

   switch (marg_cond)                             /* je nach Randbedingung einige Koeffizienten */
   {                                              /* des Gleichungssystems korrigieren          */
      case 0:                                     /* not-a-knot-Bedingung?              */
         if (n == 2)                              /* nur drei Stuetzstellen?      */
         {                                        /* Da in diesem Fall das Gleichungssystem  */
            /* unterbestimmt ist, wird nur ein Polynom */
            /* 2. Grades berechnet.                    */
            c[0] /= THREE;                        /* rechte Seite    */
            if (erster_aufruf)
               diag[0] *= HALF;                   /* auch die Matrix */
         }
         else                                     /* mehr als drei Stuetzstellen? */
         {
                                                  /* rechte */
            c[0]     *= h[1]     / (h[0]     + h[1]);
                                                  /* Seite  */
            c[n - 2] *= h[n - 2] / (h[n - 1] + h[n - 2]);
            if (erster_aufruf)
               diag[0]      -= h[0],              /* auch die */
                  diag[n - 2]  -= h[n - 1],       /* Matrix   */
                  upper[0]     -= h[0],
                  lower[n - 2] -= h[n - 1];
         }
         break;

      case 1:                                     /* erste Randableitungen vorgegeben?  */
         c[0]     -= (REAL)1.5 * ((y[1] - y[0]) / h[0] - marg_0);
         c[n - 2] -= (REAL)1.5 * (marg_n - (y[n] - y[n - 1]) / h[n - 1]);
         if (erster_aufruf)
            diag[0]     -= HALF * h[0],           /* auch die Matrix */
               diag[n - 2] -= HALF * h[n - 1];    /* vorbesetzen     */
         break;

      case 2:                                     /* zweite Randableitungen vorgegeben? */
         c[0]     -= h[0]     * HALF * marg_0;
         c[n - 2] -= h[n - 1] * HALF * marg_n;
         break;

      case 3:                                     /* dritte Randableitungen vorgegeben? */
         c[0]        += HALF * marg_0 * h[0]     * h[0];
         c[n - 2]    -= HALF * marg_n * h[n - 1] * h[n - 1];
         if (erster_aufruf)
            diag[0]     += h[0],                  /* auch die Matrix */
               diag[n - 2] += h[n - 1];           /* vorbesetzen     */
         break;

      case 4:                                     /* periodischer Spline?               */
         c[n - 1] = THREE * ((y[1] - y[0])     / h[0] -
            (y[n] - y[n - 1]) / h[n - 1]);
         if (erster_aufruf)
            if (n > 2)
               diag[n - 1]  = TWO * (h[0] + h[n - 1]),
                  ricol[0] = lowrow[0] = h[0];
   }

   switch (n)                                     /* das Gleichungssystem loesen und damit  */
   {                                              /* die Splinekoeffizienten c[i] berechnen */
      case 2:                                     /* nur drei Stuetzstellen =>    */
         /* => Loesung direkt berechnen  */
         if (marg_cond == 4)                      /* periodischer Spline?         */
            c[1] = THREE * (y[0] - y[1]) / (x[2] - x[1]) / (x[1] - x[0]),
               c[2] = - c[1];
         else
            c[1] = c[0] / diag[0];
         break;

      default:                                    /* mehr als drei Stuetzstellen? */
         if (marg_cond == 4)                      /* periodischer Spline?         */
            fehler = tzdiag(n, lower, diag, upper, lowrow,
               ricol, c, !erster_aufruf);
         else                                     /* nichtperiodischer Spline? */
            fehler = trdiag(n - 1, lower, diag, upper, c, !erster_aufruf);

         if (fehler != 0)                         /* Fehler in tzdiag() oder in trdiag()? */
            ciao(fehler + 4);
         for (i = n; i != 0; i--)                 /* die Elemente des Loesungsvektors   */
            c[i] = c[i - 1];                      /* eine Position nach rechts schieben */
   }

   switch (marg_cond)                             /* in Abhaengigkeit von der Randbedingung den */
   {                                              /* ersten und letzten Wert von c korrigieren  */
      case 0:                                     /* not-a-knot-Bedingung?              */
         if (n == 2)                              /* nur drei Stuetzstellen?      */
            c[0] = c[2] = c[1];
         else                                     /* mehr als drei Stuetzstellen? */
            c[0] = c[1] + h[0] * (c[1] - c[2]) / h[1],
               c[n] = c[n - 1] + h[n - 1] *
               (c[n - 1] - c[n - 2]) / h[n - 2];
         break;

      case 1:                                     /* erste Randableitungen vorgegeben?  */
         c[0] =  (REAL)1.5 * ((y[1] - y[0]) / h[0] - marg_0);
         c[0] = (c[0] - c[1] * h[0] * HALF) / h[0];
         c[n] = (REAL)-1.5 * ((y[n] - y[n - 1]) / h[n - 1] - marg_n);
         c[n] = (c[n] - c[n - 1] * h[n - 1] * HALF) / h[n - 1];
         break;

      case 2:                                     /* zweite Randableitungen vorgegeben? */
         c[0] = marg_0 * HALF;
         c[n] = marg_n * HALF;
         break;

      case 3:                                     /* dritte Randableitungen vorgegeben? */
         c[0] = c[1]     - marg_0 * HALF * h[0];
         c[n] = c[n - 1] + marg_n * HALF * h[n - 1];
         break;

      case 4:                                     /* periodischer Spline?               */
         c[0] = c[n];

   }

   for (i = 0; i < n; i++)                        /* die restlichen      */
      b[i] = (y[i + 1] - y[i]) / h[i] - h[i] *    /* Splinekoeffizienten */
         (c[i + 1] + TWO * c[i]) / THREE,         /* b[i] und d[i]       */
         d[i] = (c[i + 1] - c[i]) / (THREE * h[i]);/* berechnen           */

   if (!save)                                     /* Hilfsfelder nicht aufbewahren */
      ciao(0);                                    /* (letzter Aufruf einer Folge)? */

   return 0;
#undef ciao
}