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