Path: blob/devel/umfpack/src/umfpack/umf_get_memory.c
3203 views
/* ========================================================================== */1/* === UMF_get_memory ======================================================= */2/* ========================================================================== */34/* -------------------------------------------------------------------------- */5/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */6/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */7/* web: http://www.cise.ufl.edu/research/sparse/umfpack */8/* -------------------------------------------------------------------------- */910/*11Reallocate the workspace (Numeric->Memory) and shift elements downwards.12needunits: increase in size so that the free space is at least this many13Units (to which the tuple lengths is added).1415Return TRUE if successful, FALSE if out of memory.16*/1718#include "umf_internal.h"19#include "umf_garbage_collection.h"20#include "umf_tuple_lengths.h"21#include "umf_build_tuples.h"22#include "umf_mem_free_tail_block.h"23#include "umf_realloc.h"2425GLOBAL Int UMF_get_memory26(27NumericType *Numeric,28WorkType *Work,29Int needunits,30Int r2, /* compact current front to r2-by-c2 */31Int c2,32Int do_Fcpos33)34{35double nsize, bsize, tsize ;36Int i, minsize, newsize, newmem, costly, row, col, *Row_tlen, *Col_tlen,37n_row, n_col, *Row_degree, *Col_degree ;38Unit *mnew, *p ;3940/* ---------------------------------------------------------------------- */41/* get and check parameters */42/* ---------------------------------------------------------------------- */4344#ifndef NDEBUG45DEBUG1 (("::::GET MEMORY::::\n")) ;46UMF_dump_memory (Numeric) ;47#endif4849n_row = Work->n_row ;50n_col = Work->n_col ;51Row_degree = Numeric->Rperm ; /* for NON_PIVOTAL_ROW macro */52Col_degree = Numeric->Cperm ; /* for NON_PIVOTAL_COL macro */53Row_tlen = Numeric->Uilen ;54Col_tlen = Numeric->Lilen ;5556/* ---------------------------------------------------------------------- */57/* initialize the tuple list lengths */58/* ---------------------------------------------------------------------- */5960for (row = 0 ; row < n_row ; row++)61{62if (NON_PIVOTAL_ROW (row))63{64Row_tlen [row] = 0 ;65}66}67for (col = 0 ; col < n_col ; col++)68{69if (NON_PIVOTAL_COL (col))70{71Col_tlen [col] = 0 ;72}73}7475/* ---------------------------------------------------------------------- */76/* determine how much memory is needed for the tuples */77/* ---------------------------------------------------------------------- */7879nsize = (double) needunits + 2 ;80needunits += UMF_tuple_lengths (Numeric, Work, &tsize) ;81nsize += tsize ;82needunits += 2 ; /* add 2, so that newmem >= 2 is true if realloc'd */8384/* note: Col_tlen and Row_tlen are updated, but the tuple lists */85/* themselves are not. Do not attempt to scan the tuple lists. */86/* They are now stale, and are about to be destroyed and recreated. */8788/* ---------------------------------------------------------------------- */89/* determine the desired new size of memory */90/* ---------------------------------------------------------------------- */9192DEBUG0 (("UMF_get_memory: needunits: "ID"\n", needunits)) ;9394minsize = Numeric->size + needunits ;95nsize += (double) Numeric->size ;9697bsize = ((double) Int_MAX) / sizeof (Unit) - 1 ;9899newsize = (Int) (UMF_REALLOC_INCREASE * ((double) minsize)) ;100nsize *= UMF_REALLOC_INCREASE ;101nsize += 1 ;102103if (newsize < 0 || nsize > bsize)104{105/* :: realloc Numeric->Memory int overflow :: */106DEBUGm3 (("Realloc hit integer limit\n")) ;107newsize = (Int) bsize ; /* we cannot increase the size beyond bsize */108}109else110{111ASSERT (newsize <= nsize) ;112newsize = MAX (newsize, minsize) ;113}114newsize = MAX (newsize, Numeric->size) ;115116DEBUG0 ((117"REALLOC MEMORY: needunits "ID" old size: "ID" new size: "ID" Units \n",118needunits, Numeric->size, newsize)) ;119120/* Forget where the biggest free block is (we no longer need it) */121/* since garbage collection will occur shortly. */122Numeric->ibig = EMPTY ;123124DEBUG0 (("Before realloc E [0] "ID"\n", Work->E [0])) ;125126/* ---------------------------------------------------------------------- */127/* reallocate the memory, if possible, and make it bigger */128/* ---------------------------------------------------------------------- */129130mnew = (Unit *) NULL ;131while (!mnew)132{133mnew = (Unit *) UMF_realloc (Numeric->Memory, newsize, sizeof (Unit)) ;134if (!mnew)135{136if (newsize == minsize) /* last realloc attempt failed */137{138/* We failed to get the minimum. Just stick with the */139/* current allocation and hope that garbage collection */140/* can recover enough space. */141mnew = Numeric->Memory ; /* no new memory available */142newsize = Numeric->size ;143}144else145{146/* otherwise, reduce the request and keep trying */147newsize = (Int) (UMF_REALLOC_REDUCTION * ((double) newsize)) ;148newsize = MAX (minsize, newsize) ;149}150}151}152ASSERT (mnew != (Unit *) NULL) ;153154/* see if realloc had to copy, rather than just extend memory */155costly = (mnew != Numeric->Memory) ;156157/* ---------------------------------------------------------------------- */158/* extend the tail portion of memory downwards */159/* ---------------------------------------------------------------------- */160161Numeric->Memory = mnew ;162if (Work->E [0])163{164Int nb, dr, dc ;165nb = Work->nb ;166dr = Work->fnr_curr ;167dc = Work->fnc_curr ;168Work->Flublock = (Entry *) (Numeric->Memory + Work->E [0]) ;169Work->Flblock = Work->Flublock + nb * nb ;170Work->Fublock = Work->Flblock + dr * nb ;171Work->Fcblock = Work->Fublock + nb * dc ;172DEBUG0 (("after realloc E [0] "ID"\n", Work->E [0])) ;173}174ASSERT (IMPLIES (!(Work->E [0]), Work->Flublock == (Entry *) NULL)) ;175176newmem = newsize - Numeric->size ;177ASSERT (newmem == 0 || newmem >= 2) ;178179if (newmem >= 2)180{181/* reallocation succeeded */182183/* point to the old tail marker block of size 1 + header */184p = Numeric->Memory + Numeric->size - 2 ;185186/* create a new block out of the newly extended memory */187p->header.size = newmem - 1 ;188i = Numeric->size - 1 ;189p += newmem ;190191/* create a new tail marker block */192p->header.prevsize = newmem - 1 ;193p->header.size = 1 ;194195Numeric->size = newsize ;196197/* free the new block */198UMF_mem_free_tail_block (Numeric, i) ;199200Numeric->nrealloc++ ;201202if (costly)203{204Numeric->ncostly++ ;205}206207}208DEBUG1 (("Done with realloc memory\n")) ;209210/* ---------------------------------------------------------------------- */211/* garbage collection on the tail of Numeric->memory (destroys tuples) */212/* ---------------------------------------------------------------------- */213214UMF_garbage_collection (Numeric, Work, r2, c2, do_Fcpos) ;215216/* ---------------------------------------------------------------------- */217/* rebuild the tuples */218/* ---------------------------------------------------------------------- */219220return (UMF_build_tuples (Numeric, Work)) ;221}222223224