~ubuntu-branches/ubuntu/gutsy/blender/gutsy-security

« back to all changes in this revision

Viewing changes to intern/opennl/superlu/scolumn_bmod.c

  • Committer: Bazaar Package Importer
  • Author(s): Florian Ernst
  • Date: 2005-11-06 12:40:03 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051106124003-3pgs7tcg5rox96xg
Tags: 2.37a-1.1
* Non-maintainer upload.
* Split out parts of 01_SConstruct_debian.dpatch again: root_build_dir
  really needs to get adjusted before the clean target runs - closes: #333958,
  see #288882 for reference

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/*
 
3
 * -- SuperLU routine (version 3.0) --
 
4
 * Univ. of California Berkeley, Xerox Palo Alto Research Center,
 
5
 * and Lawrence Berkeley National Lab.
 
6
 * October 15, 2003
 
7
 *
 
8
 */
 
9
/*
 
10
  Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
 
11
 
 
12
  THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
 
13
  EXPRESSED OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
 
14
 
 
15
  Permission is hereby granted to use or copy this program for any
 
16
  purpose, provided the above notices are retained on all copies.
 
17
  Permission to modify the code and to distribute modified code is
 
18
  granted, provided the above notices are retained, and a notice that
 
19
  the code was modified is included with the above copyright notice.
 
20
*/
 
21
 
 
22
#include <stdio.h>
 
23
#include <stdlib.h>
 
24
#include "ssp_defs.h"
 
25
 
 
26
/* 
 
27
 * Function prototypes 
 
28
 */
 
29
void susolve(int, int, float*, float*);
 
30
void slsolve(int, int, float*, float*);
 
31
void smatvec(int, int, int, float*, float*, float*);
 
32
 
 
33
 
 
34
 
 
35
/* Return value:   0 - successful return
 
36
 *               > 0 - number of bytes allocated when run out of space
 
37
 */
 
38
int
 
39
scolumn_bmod (
 
40
             const int  jcol,     /* in */
 
41
             const int  nseg,     /* in */
 
42
             float     *dense,    /* in */
 
43
             float     *tempv,    /* working array */
 
44
             int        *segrep,  /* in */
 
45
             int        *repfnz,  /* in */
 
46
             int        fpanelc,  /* in -- first column in the current panel */
 
47
             GlobalLU_t *Glu,     /* modified */
 
48
             SuperLUStat_t *stat  /* output */
 
49
             )
 
