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

« back to all changes in this revision

Viewing changes to intern/opennl/superlu/spanel_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 slsolve(int, int, float *, float *);
 
30
void smatvec(int, int, int, float *, float *, float *);
 
31
extern void scheck_tempv();
 
32
 
 
33
void
 
34
spanel_bmod (
 
35
            const int  m,          /* in - number of rows in the matrix */
 
36
            const int  w,          /* in */
 
37
            const int  jcol,       /* in */
 
38
            const int  nseg,       /* in */
 
39
            float     *dense,     /* out, of size n by w */
 
40
            float     *tempv,     /* working array */
 
41
            int        *segrep,    /* in */
 
42
            int        *repfnz,    /* in, of size n by w */
 
43
            GlobalLU_t *Glu,       /* modified */
 
44
            SuperLUStat_t *stat    /* output */
 
45
            )
 
46
{
 
47
/* 
 
48
 * Purpose
 
49
 * =======
 
50
 *
 
51
 *    Performs numeric block updates (sup-panel) in topological order.
 
52
 *    It features: col-col, 2cols-col, 3cols-col, and sup-col updates.
 
53
 *    Special processing on the supernodal portion of L\U[*,j]
 
54
 *
 
55
 *    Before entering this routine, the original nonzeros in the panel 
 
56
 *    were already copied into the spa[m,w].
 
57
 *
 
58
 *    Updated/Output parameters-
 
59
 *      dense[0:m-1,w]: L[*,j:j+w-1] and U[*,j:j+w-1] are returned 
 
60
 *      collectively in the m-by-w vector dense[*]. 
 
61
 *
 
62
 */
 
63
 
 
64
#ifdef USE_VENDOR_BLAS
 
65
#ifdef _CRAY
 
66
    _fcd ftcs1 = _cptofcd("L", strlen("L")),
 
67
         ftcs2 = _cptofcd("N", strlen("N")),
 
68
         ftcs3 = _cptofcd("U", strlen("U"));
 
69
#endif
 
70
    int          incx = 1, incy = 1;
 
71
    float       alpha, beta;
 
72
#endif
 
73
 
 
74
    register int k, ksub;
 
75
    int          fsupc, nsupc, nsupr, nrow;
 
76
    int          krep, krep_ind;
 
77
    float       ukj, ukj1, ukj2;
 
78
    int          luptr, luptr1, luptr2;
 
79
    int          segsze;
 
80
    int          block_nrow;  /* no of rows in a block row */
 
81
    register int lptr;        /* Points to the row subscripts of a supernode */
 
82
    int          kfnz, irow, no_zeros; 
 
83
    register int isub, isub1, i;
 
84
    register int jj;          /* Index through each column in the panel */
 
85
    int          *xsup, *supno;
 
86
    int          *lsub, *xlsub;
 
87
    float       *lusup;
 
88
    int          *xlusup;
 
89
    int          *repfnz_col; /* repfnz[] for a column in the panel */
 
90
    float       *dense_col;  /* dense[] for a column in the panel */
 
91
    float       *tempv1;             /* Used in 1-D update */
 
92
    float       *TriTmp, *MatvecTmp; /* used in 2-D update */
 
93
    float      zero = 0.0;
 
94
    register int ldaTmp;
 
95
    register int r_ind, r_hi;
 
96
    static   int first = 1, maxsuper, rowblk, colblk;
 
97
    flops_t  *ops = stat->ops;
 
98
    
 
99
    xsup    = Glu->xsup;
 
100
    supno   = Glu->supno;
 
101
    lsub    = Glu->lsub;
 
102
    xlsub   = Glu->xlsub;
 
103
    lusup   = Glu->lusup;
 
104
    xlusup  = Glu->xlusup;
 
105
    
 
106
    if ( first ) {
 
107
        maxsuper = sp_ienv(3);
 
108
        rowblk   = sp_ienv(4);
 
109
        colblk   = sp_ienv(5);
 
110
        first = 0;
 
111
    }
 
112
    ldaTmp = maxsuper + rowblk;
 
113
 
 
114
    /* 
 
115
     * For each nonz supernode segment of U[*,j] in topological order 
 
116
     */
 
117
    k = nseg - 1;
 
118
    for (ksub = 0; ksub < nseg; ksub++) { /* for each updating supernode */
 
119
 
 
120
        /* krep = representative of current k-th supernode
 
121
         * fsupc = first supernodal column
 
122
         * nsupc = no of columns in a supernode
 
123
         * nsupr = no of rows in a supernode
 
124
         */
 
125
        krep = segrep[k--];
 
126
        fsupc = xsup[supno[krep]];
 
127
        nsupc = krep - fsupc + 1;
 
128
        nsupr = xlsub[fsupc+1] - xlsub[fsupc];
 
129
        nrow = nsupr - nsupc;
 
130
        lptr = xlsub[fsupc];
 
131
        krep_ind = lptr + nsupc - 1;
 
132
 
 
133
        repfnz_col = repfnz;
 
134
        dense_col = dense;
 
135
        
 
136
        if ( nsupc >= colblk && nrow > rowblk ) { /* 2-D block update */
 
137
 
 
138
            TriTmp = tempv;
 
139
        
 
140
            /* Sequence through each column in panel -- triangular solves */
 
141
            for (jj = jcol; jj < jcol + w; jj++,
 
142
                 repfnz_col += m, dense_col += m, TriTmp += ldaTmp ) {
 
143
 
 
144
                kfnz = repfnz_col[krep];
 
145
                if ( kfnz == EMPTY ) continue;  /* Skip any zero segment */
 
146
            
 
147
                segsze = krep - kfnz + 1;
 
148
                luptr = xlusup[fsupc];
 
149
 
 
150
                ops[TRSV] += segsze * (segsze - 1);
 
151
                ops[GEMV] += 2 * nrow * segsze;
 
152
        
 
153
                /* Case 1: Update U-segment of size 1 -- col-col update */
 
154
                if ( segsze == 1 ) {
 
155
                    ukj = dense_col[lsub[krep_ind]];
 
156
                    luptr += nsupr*(nsupc-1) + nsupc;
 
157
 
 
158
                    for (i = lptr + nsupc; i < xlsub[fsupc+1]; i++) {
 
159
                        irow = lsub[i];
 
160
                        dense_col[irow] -= ukj * lusup[luptr];
 
161
                        ++luptr;
 
162
                    }
 
163
 
 
164
                } else if ( segsze <= 3 ) {
 
165
                    ukj = dense_col[lsub[krep_ind]];
 
166
                    ukj1 = dense_col[lsub[krep_ind - 1]];
 
167
                    luptr += nsupr*(nsupc-1) + nsupc-1;
 
168
                    luptr1 = luptr - nsupr;
 
169
 
 
170
                    if ( segsze == 2 ) {
 
171
                        ukj -= ukj1 * lusup[luptr1];
 
172
                        dense_col[lsub[krep_ind]] = ukj;
 
173
                        for (i = lptr + nsupc; i < xlsub[fsupc+1]; ++i) {
 
174
                            irow = lsub[i];
 
175
                            luptr++; luptr1++;
 
176
                            dense_col[irow] -= (ukj*lusup[luptr]
 
177
                                                + ukj1*lusup[luptr1]);
 
178
                        }
 
179
                    } else {
 
180
                        ukj2 = dense_col[lsub[krep_ind - 2]];
 
181
                        luptr2 = luptr1 - nsupr;
 
182
                        ukj1 -= ukj2 * lusup[luptr2-1];
 
183
                        ukj = ukj - ukj1*lusup[luptr1] - ukj2*lusup[luptr2];
 
184
                        dense_col[lsub[krep_ind]] = ukj;
 
185
                        dense_col[lsub[krep_ind-1]] = ukj1;
 
186
                        for (i = lptr + nsupc; i < xlsub[fsupc+1]; ++i) {
 
187
                            irow = lsub[i];
 
188
                            luptr++; luptr1++; luptr2++;
 
189
                            dense_col[irow] -= ( ukj*lusup[luptr]
 
190
                             + ukj1*lusup[luptr1] + ukj2*lusup[luptr2] );
 
191
                        }
 
192
                    }
 
193
 
 
194
                } else  {       /* segsze >= 4 */
 
195
                    
 
196
                    /* Copy U[*,j] segment from dense[*] to TriTmp[*], which
 
197
                       holds the result of triangular solves.    */
 
198
                    no_zeros = kfnz - fsupc;
 
199
                    isub = lptr + no_zeros;
 
200
                    for (i = 0; i < segsze; ++i) {
 
201
                        irow = lsub[isub];
 
202
                        TriTmp[i] = dense_col[irow]; /* Gather */
 
203
                        ++isub;
 
204
                    }
 
205
                    
 
206
                    /* start effective triangle */
 
207
                    luptr += nsupr * no_zeros + no_zeros;
 
208
 
 
209
#ifdef USE_VENDOR_BLAS
 
210
#ifdef _CRAY
 
211
                    STRSV( ftcs1, ftcs2, ftcs3, &segsze, &lusup[luptr], 
 
212
                           &nsupr, TriTmp, &incx );
 
213
#else
 
214
                    strsv_( "L", "N", "U", &segsze, &lusup[luptr], 
 
215
                           &nsupr, TriTmp, &incx );
 
216
#endif
 
217
#else           
 
218
                    slsolve ( nsupr, segsze, &lusup[luptr], TriTmp );
 
219
#endif
 
220
                    
 
221
 
 
222
                } /* else ... */
 
223
            
 
224
            }  /* for jj ... end tri-solves */
 
225
 
 
226
            /* Block row updates; push all the way into dense[*] block */
 
227
            for ( r_ind = 0; r_ind < nrow; r_ind += rowblk ) {
 
228
                
 
229
                r_hi = SUPERLU_MIN(nrow, r_ind + rowblk);
 
230
                block_nrow = SUPERLU_MIN(rowblk, r_hi - r_ind);
 
231
                luptr = xlusup[fsupc] + nsupc + r_ind;
 
232
                isub1 = lptr + nsupc + r_ind;
 
233
                
 
234
                repfnz_col = repfnz;
 
235
                TriTmp = tempv;
 
236
                dense_col = dense;
 
237
                
 
238
                /* Sequence through each column in panel -- matrix-vector */
 
239
                for (jj = jcol; jj < jcol + w; jj++,
 
240
                     repfnz_col += m, dense_col += m, TriTmp += ldaTmp) {
 
241
                    
 
242
                    kfnz = repfnz_col[krep];
 
243
                    if ( kfnz == EMPTY ) continue; /* Skip any zero segment */
 
244
                    
 
245
                    segsze = krep - kfnz + 1;
 
246
                    if ( segsze <= 3 ) continue;   /* skip unrolled cases */
 
247
                    
 
248
                    /* Perform a block update, and scatter the result of
 
249
                       matrix-vector to dense[].                 */
 
250
                    no_zeros = kfnz - fsupc;
 
251
                    luptr1 = luptr + nsupr * no_zeros;
 
252
                    MatvecTmp = &TriTmp[maxsuper];
 
253
                    
 
254
#ifdef USE_VENDOR_BLAS
 
255
                    alpha = one; 
 
256
                    beta = zero;
 
257
#ifdef _CRAY
 
258
                    SGEMV(ftcs2, &block_nrow, &segsze, &alpha, &lusup[luptr1], 
 
259
                           &nsupr, TriTmp, &incx, &beta, MatvecTmp, &incy);
 
260
#else
 
261
                    sgemv_("N", &block_nrow, &segsze, &alpha, &lusup[luptr1], 
 
262
                           &nsupr, TriTmp, &incx, &beta, MatvecTmp, &incy);
 
263
#endif
 
264
#else
 
265
                    smatvec(nsupr, block_nrow, segsze, &lusup[luptr1],
 
266
                           TriTmp, MatvecTmp);
 
267
#endif
 
268
                    
 
269
                    /* Scatter MatvecTmp[*] into SPA dense[*] temporarily
 
270
                     * such that MatvecTmp[*] can be re-used for the
 
271
                     * the next blok row update. dense[] will be copied into 
 
272
                     * global store after the whole panel has been finished.
 
273
                     */
 
274
                    isub = isub1;
 
275
                    for (i = 0; i < block_nrow; i++) {
 
276
                        irow = lsub[isub];
 
277
                        dense_col[irow] -= MatvecTmp[i];
 
278
                        MatvecTmp[i] = zero;
 
279
                        ++isub;
 
280
                    }
 
281
                    
 
282
                } /* for jj ... */
 
283
                
 
284
            } /* for each block row ... */
 
285
            
 
286
            /* Scatter the triangular solves into SPA dense[*] */
 
287
            repfnz_col = repfnz;
 
288
            TriTmp = tempv;
 
289
            dense_col = dense;
 
290
            
 
291
            for (jj = jcol; jj < jcol + w; jj++,
 
292
                 repfnz_col += m, dense_col += m, TriTmp += ldaTmp) {
 
293
                kfnz = repfnz_col[krep];
 
294
                if ( kfnz == EMPTY ) continue; /* Skip any zero segment */
 
295
                
 
296
                segsze = krep - kfnz + 1;
 
297
                if ( segsze <= 3 ) continue; /* skip unrolled cases */
 
298
                
 
299
                no_zeros = kfnz - fsupc;                
 
300
                isub = lptr + no_zeros;
 
301
                for (i = 0; i < segsze; i++) {
 
302
                    irow = lsub[isub];
 
303
                    dense_col[irow] = TriTmp[i];
 
304
                    TriTmp[i] = zero;
 
305
                    ++isub;
 
306
                }
 
307
                
 
308
            } /* for jj ... */
 
309
            
 
310
        } else { /* 1-D block modification */
 
311
            
 
312
            
 
313
            /* Sequence through each column in the panel */
 
314
            for (jj = jcol; jj < jcol + w; jj++,
 
315
                 repfnz_col += m, dense_col += m) {
 
316
                
 
317
                kfnz = repfnz_col[krep];
 
318
                if ( kfnz == EMPTY ) continue;  /* Skip any zero segment */
 
319
                
 
320
                segsze = krep - kfnz + 1;
 
321
                luptr = xlusup[fsupc];
 
322
 
 
323
                ops[TRSV] += segsze * (segsze - 1);
 
324
                ops[GEMV] += 2 * nrow * segsze;
 
325
                
 
326
                /* Case 1: Update U-segment of size 1 -- col-col update */
 
327
                if ( segsze == 1 ) {
 
328
                    ukj = dense_col[lsub[krep_ind]];
 
329
                    luptr += nsupr*(nsupc-1) + nsupc;
 
330
 
 
331
                    for (i = lptr + nsupc; i < xlsub[fsupc+1]; i++) {
 
332
                        irow = lsub[i];
 
333
                        dense_col[irow] -= ukj * lusup[luptr];
 
334
                        ++luptr;
 
335
                    }
 
336
 
 
337
                } else if ( segsze <= 3 ) {
 
338
                    ukj = dense_col[lsub[krep_ind]];
 
339
                    luptr += nsupr*(nsupc-1) + nsupc-1;
 
340
                    ukj1 = dense_col[lsub[krep_ind - 1]];
 
341
                    luptr1 = luptr - nsupr;
 
342
 
 
343
                    if ( segsze == 2 ) {
 
344
                        ukj -= ukj1 * lusup[luptr1];
 
345
                        dense_col[lsub[krep_ind]] = ukj;
 
346
                        for (i = lptr + nsupc; i < xlsub[fsupc+1]; ++i) {
 
347
                            irow = lsub[i];
 
348
                            ++luptr;  ++luptr1;
 
349
                            dense_col[irow] -= (ukj*lusup[luptr]
 
350
                                                + ukj1*lusup[luptr1]);
 
351
                        }
 
352
                    } else {
 
353
                        ukj2 = dense_col[lsub[krep_ind - 2]];
 
354
                        luptr2 = luptr1 - nsupr;
 
355
                        ukj1 -= ukj2 * lusup[luptr2-1];
 
356
                        ukj = ukj - ukj1*lusup[luptr1] - ukj2*lusup[luptr2];
 
357
                        dense_col[lsub[krep_ind]] = ukj;
 
358
                        dense_col[lsub[krep_ind-1]] = ukj1;
 
359
                        for (i = lptr + nsupc; i < xlsub[fsupc+1]; ++i) {
 
360
                            irow = lsub[i];
 
361
                            ++luptr; ++luptr1; ++luptr2;
 
362
                            dense_col[irow] -= ( ukj*lusup[luptr]
 
363
                             + ukj1*lusup[luptr1] + ukj2*lusup[luptr2] );
 
364
                        }
 
365
                    }
 
366
 
 
367
                } else  { /* segsze >= 4 */
 
368
                    /* 
 
369
                     * Perform a triangular solve and block update,
 
370
                     * then scatter the result of sup-col update to dense[].
 
371
                     */
 
372
                    no_zeros = kfnz - fsupc;
 
373
                    
 
374
                    /* Copy U[*,j] segment from dense[*] to tempv[*]: 
 
375
                     *    The result of triangular solve is in tempv[*];
 
376
                     *    The result of matrix vector update is in dense_col[*]
 
377
                     */
 
378
                    isub = lptr + no_zeros;
 
379
                    for (i = 0; i < segsze; ++i) {
 
380
                        irow = lsub[isub];
 
381
                        tempv[i] = dense_col[irow]; /* Gather */
 
382
                        ++isub;
 
383
                    }
 
384
                    
 
385
                    /* start effective triangle */
 
386
                    luptr += nsupr * no_zeros + no_zeros;
 
387
                    
 
388
#ifdef USE_VENDOR_BLAS
 
389
#ifdef _CRAY
 
390
                    STRSV( ftcs1, ftcs2, ftcs3, &segsze, &lusup[luptr], 
 
391
                           &nsupr, tempv, &incx );
 
392
#else
 
393
                    strsv_( "L", "N", "U", &segsze, &lusup[luptr], 
 
394
                           &nsupr, tempv, &incx );
 
395
#endif
 
396
                    
 
397
                    luptr += segsze;    /* Dense matrix-vector */
 
398
                    tempv1 = &tempv[segsze];
 
399
                    alpha = one;
 
400
                    beta = zero;
 
401
#ifdef _CRAY
 
402
                    SGEMV( ftcs2, &nrow, &segsze, &alpha, &lusup[luptr], 
 
403
                           &nsupr, tempv, &incx, &beta, tempv1, &incy );
 
404
#else
 
405
                    sgemv_( "N", &nrow, &segsze, &alpha, &lusup[luptr], 
 
406
                           &nsupr, tempv, &incx, &beta, tempv1, &incy );
 
407
#endif
 
408
#else
 
409
                    slsolve ( nsupr, segsze, &lusup[luptr], tempv );
 
410
                    
 
411
                    luptr += segsze;        /* Dense matrix-vector */
 
412
                    tempv1 = &tempv[segsze];
 
413
                    smatvec (nsupr, nrow, segsze, &lusup[luptr], tempv, tempv1);
 
414
#endif
 
415
                    
 
416
                    /* Scatter tempv[*] into SPA dense[*] temporarily, such
 
417
                     * that tempv[*] can be used for the triangular solve of
 
418
                     * the next column of the panel. They will be copied into 
 
419
                     * ucol[*] after the whole panel has been finished.
 
420
                     */
 
421
                    isub = lptr + no_zeros;
 
422
                    for (i = 0; i < segsze; i++) {
 
423
                        irow = lsub[isub];
 
424
                        dense_col[irow] = tempv[i];
 
425
                        tempv[i] = zero;
 
426
                        isub++;
 
427
                    }
 
428
                    
 
429
                    /* Scatter the update from tempv1[*] into SPA dense[*] */
 
430
                    /* Start dense rectangular L */
 
431
                    for (i = 0; i < nrow; i++) {
 
432
                        irow = lsub[isub];
 
433
                        dense_col[irow] -= tempv1[i];
 
434
                        tempv1[i] = zero;
 
435
                        ++isub; 
 
436
                    }
 
437
                    
 
438
                } /* else segsze>=4 ... */
 
439
                
 
440
            } /* for each column in the panel... */
 
441
            
 
442
        } /* else 1-D update ... */
 
443
 
 
444
    } /* for each updating supernode ... */
 
445
 
 
446
}
 
447
 
 
448
 
 
449