LCOV - code coverage report
Current view: top level - src - qrfactorization.c (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 208 247 84.2 %
Date: 2020-12-14 08:13:14 Functions: 5 5 100.0 %

          Line data    Source code
       1             : #include <stdio.h>
       2             : #include <tgmath.h>
       3             : 
       4             : #include "dist.h"
       5             : #include "mathext.h"
       6             : #include "qrfactorization.h"
       7             : 
       8             : #define map(i, j) ((j)-1) * lda + ((i)-1)
       9             : #define a(i, j) a[ map(i, j) ]
      10             : #define q(i, j) q[ map(i, j) ]
      11             : #define map1(i) (i) - 1
      12             : #define x(i) x[ map1(i) ]
      13             : #define y(i) y[ map1(i) ]
      14             : #define ipiv(i) ipiv[ map1(i) ]
      15             : #define wrk(i) wrk[ map1(i) ]
      16             : #define tau(i) tau[ map1(i) ]
      17             : #define swap(T, x, y) \
      18             :   {                   \
      19             :     T tmp = (x);      \
      20             :     x = (y);          \
      21             :     y = tmp;          \
      22             :   }
      23             : 
      24             : // Compute the QR factorization with column pivoting on all columns
      25             : // of an M by N matrix A
      26             : //                     A*P = Q*R
      27             : //
      28             : // The matrix Q is represented as a product of elementary reflectors
      29             : //
      30             : //    Q = H(1) H(2) . . . H(k),   where k = min(m,n).
      31             : //
      32             : // Each H(i) has the form
      33             : //
      34             : //    H(i) = I - tau * v * v'
      35             : //
      36             : // where tau is a real scalar, and v is a real vector with v(1:i-1) = 0
      37             : // and v(i) = 1; v(i+1:m) is stored on exit in A(i+1:m,i),
      38             : // and tau in TAU(i).
      39             : //
      40             : // The matrix P is represented in IPIV as follows: If IPIV(j) = i
      41             : // then the jth column of P is the ith canonical unit vector.
      42             : //
      43             : // Variables in the calling sequence
      44             : // ---------------------------------
      45             : // M      I   IN   The number of rows of the matrix A.  M >= 0.
      46             : // N      I   IN   The number of columns of the matrix A.  N >= 0.
      47             : // A      D   IN   The given M by N matrix
      48             : //            OUT  The elements on and above the diagonal contain
      49             : //                 the min(m,n) by n upper trapezoidal matrix R
      50             : //                 (R is upper triangular if m >= n); the elements
      51             : //                  belowthe diagonal, together with the array TAU,
      52             : //                  represent the orthogonal matrix Q as a product
      53             : //                  of min(m,n) elementary reflectors
      54             : // LDA    I   IN   The leading dimension of A. LDA >= max(1,M).
      55             : // IPIV   I   OUT  If IPIV(i) = k, then the i-th column of A*P was the
      56             : //                  k-th column of A.
      57             : // TAU    I   OUT  Array of dimension min(M,N), The scalar factors of
      58             : //                 the elementary reflectors
      59             : // WRK    D   WK   Work array of  dimension N
      60             : // SAFMIN D   IN   Safe minimum such that 1.0/SAFMIN does not
      61             : //                 overflow
      62             : // IER    I   OUT  Error indicator
      63             : //                 IER = 0   successful exit
      64             : //                 IER = 1   data-error
      65             : //                 IER = 2   input data error in HOUSL
      66             : //                 IER < 0   zero pivot encountered
      67          49 : int qrf(int m, int n, double *a, int lda, int *ipiv, double *tau, double *wrk,
      68             :         double safmin, int *ier)
      69             : {
      70          49 :   const double fact = 0.05, one = 1.0, zer = 0.0;
      71          49 :   int imax = 0, ip1 = 0, mn = 0;
      72          49 :   double cnrm = 0.0, cnrmj = 0.0, taui = 0.0, tmp1 = 0.0, tmp2 = 0.0,
      73          49 :          tmp3 = 0.0;
      74             : 
      75             :   // No error has occured
      76          49 :   *ier = 0;
      77             : 
      78             :   // Validate input
      79          49 :   if ((m < 0) || (n < 0) || (lda < m))
      80             :   {
      81           3 :     *ier = 1;
      82           3 :     return 1;
      83             :   }
      84             : 
      85             :   // Quick return
      86          46 :   if ((m == 0) || (n == 0))
      87             :   {
      88           2 :     *ier = 0;
      89           2 :     return 0;
      90             :   }
      91             : 
      92             :   // Initialize column norms and pivot array
      93         162 :   for (int j = 1; j <= n; j++)
      94             :   {
      95         118 :     cnrm = dnrm2(m, a + map(1, j), 1);
      96         118 :     tau(j) = cnrm;
      97         118 :     wrk(j) = cnrm;
      98         118 :     ipiv(j) = j;
      99             :   }
     100             : 
     101          44 :   mn = n;
     102          44 :   if (m < n) mn = m;
     103             : 
     104             :   // Main loop for the factorization
     105         156 :   for (int i = 1; i <= mn; i++)
     106             :   {
     107         116 :     ip1 = i + 1;
     108             :     // determine pivot column
     109         116 :     cnrm = tau(i);
     110         116 :     imax = i;
     111         116 :     if (i < n)
     112             :     {
     113         192 :       for (int j = ip1; j <= n; j++)
     114             :       {
     115         119 :         if (tau(j) > cnrm)
     116             :         {
     117          52 :           imax = j;
     118          52 :           cnrm = tau(j);
     119             :         }
     120             :       }
     121          73 :       if (cnrm == zer)
     122             :       {
     123           1 :         printf("Message from QRF: Zero pivot encountered\n");
     124           1 :         *ier = -i;
     125           1 :         return *ier;
     126             :       }
     127             :       // Swap the columns if necessary
     128          72 :       if (imax != i)
     129             :       {
     130         188 :         for (int j = 1; j <= m; j++)
     131             :         {
     132         153 :           swap(double, a(j, imax), a(j, i));
     133             :         }
     134          35 :         swap(int, ipiv(imax), ipiv(i));
     135          35 :         tau(imax) = tau(i);
     136          35 :         wrk(imax) = wrk(i);
     137             :       }
     138             :     }
     139         115 :     if (cnrm == zer)
     140             :     {
     141           3 :       printf("Message from QRF: Zero pivot encountered\n");
     142           3 :       *ier = -i;
     143           3 :       return *ier;
     144             :     }
     145             :     else
     146             :     {
     147             :       // Generate elementary reflector H(i)
     148         112 :       taui = zer;
     149         112 :       if (i < m)
     150          95 :         housg(m - i + 1, a + map(i, i), a + map(ip1, i), 1, &taui, safmin);
     151         112 :       if (i < n)
     152             :       {
     153             :         // Apply h(i) to a(i:m,i+1:n) from the left
     154          72 :         housl(m - i + 1, n - i, a + map(i, i), 1, taui, a + map(i, ip1), lda,
     155             :               ier);
     156          72 :         if (*ier != 0)
     157             :         {
     158           0 :           printf("Message from QRF: Input-dimension error in housl\n");
     159           0 :           *ier = 2;
     160           0 :           return *ier;
     161             :         }
     162             :         // Update column norms
     163         189 :         for (int j = ip1; j <= n; j++)
     164             :         {
     165         117 :           cnrmj = tau(j);
     166         117 :           if (cnrmj != zer)
     167             :           {
     168         117 :             tmp1 = fabs(a(i, j)) / cnrmj;
     169         117 :             tmp2 = one - tmp1 * tmp1;
     170         117 :             if (tmp2 <= zer)
     171             :             {
     172           2 :               tmp2 = zer;
     173           2 :               tmp3 = zer;
     174             :             }
     175             :             else
     176             :             {
     177         115 :               tmp3 = sqrt(tmp2);
     178             :             }
     179         117 :             tmp1 = cnrmj / wrk(j);
     180         117 :             tmp2 = one + fact * tmp2 * tmp1 * tmp1;
     181         117 :             if (tmp2 == one)
     182             :             {
     183           6 :               tau(j) = dnrm2(m - i, a + map(ip1, j), 1);
     184           6 :               wrk(j) = tau(j);
     185             :             }
     186             :             else
     187             :             {
     188         111 :               tau(j) *= tmp3;
     189             :             }
     190             :           }
     191             :         }
     192             :       }
     193         112 :       tau(i) = taui;
     194             :     }
     195             :   }
     196          40 :   *ier = 0;
     197          40 :   return *ier;
     198             : }
     199             : 
     200             : // For an  M x N matrix A with M >= N and rank A = N, and a given
     201             : // M-vector Y, compute the least squares solution
     202             : //
     203             : //    min { || A*X - Y || ; X in R^N }
     204             : //
     205             : // by the algorithm
     206             : //
     207             : //     1.  Y := Q^T Y
     208             : //     2.  IF( M >= N ) THEN Solve R*Z := (I, 0)Y, Set X := Z
     209             : //                      ELSE Solve R*Z := Y, Set X = (Z,0)
     210             : //
     211             : // under the assumption that the arrays A and TAU contain the
     212             : // QR-factorization of an M x N matrix A.
     213             : //
     214             : // The routine returns Q^T Y in the array Y and the least squares
     215             : // solution in the array X. The array X may be identified with Y
     216             : // if Q^T*Y is not needed.
     217             : //
     218             : // Variables in the calling sequence
     219             : // ---------------------------------
     220             : // M    I   IN   Number of rows of the matrix A, M >= N
     221             : // N    I   IN   Number of columns of the matrix A
     222             : // A    D   IN   Array of dimension LDA x n, the factored matrix
     223             : // LDA  I   IN   Leading dimension of A, LDA >= M
     224             : // TAU  D   IN   Array of dimension N containing the scalar
     225             : //               factor of the elementary reflectors, as
     226             : //               returned by QRF
     227             : // Y    D   IN   Array of dimension M, the given vector Y
     228             : //          OUT  The vector Q^T Y
     229             : // X    D   OUT  Array of dimension N, the computed solution
     230             : // IER  I   OUT  Error indicator
     231             : //               IER = 0   no error
     232             : //               IER = 1  input data error
     233             : //               IER < 0  zero pivot encountered
     234             : //                        IER = -J signifies that the
     235             : //                        J-th diagonal element of the
     236             : //                        triangular matrix R is zero.
     237             : //
     238          47 : int qrs(int m, int n, double *a, int lda, double *tau, double *y, double *x,
     239             :         int *ier)
     240             : {
     241          47 :   const double zer = 0.0;
     242          47 :   int jm1 = 0, jp1 = 0;
     243          47 :   double sum = 0, t = 0;
     244             : 
     245             :   // Validate input: lda >= m >= 0 holds from these conditions
     246          47 :   if ((m < 0) || (n < 0) || (m < n) || (lda < m))
     247             :   {
     248           4 :     *ier = 1;
     249           4 :     return 1;
     250             :   }
     251             : 
     252          43 :   *ier = 0;
     253             : 
     254             :   // Quick return: 0 = m >= n >= 0 implies m=n=0 so that lda >= 0.
     255             :   // If lda=0, then there is a quick return and matrix a is not accessed.
     256          43 :   if ((n == 0) || ((m == 0) && (n == 0)))
     257             :   {
     258           2 :     *ier = 0;
     259           2 :     return 0;
     260             :   }
     261             : 
     262             :   // The case m = 1, under the assumption m >= n, implies n=1
     263          41 :   if (m == 1)
     264             :   {
     265           2 :     if (a(1, 1) == zer)
     266             :     {
     267           1 :       printf("Message from QRS: Zero pivot encountered\n");
     268           1 :       *ier = -1;
     269           1 :       return -1;
     270             :     }
     271             :     else
     272             :     {
     273           1 :       x(1) = y(1) / a(1, 1);
     274           1 :       *ier = 0;
     275           1 :       return 0;
     276             :     }
     277             :   }
     278             : 
     279             :   // Compute transpose(Q)*y
     280             :   //
     281             :   // The matrix Q is represented as a product of elementary reflectors
     282             :   //
     283             :   //    Q = H(1) H(2) . . . H(k),   where k = min(m,n).
     284             :   //
     285             :   // Each H(i) has the form
     286             :   //
     287             :   //    H(i) = I - tau * v * v'
     288             :   //
     289             :   //  v(1) = 1. transpose(Q) = H(j) H(j-1) . . . H(1).
     290         147 :   for (int j = 1; j <= n; j++)
     291             :   {
     292         108 :     jp1 = j + 1;
     293             : 
     294             :     // Multiply transpose(v)*y
     295         108 :     sum = y(j);  // The first element of the elementary vector is 1
     296         108 :     if (j < m)
     297             :     {
     298         437 :       for (int i = jp1; i <= m; i++)
     299             :       {
     300         346 :         sum += a(i, j) * y(i);  // v stored in lower triangle of A
     301             :       }
     302             :     }
     303             : 
     304             :     // y overwritten by y - tau(j)*(transpose(v)*y)*v
     305         108 :     if (sum != zer)  // v is not zero
     306             :     {
     307          99 :       t = -tau(j) * sum;
     308          99 :       y(j) += t;  // The first element of v is 1
     309          99 :       if (j < m)
     310             :       {
     311         419 :         for (int i = jp1; i <= m; i++)
     312             :         {
     313         334 :           y(i) += t * a(i, j);
     314             :         }
     315             :       }
     316             :     }
     317             :   }
     318             : 
     319             :   // Set x := the first n components of y
     320         147 :   for (int j = 1; j <= n; j++)
     321             :   {
     322         108 :     x(j) = y(j);
     323             :   }
     324             :   // R is stored in the upper triangle of A including diagonal.
     325             :   //
     326             :   // Solve R*Z := (I,0)Y, and set X := Z
     327             :   // or solve  R*Z := Y, and set X := (Z,0)
     328         144 :   for (int j = n; j >= 1; j--)
     329             :   {
     330         106 :     if (a(j, j) == zer)
     331             :     {
     332           1 :       printf("Message from QRS: Zero pivot encountered\n");
     333           1 :       *ier = -j;
     334           1 :       return -j;
     335             :     }
     336             :     // Back substitution
     337         105 :     x(j) = x(j) / a(j, j);
     338         105 :     if (j > 1)
     339             :     {
     340          67 :       jm1 = j - 1;
     341          67 :       t = -x(j);
     342         176 :       for (int i = 1; i <= jm1; i++)
     343             :       {
     344         109 :         x(i) += t * a(i, j);
     345             :       }
     346             :     }
     347             :   }
     348          38 :   *ier = 0;
     349          38 :   return *ier;
     350             : }
     351             : 
     352             : //  Generate an M by NQ real matrix Q with NQ = L - K + 1 orthonormal
     353             : //  columns formed as the product of N Householder reflectors
     354             : //  H(1),...,H(N) of order M >= N as returned in the columns of the
     355             : //  array A by QRF.
     356             : //
     357             : //  Variables in the calling sequence:
     358             : //  ----------------------------------
     359             : //
     360             : //  M    I  IN   The number of rows of the matrix A. M >= 0.
     361             : //  N    I  IN   The number of columns of the matrix A. M >= N >= 0.
     362             : //  K    I  IN   The lower column index, M >= K >= 1
     363             : //               K is set to 1 if K <= 0
     364             : //  L    I  IN   The higher column index, M >= L >= K >= 1
     365             : //               L is set to M if L >= M
     366             : //  A    D  IN   Array of dimension (LDA,N)
     367             : //               For IA = 1 the i-th column of A is assumed to contain
     368             : //                   the vector defining the elementary reflector
     369             : //                   H(i), for i = 1,2,...,N, as returned by QRF
     370             : //               For IA = 2 the i-th row of A is assumed to contain
     371             : //                   the vector defining the elementary reflector
     372             : //                   H(i), for i = 1,2,...,M, as returned by QRF
     373             : //  LDA  I  IN   The leading dimension of the array A, LDA >= max(1,M).
     374             : //  TAU  D  IN   Array of dimension (K) where TAU(i) contains the
     375             : //               scalar factor of the elementary reflector H(i), as
     376             : //               returned by QRF.
     377             : //  Q    D  OUT  The orthogonal matrix.
     378             : //  LDQ  D  IN   The leading dimension of the array Q, LDQ >= max(1,M)
     379             : //  IER  I  OUT  Error indicator
     380             : //               IER = 0  successful exit
     381             : //               IER = 1  input-data error
     382             : //               IER = 2  input-data error in HOUSL
     383             : //
     384             : //  NOTE: The arrays A and Q cannot be identified
     385           9 : int qorg(int m, int n, int k, int l, double *a, int lda, double *tau, double *q,
     386             :          int ldq, int *ier)
     387             : {
     388           9 :   const double zer = 0.0, one = 1.0;
     389           9 :   int j2 = 0, km1 = 0, nl = 0, nq = 0;
     390             : 
     391             :   // Validate input: lda >= m >= 0 holds from these conditions
     392           9 :   if ((m < 0) || (n < 0) || (m < n) || (k > l) || (lda < m) || (ldq < 1) ||
     393             :       (ldq < m))
     394             :   {
     395           6 :     *ier = 1;
     396           6 :     return 1;
     397             :   }
     398             : 
     399           3 :   *ier = 0;
     400             : 
     401             :   // Quick return: 0 = m >= n >= 0 implies m=n=0 so that lda >= 0.
     402             :   // If lda=0, then there is a quick return and matrix a is not accessed.
     403             :   // k=0 handled because k < = 0 means k set to 1 below.
     404           3 :   if ((n == 0) || ((m == 0) && (n == 0)))
     405             :   {
     406           2 :     *ier = 0;
     407           2 :     return 0;
     408             :   }
     409             : 
     410             :   // Set defaults
     411           1 :   if (k < 0) k = 1;
     412           1 :   if (l > m) l = m;
     413             : 
     414             :   // Initialize Q
     415           1 :   km1 = k - 1;
     416           1 :   nq = l - km1;
     417           4 :   for (int j1 = 1; j1 <= nq; j1++)
     418             :   {
     419          12 :     for (int i = 1; i <= m; i++)
     420             :     {
     421           9 :       q(i, j1) = zer;
     422             :     }
     423           3 :     q(j1 + km1, j1) = one;
     424             :   }
     425             : 
     426             :   // Apply H(1)*...*H(NL)*Q
     427           1 :   nl = l;
     428           1 :   if (l > n) nl = l;
     429           1 :   j2 = nq;
     430           4 :   for (int j1 = nl; j1 >= 1; j1--)
     431             :   {
     432             :     // Apply H(J1) to Q(J1:M,J1:NQ) from the left
     433           3 :     housl(m - j1 + 1, nq - j2 + 1, a + map(j1, j1), 1, tau(j1), q + map(j1, j2),
     434             :           ldq, ier);
     435           3 :     if (*ier != 0)
     436             :     {
     437           0 :       printf("Message from QORG: Input-dimension error in housl\n");
     438           0 :       *ier = 2;
     439           0 :       return *ier;
     440             :     }
     441           3 :     j2 = j2 - 1;
     442           3 :     if (j2 < 1) j2 = 1;
     443             :   }
     444           1 :   *ier = 0;
     445           1 :   return *ier;
     446             : }
     447             : 
     448             : // Generates an n-dimensional Householder reflector
     449             : //
     450             : //    H = I - tau*( 1 ) * ( 1 v' ),    H' * H = I,   tau scalar
     451             : //                ( v )
     452             : //
     453             : // such that
     454             : //
     455             : //    H * ( alpha ) = ( beta ),    alpha, beta scalars
     456             : //        (   x   )   (   0  )     x  (n-1)-dimensional vector
     457             : //
     458             : // Because of H'* H = I it follows that
     459             : //
     460             : //    alpha^2 + x^T x = beta^2    ==> beta = sqrt(alpha^2 + x^T x)
     461             : //
     462             : //    H'( beta )  = ( alpha )     ==> tau = (beta - alpha)/beta
     463             : //      (  0   )    (  x    )           v = xscal*x,
     464             : //                                  xscal = 1/(beta - alpha)
     465             : //
     466             : //    If x = 0, then tau = 0 and H = I, otherwise  1 <= tau <= 2.
     467             : //
     468             : // This is an edited version of the LAPACK routine DLARFG
     469             : //
     470             : // Variables in the calling sequence:
     471             : // ----------------------------------
     472             : // N      I   IN   Dimension of H
     473             : // ALPHA  D   IN   The scalar alpha
     474             : //            OUT  The scalar beta
     475             : // X      D   IN   The given vector x of dimension n - 1
     476             : //            OUT  The vector v
     477             : // INCX   I   IN   The increment between elements of X, INCX .NE. 0
     478             : // TAU    D   OUT  The scalar tau
     479             : // SAFMIN D   IN   Safe minimum such that 1.0/SAFMIN does not
     480             : //                 overflow
     481         106 : int housg(int n, double *alpha, double *x, int incx, double *tau, double safmin)
     482             : {
     483         106 :   const double one = 1.0, zer = 0.0;
     484         106 :   int ix = 0, knt = 0, kx = 0, nm1 = 0;
     485         106 :   double a1 = 0.0, a2 = 0.0, beta = 0.0, rsafmn = 0.0, tmp = 0.0, xnorm = 0.0,
     486         106 :          xscal = 0.0;
     487             : 
     488             :   // H is defined as the identity whenever incx==0; implies don't iterate
     489             :   // through x
     490         106 :   if (incx == 0)
     491             :   {
     492           1 :     *tau = zer;
     493           1 :     return -2;
     494             :   }
     495             : 
     496             :   // H is defined as the identity whenever n<1
     497         105 :   if (n < 1)
     498             :   {
     499           1 :     *tau = zer;
     500           1 :     return -1;
     501             :   }
     502             : 
     503             :   // H is defined as the identity whenever n=1
     504         104 :   if (n == 1)
     505             :   {
     506           1 :     *tau = zer;
     507           1 :     return 0;
     508             :   }
     509             : 
     510             :   // Dimension of x
     511         103 :   nm1 = n - 1;
     512             :   // Norm of x
     513         103 :   xnorm = dnrm2(nm1, x, incx);
     514             : 
     515             :   // H is the identity whenever xnorm=0 with alpha=beta and tau=0
     516         103 :   if (xnorm == zer)
     517             :   {
     518           5 :     *tau = zer;
     519           5 :     return 0;
     520             :   }
     521             : 
     522             :   // General case
     523          98 :   kx = 1;
     524          98 :   if (incx < 0) kx = 1 - (n - 1) * incx;
     525             : 
     526             :   // Compute alpha, beta, tau, and xscal
     527          98 :   a1 = xnorm;
     528          98 :   a2 = fabs(*alpha);
     529          98 :   if (a1 < a2)
     530             :   {
     531          45 :     a1 = a2;
     532          45 :     a2 = xnorm;
     533             :   }
     534          98 :   if (a2 == zer)
     535             :   {
     536           2 :     beta = a1;
     537             :   }
     538             :   else
     539             :   {
     540          96 :     tmp = a1 / a2;
     541          96 :     beta = a2 * sqrt(one + tmp * tmp);
     542             :   }
     543          98 :   if (*alpha > zer) beta = -beta;
     544             : 
     545             :   // Test for loss of accuracy
     546          98 :   if (fabs(beta) >= safmin)
     547             :   {
     548          98 :     *tau = (beta - *alpha) / beta;
     549          98 :     xscal = one / (*alpha - beta);
     550          98 :     *alpha = beta;
     551             :   }
     552             :   else  // xnorm, beta may be inaccurate; scale x and recompute
     553             :   {
     554           0 :     rsafmn = one / safmin;
     555           0 :     knt = 0;
     556             :     do
     557             :     {
     558           0 :       knt = knt + 1;
     559           0 :       if (incx == 1)
     560             :       {
     561           0 :         for (int i = 1; i <= nm1; i++)
     562             :         {
     563           0 :           x(i) = rsafmn * x(i);
     564             :         }
     565             :       }
     566             :       else
     567             :       {
     568           0 :         ix = kx;
     569           0 :         for (int i = 1; i <= nm1; i++)
     570             :         {
     571           0 :           x(ix) = rsafmn * x(ix);
     572           0 :           ix = ix + incx;
     573             :         }
     574             :       }
     575           0 :       beta = beta * rsafmn;
     576           0 :       *alpha = (*alpha) * rsafmn;
     577           0 :     } while (fabs(beta) < safmin);
     578             : 
     579             :     // new beta satisfies safmin <= beta <= 1.0
     580           0 :     xnorm = dnrm2(nm1, x, incx);
     581           0 :     a1 = xnorm;
     582           0 :     a2 = fabs(*alpha);
     583           0 :     if (a1 < a2)
     584             :     {
     585           0 :       a1 = a2;
     586           0 :       a2 = xnorm;
     587             :     }
     588           0 :     if (a2 == zer)
     589             :     {
     590           0 :       beta = a1;
     591             :     }
     592             :     else
     593             :     {
     594           0 :       tmp = a1 / a2;
     595           0 :       beta = a2 * sqrt(one + tmp * tmp);
     596             :     }
     597           0 :     if (*alpha > zer) beta = -beta;
     598           0 :     *tau = (beta - *alpha) / beta;
     599           0 :     xscal = one / (*alpha - beta);
     600           0 :     *alpha = beta;
     601           0 :     for (int j = 1; j <= knt; j++)
     602             :     {
     603           0 :       *alpha = (*alpha) * safmin;
     604             :     }
     605             :   }
     606          98 :   if (incx == 1)
     607             :   {
     608         490 :     for (int i = 1; i <= nm1; i++)
     609             :     {
     610         392 :       x(i) = xscal * x(i);
     611             :     }
     612             :   }
     613             :   else
     614             :   {
     615           0 :     ix = kx;
     616           0 :     for (int i = 1; i <= nm1; i++)
     617             :     {
     618           0 :       x(ix) = xscal * x(ix);
     619           0 :       ix = ix + incx;
     620             :     }
     621             :   }
     622          98 :   return 0;
     623             : }
     624             : 
     625             : // Multiplies a given M x N matrix A from the (L)eft by an
     626             : // M-dimensional Householder reflector
     627             : //
     628             : //    H = I - tau*x*x',   H' * H = I,  x = ( 1 )
     629             : //                                         ( v )
     630             : //
     631             : // that is, overwrite A by the product H * A
     632             : //
     633             : // Variables in the calling sequence:
     634             : // ----------------------------------
     635             : // M     I   IN   The number of rows of A
     636             : // N     I   IN   The number of columns of A
     637             : // X     D   IN   The given vector x. x(1) = 1.0 is enforced
     638             : // INCX  I   IN   The increment between elements of X, INCX .NE. 0
     639             : // TAU   D   IN   The scalar tau
     640             : // A     D   IN   The given matrix of dimension M x N
     641             : //           OUT  The computed matrix product H * A
     642             : // LDA   I   IN   The leading dimension of the array A, LDA >= M
     643             : // IER   I   OUT  Error indicator
     644             : //                IER = 0  no error
     645             : //                IER = 1  input-data error
     646          85 : int housl(int m, int n, double *x, int incx, double tau, double *a, int lda,
     647             :           int *ier)
     648             : {
     649          85 :   const double zer = 0.0;
     650          85 :   int ix = 0, kx = 0;
     651          85 :   double sum = 0.0, tmp = 0.0;
     652             : 
     653          85 :   *ier = 0;
     654             : 
     655             :   // Valid data
     656          85 :   if ((m < 0) || (n < 0) || (incx == 0) || (lda < m))
     657             :   {
     658           4 :     *ier = 1;
     659           4 :     return 1;
     660             :   }
     661             : 
     662             :   // Quick return
     663          81 :   if ((m == 0) || (n == 0) || (tau == 0.0))
     664             :   {
     665           7 :     *ier = 0;
     666           7 :     return 0;
     667             :   }
     668             : 
     669          74 :   kx = 1;
     670          74 :   if (incx < 0) kx = 1 - (m - 1) * incx;
     671             : 
     672             :   // Compute w = A' * x and  A := A - tau * x * w'
     673             : 
     674         200 :   for (int j = 1; j <= n; j++)
     675             :   {
     676         126 :     sum = a(1, j);
     677         126 :     if (m > 1)
     678             :     {
     679         126 :       ix = kx;
     680         506 :       for (int i = 2; i <= m; i++)
     681             :       {
     682         380 :         ix += incx;
     683         380 :         sum += a(i, j) * x(ix);
     684             :       }
     685             :     }
     686         126 :     if (sum != zer)
     687             :     {
     688         120 :       tmp = -tau * sum;
     689         120 :       a(1, j) += tmp;
     690         120 :       if (m > 1)
     691             :       {
     692         120 :         ix = kx;
     693         484 :         for (int i = 2; i <= m; i++)
     694             :         {
     695         364 :           ix += incx;
     696         364 :           a(i, j) += x(ix) * tmp;
     697             :         }
     698             :       }
     699             :     }
     700             :   }
     701          74 :   return *ier;
     702             : }

Generated by: LCOV version 1.14