1 
2 /*! @file dmemory.c
3  * \brief Memory details
4  *
5  * <pre>
6  * -- SuperLU routine (version 3.0) --
7  * Univ. of California Berkeley, Xerox Palo Alto Research Center,
8  * and Lawrence Berkeley National Lab.
9  * October 15, 2003
10  * </pre>
11  */
12 #include "slu_ddefs.h"
13 
14 /* Constants */
15 #define NO_MEMTYPE  4      /* 0: lusup;
16 			      1: ucol;
17 			      2: lsub;
18 			      3: usub */
19 #define GluIntArray(n)   (5 * (n) + 5)
20 
21 /* Internal prototypes */
22 void  *dexpand (int *, MemType,int, int, GlobalLU_t *);
23 int   dLUWorkInit (int, int, int, int **, double **, LU_space_t);
24 void  copy_mem_double (int, void *, void *);
25 void  dStackCompress (GlobalLU_t *);
26 void  dSetupSpace (void *, int, LU_space_t *);
27 void  *duser_malloc (int, int);
28 void  duser_free (int, int);
29 
30 /* External prototypes (in memory.c - prec-indep) */
31 extern void    copy_mem_int    (int, void *, void *);
32 extern void    user_bcopy      (char *, char *, int);
33 
34 /*! \brief Headers for 4 types of dynamatically managed memory */
35 typedef struct e_node {
36     int size;      /* length of the memory that has been used */
37     void *mem;     /* pointer to the new malloc'd store */
38 } ExpHeader;
39 
40 typedef struct {
41     int  size;
42     int  used;
43     int  top1;  /* grow upward, relative to &array[0] */
44     int  top2;  /* grow downward */
45     void *array;
46 } LU_stack_t;
47 
48 /* Variables local to this file */
49 static ExpHeader *expanders = 0; /* Array of pointers to 4 types of memory */
50 static LU_stack_t stack;
51 static int no_expand;
52 
53 /* Macros to manipulate stack */
54 #define StackFull(x)         ( x + stack.used >= stack.size )
55 #define NotDoubleAlign(addr) ( (long int)addr & 7 )
56 #define DoubleAlign(addr)    ( ((long int)addr + 7) & ~7L )
57 #define TempSpace(m, w)      ( (2*w + 4 + NO_MARKER) * m * sizeof(int) + \
58 			      (w + 1) * m * sizeof(double) )
59 #define Reduce(alpha)        ((alpha + 1) / 2)  /* i.e. (alpha-1)/2 + 1 */
60 
61 
62 
63 
64 /*! \brief Setup the memory model to be used for factorization.
65  *
66  *    lwork = 0: use system malloc;
67  *    lwork > 0: use user-supplied work[] space.
68  */
dSetupSpace(void * work,int lwork,LU_space_t * MemModel)69 void dSetupSpace(void *work, int lwork, LU_space_t *MemModel)
70 {
71     if ( lwork == 0 ) {
72 	*MemModel = SYSTEM; /* malloc/free */
73     } else if ( lwork > 0 ) {
74 	*MemModel = USER;   /* user provided space */
75 	stack.used = 0;
76 	stack.top1 = 0;
77 	stack.top2 = (lwork/4)*4; /* must be word addressable */
78 	stack.size = stack.top2;
79 	stack.array = (void *) work;
80     }
81 }
82 
83 
84 
duser_malloc(int bytes,int which_end)85 void *duser_malloc(int bytes, int which_end)
86 {
87     void *buf;
88 
89     if ( StackFull(bytes) ) return (NULL);
90 
91     if ( which_end == HEAD ) {
92 	buf = (char*) stack.array + stack.top1;
93 	stack.top1 += bytes;
94     } else {
95 	stack.top2 -= bytes;
96 	buf = (char*) stack.array + stack.top2;
97     }
98 
99     stack.used += bytes;
100     return buf;
101 }
102 
103 
duser_free(int bytes,int which_end)104 void duser_free(int bytes, int which_end)
105 {
106     if ( which_end == HEAD ) {
107 	stack.top1 -= bytes;
108     } else {
109 	stack.top2 += bytes;
110     }
111     stack.used -= bytes;
112 }
113 
114 
115 
116 /*! \brief
117  *
118  * <pre>
119  * mem_usage consists of the following fields:
120  *    - for_lu (float)
121  *      The amount of space used in bytes for the L\U data structures.
122  *    - total_needed (float)
123  *      The amount of space needed in bytes to perform factorization.
124  *    - expansions (int)
125  *      Number of memory expansions during the LU factorization.
126  * </pre>
127  */
dQuerySpace(SuperMatrix * L,SuperMatrix * U,mem_usage_t * mem_usage)128 int dQuerySpace(SuperMatrix *L, SuperMatrix *U, mem_usage_t *mem_usage)
129 {
130     SCformat *Lstore;
131     NCformat *Ustore;
132     register int n, iword, dword, panel_size = sp_ienv(1);
133 
134     Lstore = L->Store;
135     Ustore = U->Store;
136     n = L->ncol;
137     iword = sizeof(int);
138     dword = sizeof(double);
139 
140     /* For LU factors */
141     mem_usage->for_lu = (float)( (4*n + 3) * iword + Lstore->nzval_colptr[n] *
142 				 dword + Lstore->rowind_colptr[n] * iword );
143     mem_usage->for_lu += (float)( (n + 1) * iword +
144 				 Ustore->colptr[n] * (dword + iword) );
145 
146     /* Working storage to support factorization */
147     mem_usage->total_needed = mem_usage->for_lu +
148 	(float)( (2 * panel_size + 4 + NO_MARKER) * n * iword +
149 		(panel_size + 1) * n * dword );
150 
151     mem_usage->expansions = --no_expand;
152 
153     return 0;
154 } /* dQuerySpace */
155 
156 /*! \brief Allocate storage for the data structures common to all factor routines.
157  *
158  * <pre>
159  * For those unpredictable size, make a guess as FILL * nnz(A).
160  * Return value:
161  *     If lwork = -1, return the estimated amount of space required, plus n;
162  *     otherwise, return the amount of space actually allocated when
163  *     memory allocation failure occurred.
164  * </pre>
165  */
166 int
dLUMemInit(fact_t fact,void * work,int lwork,int m,int n,int annz,int panel_size,SuperMatrix * L,SuperMatrix * U,GlobalLU_t * Glu,int ** iwork,double ** dwork)167 dLUMemInit(fact_t fact, void *work, int lwork, int m, int n, int annz,
168 	  int panel_size, SuperMatrix *L, SuperMatrix *U, GlobalLU_t *Glu,
169 	  int **iwork, double **dwork)
170 {
171     int      info, iword, dword;
172     SCformat *Lstore;
173     NCformat *Ustore;
174     int      *xsup, *supno;
175     int      *lsub, *xlsub;
176     double   *lusup;
177     int      *xlusup;
178     double   *ucol;
179     int      *usub, *xusub;
180     int      nzlmax, nzumax, nzlumax;
181     int      FILL = sp_ienv(6);
182 
183     Glu->n    = n;
184     no_expand = 0;
185     iword     = sizeof(int);
186     dword     = sizeof(double);
187 
188     if ( !expanders )
189         expanders = (ExpHeader*)SUPERLU_MALLOC(NO_MEMTYPE * sizeof(ExpHeader));
190     if ( !expanders ) ABORT("SUPERLU_MALLOC fails for expanders");
191 
192     if ( fact != SamePattern_SameRowPerm ) {
193 	/* Guess for L\U factors */
194 	nzumax = nzlumax = FILL * annz;
195 	nzlmax = SUPERLU_MAX(1, FILL/4.) * annz;
196 
197 	if ( lwork == -1 ) {
198 	    return ( GluIntArray(n) * iword + TempSpace(m, panel_size)
199 		    + (nzlmax+nzumax)*iword + (nzlumax+nzumax)*dword + n );
200         } else {
201 	    dSetupSpace(work, lwork, &Glu->MemModel);
202 	}
203 
204 #if ( PRNTlevel >= 1 )
205 	printf("dLUMemInit() called: FILL %ld, nzlmax %ld, nzumax %ld\n",
206 	       FILL, nzlmax, nzumax);
207 	fflush(stdout);
208 #endif
209 
210 	/* Integer pointers for L\U factors */
211 	if ( Glu->MemModel == SYSTEM ) {
212 	    xsup   = intMalloc(n+1);
213 	    supno  = intMalloc(n+1);
214 	    xlsub  = intMalloc(n+1);
215 	    xlusup = intMalloc(n+1);
216 	    xusub  = intMalloc(n+1);
217 	} else {
218 	    xsup   = (int *)duser_malloc((n+1) * iword, HEAD);
219 	    supno  = (int *)duser_malloc((n+1) * iword, HEAD);
220 	    xlsub  = (int *)duser_malloc((n+1) * iword, HEAD);
221 	    xlusup = (int *)duser_malloc((n+1) * iword, HEAD);
222 	    xusub  = (int *)duser_malloc((n+1) * iword, HEAD);
223 	}
224 
225 	lusup = (double *) dexpand( &nzlumax, LUSUP, 0, 0, Glu );
226 	ucol  = (double *) dexpand( &nzumax, UCOL, 0, 0, Glu );
227 	lsub  = (int *)    dexpand( &nzlmax, LSUB, 0, 0, Glu );
228 	usub  = (int *)    dexpand( &nzumax, USUB, 0, 1, Glu );
229 
230 	while ( !lusup || !ucol || !lsub || !usub ) {
231 	    if ( Glu->MemModel == SYSTEM ) {
232 		SUPERLU_FREE(lusup);
233 		SUPERLU_FREE(ucol);
234 		SUPERLU_FREE(lsub);
235 		SUPERLU_FREE(usub);
236 	    } else {
237 		duser_free((nzlumax+nzumax)*dword+(nzlmax+nzumax)*iword, HEAD);
238 	    }
239 	    nzlumax /= 2;
240 	    nzumax /= 2;
241 	    nzlmax /= 2;
242 	    if ( nzlumax < annz ) {
243 		printf("Not enough memory to perform factorization.\n");
244 		return (dmemory_usage(nzlmax, nzumax, nzlumax, n) + n);
245 	    }
246 #if ( PRNTlevel >= 1)
247 	    printf("dLUMemInit() reduce size: nzlmax %ld, nzumax %ld\n",
248 		   nzlmax, nzumax);
249 	    fflush(stdout);
250 #endif
251 	    lusup = (double *) dexpand( &nzlumax, LUSUP, 0, 0, Glu );
252 	    ucol  = (double *) dexpand( &nzumax, UCOL, 0, 0, Glu );
253 	    lsub  = (int *)    dexpand( &nzlmax, LSUB, 0, 0, Glu );
254 	    usub  = (int *)    dexpand( &nzumax, USUB, 0, 1, Glu );
255 	}
256 
257     } else {
258 	/* fact == SamePattern_SameRowPerm */
259 	Lstore   = L->Store;
260 	Ustore   = U->Store;
261 	xsup     = Lstore->sup_to_col;
262 	supno    = Lstore->col_to_sup;
263 	xlsub    = Lstore->rowind_colptr;
264 	xlusup   = Lstore->nzval_colptr;
265 	xusub    = Ustore->colptr;
266 	nzlmax   = Glu->nzlmax;    /* max from previous factorization */
267 	nzumax   = Glu->nzumax;
268 	nzlumax  = Glu->nzlumax;
269 
270 	if ( lwork == -1 ) {
271 	    return ( GluIntArray(n) * iword + TempSpace(m, panel_size)
272 		    + (nzlmax+nzumax)*iword + (nzlumax+nzumax)*dword + n );
273         } else if ( lwork == 0 ) {
274 	    Glu->MemModel = SYSTEM;
275 	} else {
276 	    Glu->MemModel = USER;
277 	    stack.top2 = (lwork/4)*4; /* must be word-addressable */
278 	    stack.size = stack.top2;
279 	}
280 
281 	lsub  = expanders[LSUB].mem  = Lstore->rowind;
282 	lusup = expanders[LUSUP].mem = Lstore->nzval;
283 	usub  = expanders[USUB].mem  = Ustore->rowind;
284 	ucol  = expanders[UCOL].mem  = Ustore->nzval;;
285 	expanders[LSUB].size         = nzlmax;
286 	expanders[LUSUP].size        = nzlumax;
287 	expanders[USUB].size         = nzumax;
288 	expanders[UCOL].size         = nzumax;
289     }
290 
291     Glu->xsup    = xsup;
292     Glu->supno   = supno;
293     Glu->lsub    = lsub;
294     Glu->xlsub   = xlsub;
295     Glu->lusup   = lusup;
296     Glu->xlusup  = xlusup;
297     Glu->ucol    = ucol;
298     Glu->usub    = usub;
299     Glu->xusub   = xusub;
300     Glu->nzlmax  = nzlmax;
301     Glu->nzumax  = nzumax;
302     Glu->nzlumax = nzlumax;
303 
304     info = dLUWorkInit(m, n, panel_size, iwork, dwork, Glu->MemModel);
305     if ( info )
306 	return ( info + dmemory_usage(nzlmax, nzumax, nzlumax, n) + n);
307 
308     ++no_expand;
309     return 0;
310 
311 } /* dLUMemInit */
312 
313 /*! \brief Allocate known working storage. Returns 0 if success, otherwise
314    returns the number of bytes allocated so far when failure occurred. */
315 int
dLUWorkInit(int m,int n,int panel_size,int ** iworkptr,double ** dworkptr,LU_space_t MemModel)316 dLUWorkInit(int m, int n, int panel_size, int **iworkptr,
317             double **dworkptr, LU_space_t MemModel)
318 {
319     int    isize, dsize, extra;
320     double *old_ptr;
321     int    maxsuper = sp_ienv(3),
322            rowblk   = sp_ienv(4);
323 
324     isize = ( (2 * panel_size + 3 + NO_MARKER ) * m + n ) * sizeof(int);
325     dsize = (m * panel_size +
326 	     NUM_TEMPV(m,panel_size,maxsuper,rowblk)) * sizeof(double);
327 
328     if ( MemModel == SYSTEM )
329 	*iworkptr = (int *) intCalloc(isize/sizeof(int));
330     else
331 	*iworkptr = (int *) duser_malloc(isize, TAIL);
332     if ( ! *iworkptr ) {
333 	fprintf(stderr, "dLUWorkInit: malloc fails for local iworkptr[]\n");
334 	return (isize + n);
335     }
336 
337     if ( MemModel == SYSTEM )
338 	*dworkptr = (double *) SUPERLU_MALLOC(dsize);
339     else {
340 	*dworkptr = (double *) duser_malloc(dsize, TAIL);
341 	if ( NotDoubleAlign(*dworkptr) ) {
342 	    old_ptr = *dworkptr;
343 	    *dworkptr = (double*) DoubleAlign(*dworkptr);
344 	    *dworkptr = (double*) ((double*)*dworkptr - 1);
345 	    extra = (char*)old_ptr - (char*)*dworkptr;
346 #ifdef DEBUG
347 	    printf("dLUWorkInit: not aligned, extra %d\n", extra);
348 #endif
349 	    stack.top2 -= extra;
350 	    stack.used += extra;
351 	}
352     }
353     if ( ! *dworkptr ) {
354 	fprintf(stderr, "malloc fails for local dworkptr[].");
355 	return (isize + dsize + n);
356     }
357 
358     return 0;
359 }
360 
361 
362 /*! \brief Set up pointers for real working arrays.
363  */
364 void
dSetRWork(int m,int panel_size,double * dworkptr,double ** dense,double ** tempv)365 dSetRWork(int m, int panel_size, double *dworkptr,
366 	 double **dense, double **tempv)
367 {
368     double zero = 0.0;
369 
370     int maxsuper = sp_ienv(3),
371         rowblk   = sp_ienv(4);
372     *dense = dworkptr;
373     *tempv = *dense + panel_size*m;
374     dfill (*dense, m * panel_size, zero);
375     dfill (*tempv, NUM_TEMPV(m,panel_size,maxsuper,rowblk), zero);
376 }
377 
378 /*! \brief Free the working storage used by factor routines.
379  */
dLUWorkFree(int * iwork,double * dwork,GlobalLU_t * Glu)380 void dLUWorkFree(int *iwork, double *dwork, GlobalLU_t *Glu)
381 {
382     if ( Glu->MemModel == SYSTEM ) {
383 	SUPERLU_FREE (iwork);
384 	SUPERLU_FREE (dwork);
385     } else {
386 	stack.used -= (stack.size - stack.top2);
387 	stack.top2 = stack.size;
388 /*	dStackCompress(Glu);  */
389     }
390 
391     SUPERLU_FREE (expanders);
392     expanders = 0;
393 }
394 
395 /*! \brief Expand the data structures for L and U during the factorization.
396  *
397  * <pre>
398  * Return value:   0 - successful return
399  *               > 0 - number of bytes allocated when run out of space
400  * </pre>
401  */
402 int
dLUMemXpand(int jcol,int next,MemType mem_type,int * maxlen,GlobalLU_t * Glu)403 dLUMemXpand(int jcol,
404 	   int next,          /* number of elements currently in the factors */
405 	   MemType mem_type,  /* which type of memory to expand  */
406 	   int *maxlen,       /* modified - maximum length of a data structure */
407 	   GlobalLU_t *Glu    /* modified - global LU data structures */
408 	   )
409 {
410     void   *new_mem;
411 
412 #ifdef DEBUG
413     printf("dLUMemXpand(): jcol %d, next %d, maxlen %d, MemType %d\n",
414 	   jcol, next, *maxlen, mem_type);
415 #endif
416 
417     if (mem_type == USUB)
418     	new_mem = dexpand(maxlen, mem_type, next, 1, Glu);
419     else
420 	new_mem = dexpand(maxlen, mem_type, next, 0, Glu);
421 
422     if ( !new_mem ) {
423 	int    nzlmax  = Glu->nzlmax;
424 	int    nzumax  = Glu->nzumax;
425 	int    nzlumax = Glu->nzlumax;
426     	fprintf(stderr, "Can't expand MemType %d: jcol %d\n", mem_type, jcol);
427     	return (dmemory_usage(nzlmax, nzumax, nzlumax, Glu->n) + Glu->n);
428     }
429 
430     switch ( mem_type ) {
431       case LUSUP:
432 	Glu->lusup   = (double *) new_mem;
433 	Glu->nzlumax = *maxlen;
434 	break;
435       case UCOL:
436 	Glu->ucol   = (double *) new_mem;
437 	Glu->nzumax = *maxlen;
438 	break;
439       case LSUB:
440 	Glu->lsub   = (int *) new_mem;
441 	Glu->nzlmax = *maxlen;
442 	break;
443       case USUB:
444 	Glu->usub   = (int *) new_mem;
445 	Glu->nzumax = *maxlen;
446 	break;
447     }
448 
449     return 0;
450 
451 }
452 
453 
454 
455 void
copy_mem_double(int howmany,void * old,void * new)456 copy_mem_double(int howmany, void *old, void *new)
457 {
458     register int i;
459     double *dold = old;
460     double *dnew = new;
461     for (i = 0; i < howmany; i++) dnew[i] = dold[i];
462 }
463 
464 /*! \brief Expand the existing storage to accommodate more fill-ins.
465  */
466 void
dexpand(int * prev_len,MemType type,int len_to_copy,int keep_prev,GlobalLU_t * Glu)467 *dexpand (
468 	 int *prev_len,   /* length used from previous call */
469 	 MemType type,    /* which part of the memory to expand */
470 	 int len_to_copy, /* size of the memory to be copied to new store */
471 	 int keep_prev,   /* = 1: use prev_len;
472 			     = 0: compute new_len to expand */
473 	 GlobalLU_t *Glu  /* modified - global LU data structures */
474 	)
475 {
476     float    EXPAND = 1.5;
477     float    alpha;
478     void     *new_mem, *old_mem;
479     int      new_len, tries, lword, extra, bytes_to_copy;
480 
481     alpha = EXPAND;
482 
483     if ( no_expand == 0 || keep_prev ) /* First time allocate requested */
484         new_len = *prev_len;
485     else {
486 	new_len = alpha * *prev_len;
487     }
488 
489     if ( type == LSUB || type == USUB ) lword = sizeof(int);
490     else lword = sizeof(double);
491 
492     if ( Glu->MemModel == SYSTEM ) {
493 	new_mem = (void *) SUPERLU_MALLOC((size_t)new_len * lword);
494 	if ( no_expand != 0 ) {
495 	    tries = 0;
496 	    if ( keep_prev ) {
497 		if ( !new_mem ) return (NULL);
498 	    } else {
499 		while ( !new_mem ) {
500 		    if ( ++tries > 10 ) return (NULL);
501 		    alpha = Reduce(alpha);
502 		    new_len = alpha * *prev_len;
503 		    new_mem = (void *) SUPERLU_MALLOC((size_t)new_len * lword);
504 		}
505 	    }
506 	    if ( type == LSUB || type == USUB ) {
507 		copy_mem_int(len_to_copy, expanders[type].mem, new_mem);
508 	    } else {
509 		copy_mem_double(len_to_copy, expanders[type].mem, new_mem);
510 	    }
511 	    SUPERLU_FREE (expanders[type].mem);
512 	}
513 	expanders[type].mem = (void *) new_mem;
514 
515     } else { /* MemModel == USER */
516 	if ( no_expand == 0 ) {
517 	    new_mem = duser_malloc(new_len * lword, HEAD);
518 	    if ( NotDoubleAlign(new_mem) &&
519 		(type == LUSUP || type == UCOL) ) {
520 		old_mem = new_mem;
521 		new_mem = (void *)DoubleAlign(new_mem);
522 		extra = (char*)new_mem - (char*)old_mem;
523 #ifdef DEBUG
524 		printf("expand(): not aligned, extra %d\n", extra);
525 #endif
526 		stack.top1 += extra;
527 		stack.used += extra;
528 	    }
529 	    expanders[type].mem = (void *) new_mem;
530 	}
531 	else {
532 	    tries = 0;
533 	    extra = (new_len - *prev_len) * lword;
534 	    if ( keep_prev ) {
535 		if ( StackFull(extra) ) return (NULL);
536 	    } else {
537 		while ( StackFull(extra) ) {
538 		    if ( ++tries > 10 ) return (NULL);
539 		    alpha = Reduce(alpha);
540 		    new_len = alpha * *prev_len;
541 		    extra = (new_len - *prev_len) * lword;
542 		}
543 	    }
544 
545 	    if ( type != USUB ) {
546 		new_mem = (void*)((char*)expanders[type + 1].mem + extra);
547 		bytes_to_copy = (char*)stack.array + stack.top1
548 		    - (char*)expanders[type + 1].mem;
549 		user_bcopy(expanders[type+1].mem, new_mem, bytes_to_copy);
550 
551 		if ( type < USUB ) {
552 		    Glu->usub = expanders[USUB].mem =
553 			(void*)((char*)expanders[USUB].mem + extra);
554 		}
555 		if ( type < LSUB ) {
556 		    Glu->lsub = expanders[LSUB].mem =
557 			(void*)((char*)expanders[LSUB].mem + extra);
558 		}
559 		if ( type < UCOL ) {
560 		    Glu->ucol = expanders[UCOL].mem =
561 			(void*)((char*)expanders[UCOL].mem + extra);
562 		}
563 		stack.top1 += extra;
564 		stack.used += extra;
565 		if ( type == UCOL ) {
566 		    stack.top1 += extra;   /* Add same amount for USUB */
567 		    stack.used += extra;
568 		}
569 
570 	    } /* if ... */
571 
572 	} /* else ... */
573     }
574 
575     expanders[type].size = new_len;
576     *prev_len = new_len;
577     if ( no_expand ) ++no_expand;
578 
579     return (void *) expanders[type].mem;
580 
581 } /* dexpand */
582 
583 
584 /*! \brief Compress the work[] array to remove fragmentation.
585  */
586 void
dStackCompress(GlobalLU_t * Glu)587 dStackCompress(GlobalLU_t *Glu)
588 {
589     register int iword, dword, ndim;
590     char    *last, *fragment;
591     int      *ifrom, *ito;
592     double   *dfrom, *dto;
593     int      *xlsub, *lsub, *xusub, *usub, *xlusup;
594     double   *ucol, *lusup;
595 
596     iword = sizeof(int);
597     dword = sizeof(double);
598     ndim = Glu->n;
599 
600     xlsub  = Glu->xlsub;
601     lsub   = Glu->lsub;
602     xusub  = Glu->xusub;
603     usub   = Glu->usub;
604     xlusup = Glu->xlusup;
605     ucol   = Glu->ucol;
606     lusup  = Glu->lusup;
607 
608     dfrom = ucol;
609     dto = (double *)((char*)lusup + xlusup[ndim] * dword);
610     copy_mem_double(xusub[ndim], dfrom, dto);
611     ucol = dto;
612 
613     ifrom = lsub;
614     ito = (int *) ((char*)ucol + xusub[ndim] * iword);
615     copy_mem_int(xlsub[ndim], ifrom, ito);
616     lsub = ito;
617 
618     ifrom = usub;
619     ito = (int *) ((char*)lsub + xlsub[ndim] * iword);
620     copy_mem_int(xusub[ndim], ifrom, ito);
621     usub = ito;
622 
623     last = (char*)usub + xusub[ndim] * iword;
624     fragment = (char*) (((char*)stack.array + stack.top1) - last);
625     stack.used -= (long int) fragment;
626     stack.top1 -= (long int) fragment;
627 
628     Glu->ucol = ucol;
629     Glu->lsub = lsub;
630     Glu->usub = usub;
631 
632 #ifdef DEBUG
633     printf("dStackCompress: fragment %d\n", fragment);
634     /* for (last = 0; last < ndim; ++last)
635 	print_lu_col("After compress:", last, 0);*/
636 #endif
637 
638 }
639 
640 /*! \brief Allocate storage for original matrix A
641  */
642 void
dallocateA(int n,int nnz,double ** a,int ** asub,int ** xa)643 dallocateA(int n, int nnz, double **a, int **asub, int **xa)
644 {
645     *a    = (double *) doubleMalloc(nnz);
646     *asub = (int *) intMalloc(nnz);
647     *xa   = (int *) intMalloc(n+1);
648 }
649 
650 
doubleMalloc(int n)651 double *doubleMalloc(int n)
652 {
653     double *buf;
654     buf = (double *) SUPERLU_MALLOC((size_t)n * sizeof(double));
655     if ( !buf ) {
656 	ABORT("SUPERLU_MALLOC failed for buf in doubleMalloc()\n");
657     }
658     return (buf);
659 }
660 
doubleCalloc(int n)661 double *doubleCalloc(int n)
662 {
663     double *buf;
664     register int i;
665     double zero = 0.0;
666     buf = (double *) SUPERLU_MALLOC((size_t)n * sizeof(double));
667     if ( !buf ) {
668 	ABORT("SUPERLU_MALLOC failed for buf in doubleCalloc()\n");
669     }
670     for (i = 0; i < n; ++i) buf[i] = zero;
671     return (buf);
672 }
673 
674 
dmemory_usage(const int nzlmax,const int nzumax,const int nzlumax,const int n)675 int dmemory_usage(const int nzlmax, const int nzumax,
676 		  const int nzlumax, const int n)
677 {
678     register int iword, dword;
679 
680     iword   = sizeof(int);
681     dword   = sizeof(double);
682 
683     return (10 * n * iword +
684 	    nzlmax * iword + nzumax * (iword + dword) + nzlumax * dword);
685 
686 }
687