Rev 1820 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/* ========================================================================== *//* === UMF_get_memory ======================================================= *//* ========================================================================== *//* -------------------------------------------------------------------------- *//* UMFPACK Version 4.5, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, *//* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. *//* web: http://www.cise.ufl.edu/research/sparse/umfpack *//* -------------------------------------------------------------------------- *//*Reallocate the workspace (Numeric->Memory) and shift elements downwards.needunits: increase in size so that the free space is at least this manyUnits (to which the tuple lengths is added).Return TRUE if successful, FALSE if out of memory.*/#include "umf_internal.h"#include "umf_garbage_collection.h"#include "umf_tuple_lengths.h"#include "umf_build_tuples.h"#include "umf_mem_free_tail_block.h"#include "umf_realloc.h"GLOBAL Int UMF_get_memory(NumericType *Numeric,WorkType *Work,Int needunits,Int r2, /* compact current front to r2-by-c2 */Int c2,Int do_Fcpos){double nsize, bsize, tsize ;Int i, minsize, newsize, newmem, costly, row, col, *Row_tlen, *Col_tlen,n_row, n_col, *Row_degree, *Col_degree ;Unit *mnew, *p ;/* ---------------------------------------------------------------------- *//* get and check parameters *//* ---------------------------------------------------------------------- */#ifndef NDEBUGDEBUG1 (("::::GET MEMORY::::\n")) ;UMF_dump_memory (Numeric) ;#endifn_row = Work->n_row ;n_col = Work->n_col ;Row_degree = Numeric->Rperm ; /* for NON_PIVOTAL_ROW macro */Col_degree = Numeric->Cperm ; /* for NON_PIVOTAL_COL macro */Row_tlen = Numeric->Uilen ;Col_tlen = Numeric->Lilen ;/* ---------------------------------------------------------------------- *//* initialize the tuple list lengths *//* ---------------------------------------------------------------------- */for (row = 0 ; row < n_row ; row++){if (NON_PIVOTAL_ROW (row)){Row_tlen [row] = 0 ;}}for (col = 0 ; col < n_col ; col++){if (NON_PIVOTAL_COL (col)){Col_tlen [col] = 0 ;}}/* ---------------------------------------------------------------------- *//* determine how much memory is needed for the tuples *//* ---------------------------------------------------------------------- */nsize = (double) needunits + 2 ;needunits += UMF_tuple_lengths (Numeric, Work, &tsize) ;nsize += tsize ;needunits += 2 ; /* add 2, so that newmem >= 2 is true if realloc'd *//* note: Col_tlen and Row_tlen are updated, but the tuple lists *//* themselves are not. Do not attempt to scan the tuple lists. *//* They are now stale, and are about to be destroyed and recreated. *//* ---------------------------------------------------------------------- *//* determine the desired new size of memory *//* ---------------------------------------------------------------------- */DEBUG0 (("UMF_get_memory: needunits: "ID"\n", needunits)) ;minsize = Numeric->size + needunits ;nsize += (double) Numeric->size ;bsize = ((double) Int_MAX) / sizeof (Unit) - 1 ;newsize = (Int) (UMF_REALLOC_INCREASE * ((double) minsize)) ;nsize *= UMF_REALLOC_INCREASE ;nsize += 1 ;if (newsize < 0 || nsize > bsize){/* :: realloc Numeric->Memory int overflow :: */DEBUGm3 (("Realloc hit integer limit\n")) ;newsize = (Int) bsize ; /* we cannot increase the size beyond bsize */}else{ASSERT (newsize <= nsize) ;newsize = MAX (newsize, minsize) ;}newsize = MAX (newsize, Numeric->size) ;DEBUG0 (("REALLOC MEMORY: needunits "ID" old size: "ID" new size: "ID" Units \n",needunits, Numeric->size, newsize)) ;/* Forget where the biggest free block is (we no longer need it) *//* since garbage collection will occur shortly. */Numeric->ibig = EMPTY ;DEBUG0 (("Before realloc E [0] "ID"\n", Work->E [0])) ;/* ---------------------------------------------------------------------- *//* reallocate the memory, if possible, and make it bigger *//* ---------------------------------------------------------------------- */mnew = (Unit *) NULL ;while (!mnew){mnew = (Unit *) UMF_realloc (Numeric->Memory, newsize, sizeof (Unit)) ;if (!mnew){if (newsize == minsize) /* last realloc attempt failed */{/* We failed to get the minimum. Just stick with the *//* current allocation and hope that garbage collection *//* can recover enough space. */mnew = Numeric->Memory ; /* no new memory available */newsize = Numeric->size ;}else{/* otherwise, reduce the request and keep trying */newsize = (Int) (UMF_REALLOC_REDUCTION * ((double) newsize)) ;newsize = MAX (minsize, newsize) ;}}}ASSERT (mnew != (Unit *) NULL) ;/* see if realloc had to copy, rather than just extend memory */costly = (mnew != Numeric->Memory) ;/* ---------------------------------------------------------------------- *//* extend the tail portion of memory downwards *//* ---------------------------------------------------------------------- */Numeric->Memory = mnew ;if (Work->E [0]){Int nb, dr, dc ;nb = Work->nb ;dr = Work->fnr_curr ;dc = Work->fnc_curr ;Work->Flublock = (Entry *) (Numeric->Memory + Work->E [0]) ;Work->Flblock = Work->Flublock + nb * nb ;Work->Fublock = Work->Flblock + dr * nb ;Work->Fcblock = Work->Fublock + nb * dc ;DEBUG0 (("after realloc E [0] "ID"\n", Work->E [0])) ;}ASSERT (IMPLIES (!(Work->E [0]), Work->Flublock == (Entry *) NULL)) ;newmem = newsize - Numeric->size ;ASSERT (newmem == 0 || newmem >= 2) ;if (newmem >= 2){/* reallocation succeeded *//* point to the old tail marker block of size 1 + header */p = Numeric->Memory + Numeric->size - 2 ;/* create a new block out of the newly extended memory */p->header.size = newmem - 1 ;i = Numeric->size - 1 ;p += newmem ;/* create a new tail marker block */p->header.prevsize = newmem - 1 ;p->header.size = 1 ;Numeric->size = newsize ;/* free the new block */UMF_mem_free_tail_block (Numeric, i) ;Numeric->nrealloc++ ;if (costly){Numeric->ncostly++ ;}}DEBUG1 (("Done with realloc memory\n")) ;/* ---------------------------------------------------------------------- *//* garbage collection on the tail of Numeric->memory (destroys tuples) *//* ---------------------------------------------------------------------- */UMF_garbage_collection (Numeric, Work, r2, c2, do_Fcpos) ;/* ---------------------------------------------------------------------- *//* rebuild the tuples *//* ---------------------------------------------------------------------- */return (UMF_build_tuples (Numeric, Work)) ;}