50
{
 
51
/*
 
52
 * Purpose:
 
53
 * ========
 
54
 *    Performs numeric block updates (sup-col) in topological order.
 
55
 *    It features: col-col, 2cols-col, 3cols-col, and sup-col updates.
 
56
 *    Special processing on the supernodal portion of L\U[*,j]
 
57
 *
 
58
 */
 
59
#ifdef _CRAY
 
60
    _fcd ftcs1 = _cptofcd("L", strlen("L")),
 
61
         ftcs2 = _cptofcd("N", strlen("N")),
 
62
         ftcs3 = _cptofcd("U", strlen("U"));
 
63
#endif
 
64
 
 
65
#ifdef USE_VENDOR_BLAS
 
66
    int         incx = 1, incy = 1;
 
67
    float      alpha, beta;
 
68
#endif
 
69
    
 
70
    /* krep = representative of current k-th supernode
 
71
     * fsupc = first supernodal column
 
72
     * nsupc = no of columns in supernode
 
73
     * nsupr = no of rows in supernode (used as leading dimension)
 
74
     * luptr = location of supernodal LU-block in storage
 
75
     * kfnz = first nonz in the k-th supernodal segment
 
76
     * no_zeros = no of leading zeros in a supernodal U-segment
 
77
     */
 
78
    float       ukj, ukj1, ukj2;
 
79
    int          luptr, luptr1, luptr2;
 
80
    int          fsupc, nsupc, nsupr, segsze;
 
81
    int          nrow;    /* No of rows in the matrix of matrix-vector */
 
82
    int          jcolp1, jsupno, k, ksub, krep, krep_ind, ksupno;
 
83
    register int lptr, kfnz, isub, irow, i;
 
84
    register int no_zeros, new_next; 
 
85
    int          ufirst, nextlu;
 
86
    int          fst_col; /* First column within small LU update */
 
87
    int          d_fsupc; /* Distance between the first column of the current
 
88
                             panel and the first column of the current snode. */
 
89
    int          *xsup, *supno;
 
90
    int          *lsub, *xlsub;
 
91
    float       *lusup;
 
92
    int          *xlusup;
 
93
    int          nzlumax;
 
94
    float       *tempv1;
 
95
    float      zero = 0.0;
 
96
#ifdef USE_VENDOR_BLAS
 
97
    float      one = 1.0;
 
98
    float      none = -1.0;
 
99
#endif
 
100
    int          mem_error;
 
101
    flops_t      *ops = stat->ops;
 
102
 
 
103
    xsup    = Glu->xsup;
 
104
    supno   = Glu->supno;
 
105
    lsub    = Glu->lsub;
 
106
    xlsub   = Glu->xlsub;
 
107
    lusup   = Glu->lusup;
 
108
    xlusup  = Glu->xlusup;
 
109
    nzlumax = Glu->nzlumax;
 
110
    jcolp1 = jcol + 1;
 
111
    jsupno = supno[jcol];
 
112
    
 
113
    /* 
 
114
     * For each nonz supernode segment of U[*,j] in topological order 
 
115
     */
 
116
    k = nseg - 1;
 
117
    for (ksub = 0; ksub < nseg; ksub++) {
 
118
 
 
119
        krep = segrep[k];
 
120
        k--;
 
121
        ksupno = supno[krep];
 
122
        if ( jsupno != ksupno ) { /* Outside the rectangular supernode */
 
123
 
 
124
            fsupc = xsup[ksupno];
 
125
            fst_col = SUPERLU_MAX ( fsupc, fpanelc );
 
126
 
 
127
            /* Distance from the current supernode to the current panel; 
 
128
               d_fsupc=0 if fsupc > fpanelc. */
 
129
            d_fsupc = fst_col - fsupc; 
 
130
 
 
131
            luptr = xlusup[fst_col] + d_fsupc;
 
132
            lptr = xlsub[fsupc] + d_fsupc;
 
133
 
 
134
            kfnz = repfnz[krep];
 
135
            kfnz = SUPERLU_MAX ( kfnz, fpanelc );
 
136
 
 
137
            segsze = krep - kfnz + 1;
 
138
            nsupc = krep - fst_col + 1;
 
139
            nsupr = xlsub[fsupc+1] - xlsub[fsupc];      /* Leading dimension */
 
140
            nrow = nsupr - d_fsupc - nsupc;
 
141
            krep_ind = lptr + nsupc - 1;
 
142
 
 
143
            ops[TRSV] += segsze * (segsze - 1);
 
144
            ops[GEMV] += 2 * nrow * segsze;
 
145
 
 
146
 
 
147
            /* 
 
148
             * Case 1: Update U-segment of size 1 -- col-col update 
 
149
             */
 
150
            if ( segsze == 1 ) {
 
151
                ukj = dense[lsub[krep_ind]];
 
152
                luptr += nsupr*(nsupc-1) + nsupc;
 
153
 
 
154
                for (i = lptr + nsupc; i < xlsub[fsupc+1]; ++i) {
 
155
                    irow = lsub[i];
 
156
                    dense[irow] -=  ukj*lusup[luptr];
 
157
                    luptr++;
 
158
                }
 
159
 
 
160
            } else if ( segsze <= 3 ) {
 
161
                ukj = dense[lsub[krep_ind]];
 
162
                luptr += nsupr*(nsupc-1) + nsupc-1;
 
163
                ukj1 = dense[lsub[krep_ind - 1]];
 
164
                luptr1 = luptr - nsupr;
 
165
 
 
166
                if ( segsze == 2 ) { /* Case 2: 2cols-col update */
 
167
                    ukj -= ukj1 * lusup[luptr1];
 
168
                    dense[lsub[krep_ind]] = ukj;
 
169
                    for (i = lptr + nsupc; i < xlsub[fsupc+1]; ++i) {
 
170
                        irow = lsub[i];
 
171
                        luptr++;
 
172
                        luptr1++;
 
173
                        dense[irow] -= ( ukj*lusup[luptr]
 
174
                                        + ukj1*lusup[luptr1] );
 
175
                    }
 
176
                } else { /* Case 3: 3cols-col update */
 
177
                    ukj2 = dense[lsub[krep_ind - 2]];
 
178
                    luptr2 = luptr1 - nsupr;
 
179
                    ukj1 -= ukj2 * lusup[luptr2-1];
 
180
                    ukj = ukj - ukj1*lusup[luptr1] - ukj2*lusup[luptr2];
 
181
                    dense[lsub[krep_ind]] = ukj;
 
182
                    dense[lsub[krep_ind-1]] = ukj1;
 
183
                    for (i = lptr + nsupc; i < xlsub[fsupc+1]; ++i) {
 
184
                        irow = lsub[i];
 
185
                        luptr++;
 
186
                        luptr1++;
 
187
                        luptr2++;
 
188
                        dense[irow] -= ( ukj*lusup[luptr]
 
189
                             + ukj1*lusup[luptr1] + ukj2*lusup[luptr2] );
 
190
                    }
 
191
                }
 
192
 
 
193
 
 
194
 
 
195
            } else {
 
196
                /*
 
197
                 * Case: sup-col update
 
198
                 * Perform a triangular solve and block update,
 
199
                 * then scatter the result of sup-col update to dense
 
200
                 */
 
201
 
 
202
                no_zeros = kfnz - fst_col;
 
203
 
 
204
                /* Copy U[*,j] segment from dense[*] to tempv[*] */
 
205
                isub = lptr + no_zeros;
 
206
                for (i = 0; i < segsze; i++) {
 
207
                    irow = lsub[isub];
 
208
                    tempv[i] = dense[irow];
 
209
                    ++isub; 
 
210
                }
 
211
 
 
212
                /* Dense triangular solve -- start effective triangle */
 
213
                luptr += nsupr * no_zeros + no_zeros; 
 
214
                
 
215
#ifdef USE_VENDOR_BLAS
 
216
#ifdef _CRAY
 
217
                STRSV( ftcs1, ftcs2, ftcs3, &segsze, &lusup[luptr], 
 
218
                       &nsupr, tempv, &incx );
 
219
#else           
 
220
                strsv_( "L", "N", "U", &segsze, &lusup[luptr], 
 
221
                       &nsupr, tempv, &incx );
 
222
#endif          
 
223
                luptr += segsze;  /* Dense matrix-vector */
 
224
                tempv1 = &tempv[segsze];
 
225
                alpha = one;
 
226
                beta = zero;
 
227
#ifdef _CRAY
 
228
                SGEMV( ftcs2, &nrow, &segsze, &alpha, &lusup[luptr], 
 
229
                       &nsupr, tempv, &incx, &beta, tempv1, &incy );
 
230
#else
 
231
                sgemv_( "N", &nrow, &segsze, &alpha, &lusup[luptr], 
 
232
                       &nsupr, tempv, &incx, &beta, tempv1, &incy );
 
233
#endif
 
234
#else
 
235
                slsolve ( nsupr, segsze, &lusup[luptr], tempv );
 
236
 
 
237
                luptr += segsze;  /* Dense matrix-vector */
 
238
                tempv1 = &tempv[segsze];
 
239
                smatvec (nsupr, nrow , segsze, &lusup[luptr], tempv, tempv1);
 
240
#endif
 
241
                
 
242
                
 
243
                /* Scatter tempv[] into SPA dense[] as a temporary storage */
 
244
                isub = lptr + no_zeros;
 
245
                for (i = 0; i < segsze; i++) {
 
246
                    irow = lsub[isub];
 
247
                    dense[irow] = tempv[i];
 
248
                    tempv[i] = zero;
 
249
                    ++isub;
 
250
                }
 
251
 
 
252
                /* Scatter tempv1[] into SPA dense[] */
 
253
                for (i = 0; i < nrow; i++) {
 
254
                    irow = lsub[isub];
 
255
                    dense[irow] -= tempv1[i];
 
256
                    tempv1[i] = zero;
 
257
                    ++isub;
 
258
                }
 
259
            }
 
260
            
 
261
        } /* if jsupno ... */
 
262
 
 
263
    } /* for each segment... */
 
264
 
 
265
    /*
 
266
     *  Process the supernodal portion of L\U[*,j]
 
267
     */
 
268
    nextlu = xlusup[jcol];
 
269
    fsupc = xsup[jsupno];
 
270
 
 
271
    /* Copy the SPA dense into L\U[*,j] */
 
272
    new_next = nextlu + xlsub[fsupc+1] - xlsub[fsupc];
 
273
    while ( new_next > nzlumax ) {
 
274
        if ((mem_error = sLUMemXpand(jcol, nextlu, LUSUP, &nzlumax, Glu)))
 
275
            return (mem_error);
 
276
        lusup = Glu->lusup;
 
277
        lsub = Glu->lsub;
 
278
    }
 
279
 
 
280
    for (isub = xlsub[fsupc]; isub < xlsub[fsupc+1]; isub++) {
 
281
        irow = lsub[isub];
 
282
        lusup[nextlu] = dense[irow];
 
283
        dense[irow] = zero;
 
284
        ++nextlu;
 
285
    }
 
286
 
 
287
    xlusup[jcolp1] = nextlu;    /* Close L\U[*,jcol] */
 
288
 
 
289
    /* For more updates within the panel (also within the current supernode), 
 
290
     * should start from the first column of the panel, or the first column 
 
291
     * of the supernode, whichever is bigger. There are 2 cases:
 
292
     *    1) fsupc < fpanelc, then fst_col := fpanelc
 
293
     *    2) fsupc >= fpanelc, then fst_col := fsupc
 
294
     */
 
295
    fst_col = SUPERLU_MAX ( fsupc, fpanelc );
 
296
 
 
297
    if ( fst_col < jcol ) {
 
298
 
 
299
        /* Distance between the current supernode and the current panel.
 
300
           d_fsupc=0 if fsupc >= fpanelc. */
 
301
        d_fsupc = fst_col - fsupc;
 
302
 
 
303
        lptr = xlsub[fsupc] + d_fsupc;
 
304
        luptr = xlusup[fst_col] + d_fsupc;
 
305
        nsupr = xlsub[fsupc+1] - xlsub[fsupc];  /* Leading dimension */
 
306
        nsupc = jcol - fst_col; /* Excluding jcol */
 
307
        nrow = nsupr - d_fsupc - nsupc;
 
308
 
 
309
        /* Points to the beginning of jcol in snode L\U(jsupno) */
 
310
        ufirst = xlusup[jcol] + d_fsupc;        
 
311
 
 
312
        ops[TRSV] += nsupc * (nsupc - 1);
 
313
        ops[GEMV] += 2 * nrow * nsupc;
 
314
        
 
315
#ifdef USE_VENDOR_BLAS
 
316
#ifdef _CRAY
 
317
        STRSV( ftcs1, ftcs2, ftcs3, &nsupc, &lusup[luptr], 
 
318
               &nsupr, &lusup[ufirst], &incx );
 
319
#else
 
320
        strsv_( "L", "N", "U", &nsupc, &lusup[luptr], 
 
321
               &nsupr, &lusup[ufirst], &incx );
 
322
#endif
 
323
        
 
324
        alpha = none; beta = one; /* y := beta*y + alpha*A*x */
 
325
 
 
326
#ifdef _CRAY
 
327
        SGEMV( ftcs2, &nrow, &nsupc, &alpha, &lusup[luptr+nsupc], &nsupr,
 
328
               &lusup[ufirst], &incx, &beta, &lusup[ufirst+nsupc], &incy );
 
329
#else
 
330
        sgemv_( "N", &nrow, &nsupc, &alpha, &lusup[luptr+nsupc], &nsupr,
 
331
               &lusup[ufirst], &incx, &beta, &lusup[ufirst+nsupc], &incy );
 
332
#endif
 
333
#else
 
334
        slsolve ( nsupr, nsupc, &lusup[luptr], &lusup[ufirst] );
 
335
 
 
336
        smatvec ( nsupr, nrow, nsupc, &lusup[luptr+nsupc],
 
337
                &lusup[ufirst], tempv );
 
338
        
 
339
        /* Copy updates from tempv[*] into lusup[*] */
 
340
        isub = ufirst + nsupc;
 
341
        for (i = 0; i < nrow; i++) {
 
342
            lusup[isub] -= tempv[i];
 
343
            tempv[i] = 0.0;
 
344
            ++isub;
 
345
        }
 
346
 
 
347
#endif
 
348
        
 
349
        
 
350
    } /* if fst_col < jcol ... */ 
 
351
 
 
352
    return 0;
 
353
}