home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / apps / clib / progs / meschach / !Meschach / c / sparse < prev    next >
Encoding:
Text File  |  1994-03-08  |  23.2 KB  |  1,024 lines

  1. 05:34:35 des Exp $";
  2.  
  3. #include    <stdio.h>
  4. #include    <math.h>
  5. #include    "matrix.h"
  6.  
  7.  
  8. /* _v_norm1 -- computes (scaled) 1-norms of vectors */
  9. double    _v_norm1(x,scale)
  10. VEC    *x, *scale;
  11. {
  12.     int    i, dim;
  13.     Real    s, sum;
  14.  
  15.     if ( x == (VEC *)NULL )
  16.         error(E_NULL,"_v_norm1");
  17.     dim = x->dim;
  18.  
  19.     sum = 0.0;
  20.     if ( scale == (VEC *)NULL )
  21.         for ( i = 0; i < dim; i++ )
  22.             sum += fabs(x->ve[i]);
  23.     else if ( scale->dim < dim )
  24.         error(E_SIZES,"_v_norm1");
  25.     else
  26.         for ( i = 0; i < dim; i++ )
  27.         {    s = scale->ve[i];
  28.             sum += ( s== 0.0 ) ? fabs(x->ve[i]) : fabs(x->ve[i]/s);
  29.         }
  30.  
  31.     return sum;
  32. }
  33.  
  34. /* square -- returns x^2 */
  35. double    square(x)
  36. double    x;
  37. {    return x*x;    }
  38.  
  39. /* cube -- returns x^3 */
  40. double cube(x)
  41. double x;
  42. {  return x*x*x;   }
  43.  
  44. /* _v_norm2 -- computes (scaled) 2-norm (Euclidean norm) of vectors */
  45. double    _v_norm2(x,scale)
  46. VEC    *x, *scale;
  47. {
  48.     int    i, dim;
  49.     Real    s, sum;
  50.  
  51.     if ( x == (VEC *)NULL )
  52.         error(E_NULL,"_v_norm2");
  53.     dim = x->dim;
  54.  
  55.     sum = 0.0;
  56.     if ( scale == (VEC *)NULL )
  57.         for ( i = 0; i < dim; i++ )
  58.             sum += square(x->ve[i]);
  59.     else if ( scale->dim < dim )
  60.         error(E_SIZES,"_v_norm2");
  61.     else
  62.         for ( i = 0; i < dim; i++ )
  63.         {    s = scale->ve[i];
  64.             sum += ( s== 0.0 ) ? square(x->ve[i]) :
  65.                             square(x->ve[i]/s);
  66.         }
  67.  
  68.     return sqrt(sum);
  69. }
  70.  
  71. #define    max(a,b)    ((a) > (b) ? (a) : (b))
  72.  
  73. /* _v_norm_inf -- computes (scaled) infinity-norm (supremum norm) of vectors */
  74. double    _v_norm_inf(x,scale)
  75. VEC    *x, *scale;
  76. {
  77.     int    i, dim;
  78.     Real    s, maxval, tmp;
  79.  
  80.     if ( x == (VEC *)NULL )
  81.         error(E_NULL,"_v_norm_inf");
  82.     dim = x->dim;
  83.  
  84.     maxval = 0.0;
  85.     if ( scale == (VEC *)NULL )
  86.         for ( i = 0; i < dim; i++ )
  87.         {    tmp = fabs(x->ve[i]);
  88.             maxval = max(maxval,tmp);
  89.         }
  90.     else if ( scale->dim < dim )
  91.         error(E_SIZES,"_v_norm_inf");
  92.     else
  93.         for ( i = 0; i < dim; i++ )
  94.         {    s = scale->ve[i];
  95.             tmp = ( s== 0.0 ) ? fabs(x->ve[i]) : fabs(x->ve[i]/s);
  96.             maxval = max(maxval,tmp);
  97.         }
  98.  
  99.     return maxval;
  100. }
  101.  
  102. /* m_norm1 -- compute matrix 1-norm -- unscaled */
  103. double    m_norm1(A)
  104. MAT    *A;
  105. {
  106.     int    i, j, m, n;
  107.     Real    maxval, sum;
  108.  
  109.     if ( A == (MAT *)NULL )
  110.         error(E_NULL,"m_norm1");
  111.  
  112.     m = A->m;    n = A->n;
  113.     maxval = 0.0;
  114.  
  115.     for ( j = 0; j < n; j++ )
  116.     {
  117.         sum = 0.0;
  118.         for ( i = 0; i < m; i ++ )
  119.             sum += fabs(A->me[i][j]);
  120.         maxval = max(maxval,sum);
  121.     }
  122.  
  123.     return maxval;
  124. }
  125.  
  126. /* m_norm_inf -- compute matrix infinity-norm -- unscaled */
  127. double    m_norm_inf(A)
  128. MAT    *A;
  129. {
  130.     int    i, j, m, n;
  131.     Real    maxval, sum;
  132.  
  133.     if ( A == (MAT *)NULL )
  134.         error(E_NULL,"m_norm_inf");
  135.  
  136.     m = A->m;    n = A->n;
  137.     maxval = 0.0;
  138.  
  139.     for ( i = 0; i < m; i++ )
  140.     {
  141.         sum = 0.0;
  142.         for ( j = 0; j < n; j ++ )
  143.             sum += fabs(A->me[i][j]);
  144.         maxval = max(maxval,sum);
  145.     }
  146.  
  147.     return maxval;
  148. }
  149.  
  150. /* m_norm_frob -- compute matrix frobenius-norm -- unscaled */
  151. double    m_norm_frob(A)
  152. MAT    *A;
  153. {
  154.     int    i, j, m, n;
  155.     Real    sum;
  156.  
  157.     if ( A == (MAT *)NULL )
  158.         error(E_NULL,"m_norm_frob");
  159.  
  160.     m = A->m;    n = A->n;
  161.     sum = 0.0;
  162.  
  163.     for ( i = 0; i < m; i++ )
  164.         for ( j = 0; j < n; j ++ )
  165.             sum += square(A->me[i][j]);
  166.  
  167.     return sqrt(sum);
  168. }
  169.  
  170. FileDataŵotherioŵEÿÿÿ‘ñ?ñã
  171. /**************************************************************************
  172. **
  173. ** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved.
  174. **
  175. **                 Meschach Library
  176. ** 
  177. ** This Meschach Library is provided "as is" without any express 
  178. ** or implied warranty of any kind with respect to this software. 
  179. ** In particular the authors shall not be liable for any direct, 
  180. ** indirect, special, incidental or consequential damages arising 
  181. ** in any way from use of the software.
  182. ** 
  183. ** Everyone is granted permission to copy, modify and redistribute this
  184. ** Meschach Library, provided:
  185. **  1.  All copies contain this copyright notice.
  186. **  2.  All modified copies shall carry a notice stating who
  187. **      made the last modification and the date of such modification.
  188. **  3.  No charge is made for this software or works derived from it.  
  189. **      This clause shall not be construed as constraining other software
  190. **      distributed on the same medium as this software, nor is a
  191. **      distribution fee considered a charge.
  192. **
  193. ***************************************************************************/
  194.  
  195.  
  196. /*
  197.     File for doing assorted I/O operations not invlolving
  198.     MAT/VEC/PERM objects
  199. */
  200. static    char    rcsid[] = "$Id: otherio.c,v 1.2 1994/01/13 05:34:52 des Exp $";
  201.  
  202. #include    <stdio.h>
  203. #include    <ctype.h>
  204. #include    "matrix.h"
  205.  
  206.  
  207.  
  208. /* scratch area -- enough for a single line */
  209. static    char    scratch[MAXLINE+1];
  210.  
  211. /* default value for fy_or_n */
  212. static    int    y_n_dflt = TRUE;
  213.  
  214. /* fy_or_n -- yes-or-no to question is string s
  215.     -- question written to stderr, input from fp 
  216.     -- if fp is NOT a tty then return y_n_dflt */
  217. int    fy_or_n(fp,s)
  218. FILE    *fp;
  219. char    *s;
  220. {
  221.     char    *cp;
  222.  
  223.     if ( ! isatty(fileno(fp)) )
  224.         return y_n_dflt;
  225.  
  226.     for ( ; ; )
  227.     {
  228.         fprintf(stderr,"%s (y/n) ? ",s);
  229.         if ( fgets(scratch,MAXLINE,fp)==NULL )
  230.             error(E_INPUT,"fy_or_n");
  231.         cp = scratch;
  232.         while ( isspace(*cp) )
  233.             cp++;
  234.         if ( *cp == 'y' || *cp == 'Y' )
  235.             return TRUE;
  236.         if ( *cp == 'n' || *cp == 'N' )
  237.             return FALSE;
  238.         fprintf(stderr,"Please reply with 'y' or 'Y' for yes ");
  239.         fprintf(stderr,"and 'n' or 'N' for no.\n");
  240.     }
  241. }
  242.  
  243. /* yn_dflt -- sets the value of y_n_dflt to val */
  244. int    yn_dflt(val)
  245. int    val;
  246. {    return y_n_dflt = val;        }
  247.  
  248. /* fin_int -- return integer read from file/stream fp
  249.     -- prompt s on stderr if fp is a tty
  250.     -- check that x lies between low and high: re-prompt if
  251.         fp is a tty, error exit otherwise
  252.     -- ignore check if low > high        */
  253. int    fin_int(fp,s,low,high)
  254. FILE    *fp;
  255. char    *s;
  256. int    low, high;
  257. {
  258.     int    retcode, x;
  259.  
  260.     if ( ! isatty(fileno(fp)) )
  261.     {
  262.         skipjunk(fp);
  263.         if ( (retcode=fscanf(fp,"%d",&x)) == EOF )
  264.             error(E_INPUT,"fin_int");
  265.         if ( retcode <= 0 )
  266.             error(E_FORMAT,"fin_int");
  267.         if ( low <= high && ( x < low || x > high ) )
  268.             error(E_BOUNDS,"fin_int");
  269.         return x;
  270.     }
  271.  
  272.     for ( ; ; )
  273.     {
  274.         fprintf(stderr,"%s: ",s);
  275.         if ( fgets(scratch,MAXLINE,stdin)==NULL )
  276.             error(E_INPUT,"fin_int");
  277.         retcode = sscanf(scratch,"%d",&x);
  278.         if ( ( retcode==1 && low > high ) ||
  279.                     ( x >= low && x <= high ) )
  280.             return x;
  281.         fprintf(stderr,"Please type an integer in range [%d,%d].\n",
  282.                             low,high);
  283.     }
  284. }
  285.  
  286.  
  287. /* fin_double -- return double read from file/stream fp
  288.     -- prompt s on stderr if fp is a tty
  289.     -- check that x lies between low and high: re-prompt if
  290.         fp is a tty, error exit otherwise
  291.     -- ignore check if low > high        */
  292. double    fin_double(fp,s,low,high)
  293. FILE    *fp;
  294. char    *s;
  295. double    low, high;
  296. {
  297.     Real    retcode, x;
  298.  
  299.     if ( ! isatty(fileno(fp)) )
  300.     {
  301.         skipjunk(fp);
  302. #if REAL == DOUBLE
  303.         if ( (retcode=fscanf(fp,"%lf",&x)) == EOF )
  304. #elif REAL == FLOAT
  305.         if ( (retcode=fscanf(fp,"%f",&x)) == EOF )
  306. #endif
  307.             error(E_INPUT,"fin_double");
  308.         if ( retcode <= 0 )
  309.             error(E_FORMAT,"fin_double");
  310.         if ( low <= high && ( x < low || x > high ) )
  311.             error(E_BOUNDS,"fin_double");
  312.         return (double)x;
  313.     }
  314.  
  315.     for ( ; ; )
  316.     {
  317.         fprintf(stderr,"%s: ",s);
  318.         if ( fgets(scratch,MAXLINE,stdin)==NULL )
  319.             error(E_INPUT,"fin_double");
  320. #if REAL == DOUBLE
  321.         retcode = sscanf(scratch,"%lf",&x);
  322. #elif REAL == FLOAT 
  323.         retcode = sscanf(scratch,"%f",&x);
  324. #endif
  325.         if ( ( retcode==1 && low > high ) ||
  326.                     ( x >= low && x <= high ) )
  327.             return (double)x;
  328.         fprintf(stderr,"Please type an double in range [%g,%g].\n",
  329.                             low,high);
  330.     }
  331. }
  332.  
  333.  
  334. FileDataŵpxopIEÿÿÿàÆ-;èº
  335. /**************************************************************************
  336. **
  337. ** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved.
  338. **
  339. **                 Meschach Library
  340. ** 
  341. ** This Meschach Library is provided "as is" without any express 
  342. ** or implied warranty of any kind with respect to this software. 
  343. ** In particular the authors shall not be liable for any direct, 
  344. ** indirect, special, incidental or consequential damages arising 
  345. ** in any way from use of the software.
  346. ** 
  347. ** Everyone is granted permission to copy, modify and redistribute this
  348. ** Meschach Library, provided:
  349. **  1.  All copies contain this copyright notice.
  350. **  2.  All modified copies shall carry a notice stating who
  351. **      made the last modification and the date of such modification.
  352. **  3.  No charge is made for this software or works derived from it.  
  353. **      This clause shall not be construed as constraining other software
  354. **      distributed on the same medium as this software, nor is a
  355. **      distribution fee considered a charge.
  356. **
  357. ***************************************************************************/
  358.  
  359.  
  360. /* pxop.c 1.5 12/03/87 */
  361.  
  362.  
  363. #include    <stdio.h>
  364. #include    "matrix.h"
  365.  
  366. static    char    rcsid[] = "$Id: pxop.c,v 1.5 1994/03/23 23:58:50 des Exp $";
  367.  
  368. /**********************************************************************
  369. Note: A permutation is often interpreted as a matrix
  370.         (i.e. a permutation matrix).
  371.     A permutation px represents a permutation matrix P where
  372.         P[i][j] == 1 if and only if px->pe[i] == j
  373. **********************************************************************/
  374.  
  375.  
  376. /* px_inv -- invert permutation -- in situ
  377.     -- taken from ACM Collected Algorithms #250 */
  378. PERM    *px_inv(px,out)
  379. PERM    *px, *out;
  380. {
  381.     int    i, j, k, n, *p;
  382.     
  383.     out = px_copy(px, out);
  384.     n = out->size;
  385.     p = (int *)(out->pe);
  386.     for ( n--; n>=0; n-- )
  387.     {
  388.     i = p[n];
  389.     if ( i < 0 )    p[n] = -1 - i;
  390.     else if ( i != n )
  391.     {
  392.         k = n;
  393.         while (TRUE)
  394.         {
  395.         if ( i < 0 || i >= out->size )
  396.             error(E_BOUNDS,"px_inv");
  397.         j = p[i];    p[i] = -1 - k;
  398.         if ( j == n )
  399.         {    p[n] = i;    break;        }
  400.         k = i;        i = j;
  401.         }
  402.     }
  403.     }
  404.     return out;
  405. }
  406.  
  407. /* px_mlt -- permutation multiplication (composition) */
  408. PERM    *px_mlt(px1,px2,out)
  409. PERM    *px1,*px2,*out;
  410. {
  411.     u_int    i,size;
  412.     
  413.     if ( px1==(PERM *)NULL || px2==(PERM *)NULL )
  414.     error(E_NULL,"px_mlt");
  415.     if ( px1->size != px2->size )
  416.     error(E_SIZES,"px_mlt");
  417.     if ( px1 == out || px2 == out )
  418.     error(E_INSITU,"px_mlt");
  419.     if ( out==(PERM *)NULL || out->size < px1->size )
  420.     out = px_resize(out,px1->size);
  421.     
  422.     size = px1->size;
  423.     for ( i=0; i<size; i++ )
  424.     if ( px2->pe[i] >= size )
  425.         error(E_BOUNDS,"px_mlt");
  426.     else
  427.         out->pe[i] = px1->pe[px2->pe[i]];
  428.     
  429.     return out;
  430. }
  431.  
  432. /* px_vec -- permute vector */
  433. VEC    *px_vec(px,vector,out)
  434. PERM    *px;
  435. VEC    *vector,*out;
  436. {
  437.     u_int    old_i, i, size, start;
  438.     Real    tmp;
  439.     
  440.     if ( px==(PERM *)NULL || vector==(VEC *)NULL )
  441.     error(E_NULL,"px_vec");
  442.     if ( px->size > vector->dim )
  443.     error(E_SIZES,"px_vec");
  444.     if ( out==(VEC *)NULL || out->dim < vector->dim )
  445.     out = v_resize(out,vector->dim);
  446.     
  447.     size = px->size;
  448.     if ( size == 0 )
  449.     return v_copy(vector,out);
  450.     if ( out != vector )
  451.     {
  452.     for ( i=0; i<size; i++ )
  453.         if ( px->pe[i] >= size )
  454.         error(E_BOUNDS,"px_vec");
  455.         else
  456.         out->ve[i] = vector->ve[px->pe[i]];
  457.     }
  458.     else
  459.     {    /* in situ algorithm */
  460.     start = 0;
  461.     while ( start < size )
  462.     {
  463.         old_i = start;
  464.         i = px->pe[old_i];
  465.         if ( i >= size )
  466.         {
  467.         start++;
  468.         continue;
  469.         }
  470.         tmp = vector->ve[start];
  471.         while ( TRUE )
  472.         {
  473.         vector->ve[old_i] = vector->ve[i];
  474.         px->pe[old_i] = i+size;
  475.         old_i = i;
  476.         i = px->pe[old_i];
  477.         if ( i >= size )
  478.             break;
  479.         if ( i == start )
  480.         {
  481.             vector->ve[old_i] = tmp;
  482.             px->pe[old_i] = i+size;
  483.             break;
  484.         }
  485.         }
  486.         start++;
  487.     }
  488.  
  489.     for ( i = 0; i < size; i++ )
  490.         if ( px->pe[i] < size )
  491.         error(E_BOUNDS,"px_vec");
  492.         else
  493.         px->pe[i] = px->pe[i]-size;
  494.     }
  495.     
  496.     return out;
  497. }
  498.  
  499. /* pxinv_vec -- apply the inverse of px to x, returning the result in out */
  500. VEC    *pxinv_vec(px,x,out)
  501. PERM    *px;
  502. VEC    *x, *out;
  503. {
  504.     u_int    i, size;
  505.     
  506.     if ( ! px || ! x )
  507.     error(E_NULL,"pxinv_vec");
  508.     if ( px->size > x->dim )
  509.     error(E_SIZES,"pxinv_vec");
  510.     /* if ( x == out )
  511.     error(E_INSITU,"pxinv_vec"); */
  512.     if ( ! out || out->dim < x->dim )
  513.     out = v_resize(out,x->dim);
  514.     
  515.     size = px->size;
  516.     if ( size == 0 )
  517.     return v_copy(x,out);
  518.     if ( out != x )
  519.     {
  520.     for ( i=0; i<size; i++ )
  521.         if ( px->pe[i] >= size )
  522.         error(E_BOUNDS,"pxinv_vec");
  523.         else
  524.         out->ve[px->pe[i]] = x->ve[i];
  525.     }
  526.     else
  527.     {    /* in situ algorithm --- cheat's way out */
  528.     px_inv(px,px);
  529.     px_vec(px,x,out);
  530.     px_inv(px,px);
  531.     }
  532.  
  533.     return out;
  534. }
  535.  
  536.  
  537.  
  538. /* px_transp -- transpose elements of permutation
  539.         -- Really multiplying a permutation by a transposition */
  540. PERM    *px_transp(px,i1,i2)
  541. PERM    *px;        /* permutation to transpose */
  542. u_int    i1,i2;        /* elements to transpose */
  543. {
  544.     u_int    temp;
  545.  
  546.     if ( px==(PERM *)NULL )
  547.         error(E_NULL,"px_transp");
  548.  
  549.     if ( i1 < px->size && i2 < px->size )
  550.     {
  551.         temp = px->pe[i1];
  552.         px->pe[i1] = px->pe[i2];
  553.         px->pe[i2] = temp;
  554.     }
  555.  
  556.     return px;
  557. }
  558.  
  559. /* myqsort -- a cheap implementation of Quicksort on integers
  560.         -- returns number of swaps */
  561. static int myqsort(a,num)
  562. int    *a, num;
  563. {
  564.     int    i, j, tmp, v;
  565.     int    numswaps;
  566.  
  567.     numswaps = 0;
  568.     if ( num <= 1 )
  569.         return 0;
  570.  
  571.     i = 0;    j = num;    v = a[0];
  572.     for ( ; ; )
  573.     {
  574.         while ( a[++i] < v )
  575.             ;
  576.         while ( a[--j] > v )
  577.             ;
  578.         if ( i >= j )    break;
  579.  
  580.         tmp = a[i];
  581.         a[i] = a[j];
  582.         a[j] = tmp;
  583.         numswaps++;
  584.     }
  585.  
  586.     tmp = a[0];
  587.     a[0] = a[j];
  588.     a[j] = tmp;
  589.     if ( j != 0 )
  590.         numswaps++;
  591.  
  592.     numswaps += myqsort(&a[0],j);
  593.     numswaps += myqsort(&a[j+1],num-(j+1));
  594.  
  595.     return numswaps;
  596. }
  597.  
  598.  
  599. /* px_sign -- compute the ``sign'' of a permutation = +/-1 where
  600.         px is the product of an even/odd # transpositions */
  601. int    px_sign(px)
  602. PERM    *px;
  603. {
  604.     int    numtransp;
  605.     PERM    *px2;
  606.  
  607.     if ( px==(PERM *)NULL )
  608.         error(E_NULL,"px_sign");
  609.     px2 = px_copy(px,PNULL);
  610.     numtransp = myqsort(px2->pe,px2->size);
  611.     px_free(px2);
  612.  
  613.     return ( numtransp % 2 ) ? -1 : 1;
  614. }
  615.  
  616.  
  617. /* px_cols -- permute columns of matrix A; out = A.px'
  618.     -- May NOT be in situ */
  619. MAT    *px_cols(px,A,out)
  620. PERM    *px;
  621. MAT    *A, *out;
  622. {
  623.     int    i, j, m, n, px_j;
  624.     Real    **A_me, **out_me;
  625. #ifdef ANSI_C
  626.     MAT    *m_get(int, int);
  627. #else
  628.     extern MAT    *m_get();
  629. #endif
  630.  
  631.     if ( ! A || ! px )
  632.         error(E_NULL,"px_cols");
  633.     if ( px->size != A->n )
  634.         error(E_SIZES,"px_cols");
  635.     if ( A == out )
  636.         error(E_INSITU,"px_cols");
  637.     m = A->m;    n = A->n;
  638.     if ( ! out || out->m != m || out->n != n )
  639.         out = m_get(m,n);
  640.     A_me = A->me;    out_me = out->me;
  641.  
  642.     for ( j = 0; j < n; j++ )
  643.     {
  644.         px_j = px->pe[j];
  645.         if ( px_j >= n )
  646.             error(E_BOUNDS,"px_cols");
  647.         for ( i = 0; i < m; i++ )
  648.             out_me[i][px_j] = A_me[i][j];
  649.     }
  650.  
  651.     return out;
  652. }
  653.  
  654. /* px_rows -- permute columns of matrix A; out = px.A
  655.     -- May NOT be in situ */
  656. MAT    *px_rows(px,A,out)
  657. PERM    *px;
  658. MAT    *A, *out;
  659. {
  660.     int    i, j, m, n, px_i;
  661.     Real    **A_me, **out_me;
  662. #ifdef ANSI_C
  663.     MAT    *m_get(int, int);
  664. #else
  665.     extern MAT    *m_get();
  666. #endif
  667.  
  668.     if ( ! A || ! px )
  669.         error(E_NULL,"px_rows");
  670.     if ( px->size != A->m )
  671.         error(E_SIZES,"px_rows");
  672.     if ( A == out )
  673.         error(E_INSITU,"px_rows");
  674.     m = A->m;    n = A->n;
  675.     if ( ! out || out->m != m || out->n != n )
  676.         out = m_get(m,n);
  677.     A_me = A->me;    out_me = out->me;
  678.  
  679.     for ( i = 0; i < m; i++ )
  680.     {
  681.         px_i = px->pe[i];
  682.         if ( px_i >= m )
  683.             error(E_BOUNDS,"px_rows");
  684.         for ( j = 0; j < n; j++ )
  685.             out_me[i][j] = A_me[px_i][j];
  686.     }
  687.  
  688.     return out;
  689. }
  690.  
  691. FileDataŵqrfactorE4EÿÿÿØþ?´!
  692. /**************************************************************************
  693. **
  694. ** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved.
  695. **
  696. **                 Meschach Library
  697. ** 
  698. ** This Meschach Library is provided "as is" without any express 
  699. ** or implied warranty of any kind with respect to this software. 
  700. ** In particular the authors shall not be liable for any direct, 
  701. ** indirect, special, incidental or consequential damages arising 
  702. ** in any way from use of the software.
  703. ** 
  704. ** Everyone is granted permission to copy, modify and redistribute this
  705. ** Meschach Library, provided:
  706. **  1.  All copies contain this copyright notice.
  707. **  2.  All modified copies shall carry a notice stating who
  708. **      made the last modification and the date of such modification.
  709. **  3.  No charge is made for this software or works derived from it.  
  710. **      This clause shall not be construed as constraining other software
  711. **      distributed on the same medium as this software, nor is a
  712. **      distribution fee considered a charge.
  713. **
  714. ***************************************************************************/
  715.  
  716.  
  717. /*
  718.   This file contains the routines needed to perform QR factorisation
  719.   of matrices, as well as Householder transformations.
  720.   The internal "factored form" of a matrix A is not quite standard.
  721.   The diagonal of A is replaced by the diagonal of R -- not by the 1st non-zero
  722.   entries of the Householder vectors. The 1st non-zero entries are held in
  723.   the diag parameter of QRfactor(). The reason for this non-standard
  724.   representation is that it enables direct use of the Usolve() function
  725.   rather than requiring that  a seperate function be written just for this case.
  726.   See, e.g., QRsolve() below for more details.
  727.   
  728. */
  729.  
  730.  
  731. static    char    rcsid[] = "$Id: qrfactor.c,v 1.5 1994/01/13 05:35:07 des Exp $";
  732.  
  733. #include    <stdio.h>
  734. #include    <math.h>
  735. #include        "matrix2.h"
  736.  
  737.  
  738.  
  739.  
  740.  
  741. #define        sign(x)    ((x) > 0.0 ? 1 : ((x) < 0.0 ? -1 : 0 ))
  742.  
  743. extern    VEC    *Usolve();    /* See matrix2.h */
  744.  
  745. /* Note: The usual representation of a Householder transformation is taken
  746.    to be:
  747.    P = I - beta.u.uT
  748.    where beta = 2/(uT.u) and u is called the Householder vector
  749.    */
  750.  
  751. /* QRfactor -- forms the QR factorisation of A -- factorisation stored in
  752.    compact form as described above ( not quite standard format ) */
  753. /* MAT    *QRfactor(A,diag,beta) */
  754. MAT    *QRfactor(A,diag)
  755. MAT    *A;
  756. VEC    *diag /* ,*beta */;
  757. {
  758.     u_int    k,limit;
  759.     Real    beta;
  760.     static    VEC    *tmp1=VNULL;
  761.     
  762.     if ( ! A || ! diag )
  763.     error(E_NULL,"QRfactor");
  764.     limit = min(A->m,A->n);
  765.     if ( diag->dim < limit )
  766.     error(E_SIZES,"QRfactor");
  767.     
  768.     tmp1 = v_resize(tmp1,A->m);
  769.     MEM_STAT_REG(tmp1,TYPE_VEC);
  770.     
  771.     for ( k=0; k<limit; k++ )
  772.     {
  773.     /* get H/holder vector for the k-th column */
  774.     get_col(A,k,tmp1);
  775.     /* hhvec(tmp1,k,&beta->ve[k],tmp1,&A->me[k][k]); */
  776.     hhvec(tmp1,k,&beta,tmp1,&A->me[k][k]);
  777.     diag->ve[k] = tmp1->ve[k];
  778.     
  779.     /* apply H/holder vector to remaining columns */
  780.     /* hhtrcols(A,k,k+1,tmp1,beta->ve[k]); */
  781.     hhtrcols(A,k,k+1,tmp1,beta);
  782.     }
  783.  
  784.     return (A);
  785. }
  786.  
  787. /* QRCPfactor -- forms the QR factorisation of A with column pivoting
  788.    -- factorisation stored in compact form as described above
  789.    ( not quite standard format )                */
  790. /* MAT    *QRCPfactor(A,diag,beta,px) */
  791. MAT    *QRCPfactor(A,diag,px)
  792. MAT    *A;
  793. VEC    *diag /* , *beta */;
  794. PERM    *px;
  795. {
  796.     u_int    i, i_max, j, k, limit;
  797.     static    VEC    *gamma=VNULL, *tmp1=VNULL, *tmp2=VNULL;
  798.     Real    beta, maxgamma, sum, tmp;
  799.     
  800.     if ( ! A || ! diag || ! px )
  801.     error(E_NULL,"QRCPfactor");
  802.     limit = min(A->m,A->n);
  803.     if ( diag->dim < limit || px->size != A->n )
  804.     error(E_SIZES,"QRCPfactor");
  805.     
  806.     tmp1 = v_resize(tmp1,A->m);
  807.     tmp2 = v_resize(tmp2,A->m);
  808.     gamma = v_resize(gamma,A->n);
  809.     MEM_STAT_REG(tmp1,TYPE_VEC);
  810.     MEM_STAT_REG(tmp2,TYPE_VEC);
  811.     MEM_STAT_REG(gamma,TYPE_VEC);
  812.     
  813.     /* initialise gamma and px */
  814.     for ( j=0; j<A->n; j++ )
  815.     {
  816.     px->pe[j] = j;
  817.     sum = 0.0;
  818.     for ( i=0; i<A->m; i++ )
  819.         sum += square(A->me[i][j]);
  820.     gamma->ve[j] = sum;
  821.     }
  822.     
  823.     for ( k=0; k<limit; k++ )
  824.     {
  825.     /* find "best" column to use */
  826.     i_max = k;    maxgamma = gamma->ve[k];
  827.     for ( i=k+1; i<A->n; i++ )
  828.         /* Loop invariant:maxgamma=gamma[i_max]
  829.            >=gamma[l];l=k,...,i-1 */
  830.         if ( gamma->ve[i] > maxgamma )
  831.         {    maxgamma = gamma->ve[i]; i_max = i;    }
  832.     
  833.     /* swap columns if necessary */
  834.     if ( i_max != k )
  835.     {
  836.         /* swap gamma values */
  837.         tmp = gamma->ve[k];
  838.         gamma->ve[k] = gamma->ve[i_max];
  839.         gamma->ve[i_max] = tmp;
  840.         
  841.         /* update column permutation */
  842.         px_transp(px,k,i_max);
  843.         
  844.         /* swap columns of A */
  845.         for ( i=0; i<A->m; i++ )
  846.         {
  847.         tmp = A->me[i][k];
  848.         A->me[i][k] = A->me[i][i_max];
  849.         A->me[i][i_max] = tmp;
  850.         }
  851.     }
  852.     
  853.     /* get H/holder vector for the k-th column */
  854.     get_col(A,k,tmp1);
  855.     /* hhvec(tmp1,k,&beta->ve[k],tmp1,&A->me[k][k]); */
  856.     hhvec(tmp1,k,&beta,tmp1,&A->me[k][k]);
  857.     diag->ve[k] = tmp1->ve[k];
  858.     
  859.     /* apply H/holder vector to remaining columns */
  860.     /* hhtrcols(A,k,k+1,tmp1,beta->ve[k]); */
  861.     hhtrcols(A,k,k+1,tmp1,beta);
  862.     
  863.     /* update gamma values */
  864.     for ( j=k+1; j<A->n; j++ )
  865.         gamma->ve[j] -= square(A->me[k][j]);
  866.     }
  867.  
  868.     return (A);
  869. }
  870.  
  871. /* Qsolve -- solves Qx = b, Q is an orthogonal matrix stored in compact
  872.    form a la QRfactor() -- may be in-situ */
  873. /* VEC    *_Qsolve(QR,diag,beta,b,x,tmp) */
  874. VEC    *_Qsolve(QR,diag,b,x,tmp)
  875. MAT    *QR;
  876. VEC    *diag /* ,*beta */ , *b, *x, *tmp;
  877. {
  878.     u_int    dynamic;
  879.     int        k, limit;
  880.     Real    beta, r_ii, tmp_val;
  881.     
  882.     limit = min(QR->m,QR->n);
  883.     dynamic = FALSE;
  884.     if ( ! QR || ! diag || ! b )
  885.     error(E_NULL,"_Qsolve");
  886.     if ( diag->dim < limit || b->dim != QR->m )
  887.     error(E_SIZES,"_Qsolve");
  888.     x = v_resize(x,QR->m);
  889.     if ( tmp == VNULL )
  890.     dynamic = TRUE;
  891.     tmption and the date of such modification.
  892. **  3.  No charge is made for this software or works derived from it.  
  893. **      This clause shall not be construed as constraining other software
  894. **      distributed on the same medium as this software, nor is a
  895. **      distribution fee considered a charge.
  896. **
  897. ***************************************************************************/
  898.  
  899.  
  900. /*
  901.   Sparse matrix Bunch--Kaufman--Parlett factorisation and solve
  902.   Radical revision started Thu 05th Nov 1992, 09:36:12 AM
  903.   to use Karen George's suggestion of leaving the the row elements unordered
  904.   Radical revision completed Mon 07th Dec 1992, 10:59:57 AM
  905. */
  906.  
  907. static    char    rcsid[] = "$Id: spbkp.c,v 1.5 1994/01/13 05:44:35 des Exp $";
  908.  
  909. #include    <stdio.h>
  910. #include    <math.h>
  911. #include    "matrix.h"
  912. #include    "sparse.h"
  913. #include        "sparse2.h"
  914.  
  915.  
  916. #ifdef MALLOCDECL
  917. #include <malloc.h>
  918. #endif
  919.  
  920. #define alpha    0.6403882032022076 /* = (1+sqrt(17))/8 */
  921.  
  922.  
  923. #define    btos(x)    ((x) ? "TRUE" : "FALSE")
  924.  
  925. /* assume no use of sqr() uses side-effects */
  926. #define    sqr(x)    ((x)*(x))
  927.  
  928. /* unord_get_idx -- returns index (encoded if entry not allocated)
  929.     of the element of row r with column j
  930.     -- uses linear search */
  931. int    unord_get_idx(r,j)
  932. SPROW    *r;
  933. int    j;
  934. {
  935.     int        idx;
  936.     row_elt    *e;
  937.  
  938.     if ( ! r || ! r->elt )
  939.     error(E_NULL,"unord_get_idx");
  940.     for ( idx = 0, e = r->elt; idx < r->len; idx++, e++ )
  941.     if ( e->col == j )
  942.         break;
  943.     if ( idx >= r->len )
  944.     return -(r->len+2);
  945.     else
  946.     return idx;
  947. }
  948.  
  949. /* unord_get_val -- returns value of the (i,j) entry of A
  950.     -- same assumptions as unord_get_idx() */
  951. double    unord_get_val(A,i,j)
  952. SPMAT    *A;
  953. int    i, j;
  954. {
  955.     SPROW    *r;
  956.     int        idx;
  957.  
  958.     if ( ! A )
  959.     error(E_NULL,"unord_get_val");
  960.     if ( i < 0 || i >= A->m || j < 0 || j >= A->n )
  961.     error(E_BOUNDS,"unord_get_val");
  962.  
  963.     r = &(A->row[i]);
  964.     idx = unord_get_idx(r,j);
  965.     if ( idx < 0 )
  966.     return 0.0;
  967.     else
  968.     return r->elt[idx].val;
  969. }
  970.  
  971.         
  972. /* bkp_swap_elt -- swaps the (i,j) with the (k,l) entry of sparse matrix
  973.     -- either or both of the entries may be unallocated */
  974. static SPMAT    *bkp_swap_elt(A,i1,j1,idx1,i2,j2,idx2)
  975. SPMAT    *A;
  976. int    i1, j1, idx1, i2, j2, idx2;
  977. {
  978.     int        tmp_row, tmp_idx;
  979.     SPROW    *r1, *r2;
  980.     row_elt    *e1, *e2;
  981.     Real    tmp;
  982.  
  983.     if ( ! A )
  984.     error(E_NULL,"bkp_swap_elt");
  985.  
  986.     if ( i1 < 0 || j1 < 0 || i2 < 0 || j2 < 0 ||
  987.      i1 >= A->m || j1 >= A->n || i2 >= A->m || j2 >= A->n )
  988.     {
  989.     error(E_BOUNDS,"bkp_swap_elt");
  990.     }
  991.  
  992.     if ( i1 == i2 && j1 == j2 )
  993.     return A;
  994.     if ( idx1 < 0 && idx2 < 0 )    /* neither allocated */
  995.     return A;
  996.  
  997.     r1 = &(A->row[i1]);        r2 = &(A->row[i2]);
  998.     /* if ( idx1 >= r1->len || idx2 >= r2->len )
  999.     error(E_BOUNDS,"bkp_swap_elt"); */
  1000.     if ( idx1 < 0 )    /* assume not allocated */
  1001.     {
  1002.     idx1 = r1->len;
  1003.     if ( idx1 >= r1->maxlen )
  1004.     {    tracecatch(sprow_xpd(r1,2*r1->maxlen+1,TYPE_SPMAT),
  1005.             "bkp_swap_elt");    }
  1006.     r1->len = idx1+1;
  1007.     r1->elt[idx1].col = j1;
  1008.     r1->elt[idx1].val = 0.0;
  1009.     /* now patch up column access path */
  1010.     tmp_row = -1;    tmp_idx = j1;
  1011.     chase_col(A,j1,&tmp_row,&tmp_idx,i1-1);
  1012.  
  1013.     if ( tmp_row < 0 )
  1014.     {
  1015.         r1->elt[idx1].nxt_row = A->start_row[j1];
  1016.         r1->elt[idx1].nxt_idx = A->start_idx[j1];
  1017.         A->start_row[j1] = i1;
  1018.         A->start_idx[j1] = idx1;
  1019.     }
  1020.     else
  1021.     {
  1022.         row_elt    *tmp_e;
  1023.  
  1024.         tmp_e = &(A->