1 
2 /*! @file zlaqgs.c
3  * \brief Equlibrates a general sprase matrix
4  *
5  * <pre>
6  * -- SuperLU routine (version 2.0) --
7  * Univ. of California Berkeley, Xerox Palo Alto Research Center,
8  * and Lawrence Berkeley National Lab.
9  * November 15, 1997
10  *
11  * Modified from LAPACK routine ZLAQGE
12  * </pre>
13  */
14 /*
15  * File name:	zlaqgs.c
16  * History:     Modified from LAPACK routine ZLAQGE
17  */
18 #include <math.h>
19 #include "slu_zdefs.h"
20 
21 /*! \brief
22  *
23  * <pre>
24  *   Purpose
25  *   =======
26  *
27  *   ZLAQGS equilibrates a general sparse M by N matrix A using the row and
28  *   scaling factors in the vectors R and C.
29  *
30  *   See supermatrix.h for the definition of 'SuperMatrix' structure.
31  *
32  *   Arguments
33  *   =========
34  *
35  *   A       (input/output) SuperMatrix*
36  *           On exit, the equilibrated matrix.  See EQUED for the form of
37  *           the equilibrated matrix. The type of A can be:
38  *	    Stype = NC; Dtype = SLU_Z; Mtype = GE.
39  *
40  *   R       (input) double*, dimension (A->nrow)
41  *           The row scale factors for A.
42  *
43  *   C       (input) double*, dimension (A->ncol)
44  *           The column scale factors for A.
45  *
46  *   ROWCND  (input) double
47  *           Ratio of the smallest R(i) to the largest R(i).
48  *
49  *   COLCND  (input) double
50  *           Ratio of the smallest C(i) to the largest C(i).
51  *
52  *   AMAX    (input) double
53  *           Absolute value of largest matrix entry.
54  *
55  *   EQUED   (output) char*
56  *           Specifies the form of equilibration that was done.
57  *           = 'N':  No equilibration
58  *           = 'R':  Row equilibration, i.e., A has been premultiplied by
59  *                   diag(R).
60  *           = 'C':  Column equilibration, i.e., A has been postmultiplied
61  *                   by diag(C).
62  *           = 'B':  Both row and column equilibration, i.e., A has been
63  *                   replaced by diag(R) * A * diag(C).
64  *
65  *   Internal Parameters
66  *   ===================
67  *
68  *   THRESH is a threshold value used to decide if row or column scaling
69  *   should be done based on the ratio of the row or column scaling
70  *   factors.  If ROWCND < THRESH, row scaling is done, and if
71  *   COLCND < THRESH, column scaling is done.
72  *
73  *   LARGE and SMALL are threshold values used to decide if row scaling
74  *   should be done based on the absolute size of the largest matrix
75  *   element.  If AMAX > LARGE or AMAX < SMALL, row scaling is done.
76  *
77  *   =====================================================================
78  * </pre>
79  */
80 
81 void
zlaqgs(SuperMatrix * A,double * r,double * c,double rowcnd,double colcnd,double amax,char * equed)82 zlaqgs(SuperMatrix *A, double *r, double *c,
83 	double rowcnd, double colcnd, double amax, char *equed)
84 {
85 
86 
87 #define THRESH    (0.1)
88 
89     /* Local variables */
90     NCformat *Astore;
91     doublecomplex   *Aval;
92     int i, j, irow;
93     double large, small, cj;
94     double temp;
95 
96 
97     /* Quick return if possible */
98     if (A->nrow <= 0 || A->ncol <= 0) {
99 	*(unsigned char *)equed = 'N';
100 	return;
101     }
102 
103     Astore = A->Store;
104     Aval = Astore->nzval;
105 
106     /* Initialize LARGE and SMALL. */
107     small = dlamch_("Safe minimum") / dlamch_("Precision");
108     large = 1. / small;
109 
110     if (rowcnd >= THRESH && amax >= small && amax <= large) {
111 	if (colcnd >= THRESH)
112 	    *(unsigned char *)equed = 'N';
113 	else {
114 	    /* Column scaling */
115 	    for (j = 0; j < A->ncol; ++j) {
116 		cj = c[j];
117 		for (i = Astore->colptr[j]; i < Astore->colptr[j+1]; ++i) {
118 		    zd_mult(&Aval[i], &Aval[i], cj);
119                 }
120 	    }
121 	    *(unsigned char *)equed = 'C';
122 	}
123     } else if (colcnd >= THRESH) {
124 	/* Row scaling, no column scaling */
125 	for (j = 0; j < A->ncol; ++j)
126 	    for (i = Astore->colptr[j]; i < Astore->colptr[j+1]; ++i) {
127 		irow = Astore->rowind[i];
128 		zd_mult(&Aval[i], &Aval[i], r[irow]);
129 	    }
130 	*(unsigned char *)equed = 'R';
131     } else {
132 	/* Row and column scaling */
133 	for (j = 0; j < A->ncol; ++j) {
134 	    cj = c[j];
135 	    for (i = Astore->colptr[j]; i < Astore->colptr[j+1]; ++i) {
136 		irow = Astore->rowind[i];
137 		temp = cj * r[irow];
138 		zd_mult(&Aval[i], &Aval[i], temp);
139 	    }
140 	}
141 	*(unsigned char *)equed = 'B';
142     }
143 
144     return;
145 
146 } /* zlaqgs */
147 
148