Path: blob/devel/umfpack/src/umfpack/umf_garbage_collection.c
3203 views
/* ========================================================================== */1/* === UMF_garbage_collection =============================================== */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/*11Compress the elements at the tail of Numeric->Memory, and delete the tuples.12Elements are renumbered. The new numbering space is compressed, and13in the order of element creation (original elements of A first, followed14by the new elements in the order that they were formed).1516Only called by UMF_get_memory.1718There are 5 ways in which garbage collection can be performed:1920Allocate a new working array for the current frontal matrix. In this21case, there are never any pivot rows/columns in the current frontal22matrix (fnpiv = 0), and the old working array for the current frontal23matrix can always be fully compacted, to fnrows-by-fncols.2425UMF_kernel : UMF_extend : UMF_grow_front : UMF_get_memory26UMF_kernel : UMF_init_front : UMF_grow_front : UMF_get_memory27UMF_kernel : UMF_start_front : UMF_grow_front : UMF_get_memory2829Allocate a new element. In this case, UMF_grow_front may or may not30be subsequently called, depending on Work->do_grow. There are never31any pivot rows/columns in the current frontal matrix (fnpiv=0), but one32may be added if UMF_init_front is to be called just after33UMF_create_element. If do_grow is true, then the current front can be34fully compacted, to fnrows-by-fncols. Otherwise, it can only be35partially compacted, to MAX (fnrows, fnrows_new + 1) -by-36MAX (fncols, fncols_new + 1).3738UMF_kernel : UMF_create_element : UMF_get_memory3940Allocate rows of L and columns of U. In this case, the current41frontal matrix is only partially compacted, to (fnrows_new + 1)-by-42(fncols_new + 1). There are pivots in the frontal matrix (fnpiv > 0).4344UMF_kernel : UMF_store_lu : UMF_get_memory45*/4647#include "umf_internal.h"4849GLOBAL void UMF_garbage_collection50(51NumericType *Numeric,52WorkType *Work,53Int drnew, /* compact current front to drnew-by-dcnew */54Int dcnew,55Int do_Fcpos56)57{58/* ---------------------------------------------------------------------- */59/* local variables */60/* ---------------------------------------------------------------------- */6162Int size, e, n_row, n_col, nrows, ncols, nrowsleft, ncolsleft, prevsize,63csize, size2, i2, j2, i, j, cdeg, rdeg, *E, row, col,64*Rows, *Cols, *Rows2, *Cols2, nel, e2, *Row_tuples, *Col_tuples,65*Row_degree, *Col_degree ;66Entry *C, *C1, *C3, *C2 ;67Unit *psrc, *pdest, *p, *pnext ;68Element *epsrc, *epdest ;6970#ifndef NDEBUG71Int nmark ;72#endif7374/* ---------------------------------------------------------------------- */75/* get parameters */76/* ---------------------------------------------------------------------- */7778Col_degree = Numeric->Cperm ; /* for NON_PIVOTAL_COL macro */79Row_degree = Numeric->Rperm ; /* for NON_PIVOTAL_ROW macro */80Row_tuples = Numeric->Uip ;81Col_tuples = Numeric->Lip ;82E = Work->E ;83n_row = Work->n_row ;84n_col = Work->n_col ;8586/* note that the tuple lengths (Col_tlen and Row_tlen) are updated, but */87/* the tuple lists themselves are stale and are about to be destroyed */88/* and recreated. Do not attempt to scan them until they are recreated. */8990#ifndef NDEBUG91DEBUGm1 (("::::GARBAGE COLLECTION::::\n")) ;92UMF_dump_memory (Numeric) ;93#endif9495Numeric->ngarbage++ ;9697/* ---------------------------------------------------------------------- */98/* delete the tuple lists by marking the blocks as free */99/* ---------------------------------------------------------------------- */100101/* do not modify Row_tlen and Col_tlen */102/* those are needed for UMF_build_tuples */103104for (row = 0 ; row < n_row ; row++)105{106if (NON_PIVOTAL_ROW (row) && Row_tuples [row])107{108DEBUG2 (("row "ID" tuples "ID"\n", row, Row_tuples [row])) ;109p = Numeric->Memory + Row_tuples [row] - 1 ;110DEBUG2 (("Freeing tuple list row "ID", p-S "ID", size "ID"\n",111row, (Int) (p-Numeric->Memory), p->header.size)) ;112ASSERT (p->header.size > 0) ;113ASSERT (p >= Numeric->Memory + Numeric->itail) ;114ASSERT (p < Numeric->Memory + Numeric->size) ;115p->header.size = -p->header.size ;116Row_tuples [row] = 0 ;117}118}119120for (col = 0 ; col < n_col ; col++)121{122if (NON_PIVOTAL_COL (col) && Col_tuples [col])123{124DEBUG2 (("col "ID" tuples "ID"\n", col, Col_tuples [col])) ;125p = Numeric->Memory + Col_tuples [col] - 1 ;126DEBUG2 (("Freeing tuple list col "ID", p-S "ID", size "ID"\n",127col, (Int) (p-Numeric->Memory), p->header.size)) ;128ASSERT (p->header.size > 0) ;129ASSERT (p >= Numeric->Memory + Numeric->itail) ;130ASSERT (p < Numeric->Memory + Numeric->size) ;131p->header.size = -p->header.size ;132Col_tuples [col] = 0 ;133}134}135136/* ---------------------------------------------------------------------- */137/* mark the elements, and compress the name space */138/* ---------------------------------------------------------------------- */139140nel = Work->nel ;141ASSERT (nel < Work->elen) ;142143#ifndef NDEBUG144nmark = 0 ;145UMF_dump_current_front (Numeric, Work, FALSE) ;146DEBUGm1 (("E [0] "ID" \n", E [0])) ;147ASSERT (IMPLIES (E [0],148Work->Flublock == (Entry *) (Numeric->Memory + E [0]))) ;149ASSERT (IMPLIES (Work->Flublock,150Work->Flublock == (Entry *) (Numeric->Memory + E [0]))) ;151ASSERT ((E [0] != 0) == (Work->Flublock != (Entry *) NULL)) ;152#endif153154e2 = 0 ;155156for (e = 0 ; e <= nel ; e++) /* for all elements in order of creation */157{158if (E [e])159{160psrc = Numeric->Memory + E [e] ;161psrc-- ; /* get the header of this block */162if (e > 0)163{164e2++ ; /* do not renumber element zero */165}166ASSERT (psrc->header.size > 0) ;167psrc->header.size = e2 ; /* store the new name in the header */168#ifndef NDEBUG169nmark++ ;170#endif171DEBUG7 ((ID":: Mark e "ID" at psrc-S "ID", new e "ID"\n",172nmark, e, (Int) (psrc-Numeric->Memory), e2)) ;173E [e] = 0 ;174if (e == Work->prior_element)175{176Work->prior_element = e2 ;177}178}179}180181/* all 1..e2 are now in use (element zero may or may not be in use) */182Work->nel = e2 ;183nel = Work->nel ;184185#ifndef NDEBUG186for (e = 0 ; e < Work->elen ; e++)187{188ASSERT (!E [e]) ;189}190#endif191192/* ---------------------------------------------------------------------- */193/* compress the elements */194/* ---------------------------------------------------------------------- */195196/* point to tail marker block of size 1 + header */197psrc = Numeric->Memory + Numeric->size - 2 ;198pdest = psrc ;199prevsize = psrc->header.prevsize ;200DEBUG7 (("Starting the compression:\n")) ;201202while (prevsize > 0)203{204205/* ------------------------------------------------------------------ */206/* move up to the next element above the current header, and */207/* get the element name and size */208/* (if it is an element, the name will be positive) */209/* ------------------------------------------------------------------ */210211size = prevsize ;212psrc -= (size + 1) ;213e = psrc->header.size ;214prevsize = psrc->header.prevsize ;215/* top block at tail has prevsize of 0 */216217/* a free block will have a negative size, so skip it */218/* otherwise, if size >= 0, it holds the element name, not the size */219220DEBUG8 (("psrc-S: "ID" prevsize: "ID" size: "ID,221(Int) (psrc-Numeric->Memory), prevsize, size)) ;222223if (e == 0)224{225/* -------------------------------------------------------------- */226/* this is the current frontal matrix */227/* -------------------------------------------------------------- */228229Entry *F1, *F2, *Fsrc, *Fdst ;230Int c, r, k, dr, dc, gap, gap1, gap2, nb ;231232/* shift the frontal matrix down */233F1 = (Entry *) (psrc + 1) ;234235/* get the size of the current front. r and c could be zero */236k = Work->fnpiv ;237dr = Work->fnr_curr ;238dc = Work->fnc_curr ;239r = Work->fnrows ;240c = Work->fncols ;241nb = Work->nb ;242243ASSERT ((dr >= 0 && (dr % 2) == 1) || dr == 0) ;244ASSERT (drnew >= 0) ;245if (drnew % 2 == 0)246{247/* make sure leading frontal matrix dimension is always odd */248drnew++ ;249}250drnew = MIN (dr, drnew) ;251ASSERT ((drnew >= 0 && (drnew % 2) == 1) || drnew == 0) ;252253pnext = pdest ;254255#ifndef NDEBUG256DEBUGm2 (("move front: dr "ID" dc "ID" r "ID" drnew "ID" c "ID257" dcnew " ID" k "ID"\n", dr, dc, r, drnew, c, dcnew, k)) ;258DEBUG7 (("\n")) ;259DEBUG7 ((ID":: Move current frontal matrix from: psrc-S: "ID" \n",260nmark, (Int) (psrc-Numeric->Memory))) ;261nmark-- ;262ASSERT (E [e] == 0) ;263ASSERT (Work->Flublock == F1) ;264ASSERT (Work->Flblock == Work->Flublock + nb*nb) ;265ASSERT (Work->Fublock == Work->Flblock + dr*nb) ;266ASSERT (Work->Fcblock == Work->Fublock + nb*dc) ;267DEBUG7 (("C block: ")) ;268UMF_dump_dense (Work->Fcblock, dr, r, c) ;269DEBUG7 (("L block: ")) ;270UMF_dump_dense (Work->Flblock, dr, r, k);271DEBUG7 (("U' block: ")) ;272UMF_dump_dense (Work->Fublock, dc, c, k) ;273DEBUG7 (("LU block: ")) ;274UMF_dump_dense (Work->Flublock, nb, k, k) ;275ASSERT (r <= drnew && c <= dcnew && drnew <= dr && dcnew <= dc) ;276#endif277278/* compact frontal matrix to drnew-by-dcnew before moving it */279280/* do not compact the LU block (nb-by-nb) */281282/* compact the columns of L (from dr-by-nb to drnew-by-nb) */283Fsrc = Work->Flblock ;284Fdst = Work->Flblock ;285ASSERT (Fdst == F1 + nb*nb) ;286gap1 = dr - r ;287gap2 = drnew - r ;288ASSERT (gap1 >= 0) ;289for (j = 0 ; j < k ; j++)290{291for (i = 0 ; i < r ; i++)292{293*Fdst++ = *Fsrc++ ;294}295Fsrc += gap1 ;296Fdst += gap2 ;297}298ASSERT (Fdst == F1 + nb*nb + drnew*k) ;299Fdst += drnew * (nb - k) ;300301/* compact the rows of U (U' from dc-by-nb to dcnew-by-nb) */302Fsrc = Work->Fublock ;303ASSERT (Fdst == F1 + nb*nb + drnew*nb) ;304gap1 = dc - c ;305gap2 = dcnew - c ;306for (i = 0 ; i < k ; i++)307{308for (j = 0 ; j < c ; j++)309{310*Fdst++ = *Fsrc++ ;311}312Fsrc += gap1 ;313Fdst += gap2 ;314}315ASSERT (Fdst == F1 + nb*nb + drnew*nb + dcnew*k) ;316Fdst += dcnew * (nb - k) ;317318/* compact the columns of C (from dr-by-dc to drnew-by-dcnew) */319Fsrc = Work->Fcblock ;320ASSERT (Fdst == F1 + nb*nb + drnew*nb + nb*dcnew) ;321gap1 = dr - r ;322gap2 = drnew - r ;323for (j = 0 ; j < c ; j++)324{325for (i = 0 ; i < r ; i++)326{327*Fdst++ = *Fsrc++ ;328}329Fsrc += gap1 ;330Fdst += gap2 ;331}332ASSERT (Fdst == F1 + nb*nb + drnew*nb + nb*dcnew + drnew*c) ;333334/* recompute Fcpos, if necessary */335if (do_Fcpos)336{337Int *Fcols, *Fcpos ;338Fcols = Work->Fcols ;339Fcpos = Work->Fcpos ;340for (j = 0 ; j < c ; j++)341{342col = Fcols [j] ;343ASSERT (col >= 0 && col < Work->n_col) ;344ASSERT (Fcpos [col] == j * dr) ;345Fcpos [col] = j * drnew ;346}347#ifndef NDEBUG348{349Int cnt = 0 ;350for (j = 0 ; j < Work->n_col ; j++)351{352if (Fcpos [j] != EMPTY) cnt++ ;353}354DEBUGm2 (("Recompute Fcpos cnt "ID" c "ID"\n", cnt, c)) ;355ASSERT (cnt == c) ;356}357#endif358}359360#ifndef NDEBUG361DEBUGm2 (("Compacted front, drnew "ID" dcnew "ID"\n", drnew, dcnew)) ;362DEBUG7 (("C block: ")) ;363UMF_dump_dense (F1 + nb*nb + drnew*nb + nb*dcnew, drnew, r, c) ;364DEBUG7 (("L block: ")) ;365UMF_dump_dense (F1 + nb*nb, drnew, r, k) ;366DEBUG7 (("U block: ")) ;367UMF_dump_dense (F1 + nb*nb + drnew*nb, nb, k, c) ;368DEBUG7 (("LU block: ")) ;369UMF_dump_dense (F1, nb, k, k) ;370#endif371372/* Compacted dimensions of the new frontal matrix. */373Work->fnr_curr = drnew ;374Work->fnc_curr = dcnew ;375Work->fcurr_size = (drnew + nb) * (dcnew + nb) ;376size = UNITS (Entry, Work->fcurr_size) ;377378/* make sure the object doesn't evaporate. The front can have379* zero size (Work->fcurr_size = 0), but the size of the memory380* block containing it cannot have zero size. */381size = MAX (1, size) ;382383/* get the destination of frontal matrix */384pnext->header.prevsize = size ;385pdest -= (size + 1) ;386F2 = (Entry *) (pdest + 1) ;387388ASSERT ((unsigned Int) psrc + 1 + size <= (unsigned Int) pnext) ;389ASSERT (psrc <= pdest) ;390ASSERT (F1 <= F2) ;391392/* move the C block first */393Fsrc = F1 + nb*nb + drnew*nb + nb*dcnew + drnew*c ;394Fdst = F2 + nb*nb + drnew*nb + nb*dcnew + drnew*c ;395gap = drnew - r ;396for (j = c-1 ; j >= 0 ; j--)397{398Fsrc -= gap ;399Fdst -= gap ;400/* move column j of C */401for (i = r-1 ; i >= 0 ; i--)402{403*--Fdst = *--Fsrc ;404}405}406ASSERT (Fsrc == F1 + nb*nb + drnew*nb + nb*dcnew) ;407ASSERT (Fdst == F2 + nb*nb + drnew*nb + nb*dcnew) ;408409/* move the U block */410Fsrc -= dcnew * (nb - k) ;411Fdst -= dcnew * (nb - k) ;412ASSERT (Fsrc == F1 + nb*nb + drnew*nb + dcnew*k) ;413ASSERT (Fdst == F2 + nb*nb + drnew*nb + dcnew*k) ;414gap = dcnew - c ;415for (i = k-1 ; i >= 0 ; i--)416{417Fsrc -= gap ;418Fdst -= gap ;419for (j = c-1 ; j >= 0 ; j--)420{421*--Fdst = *--Fsrc ;422}423}424ASSERT (Fsrc == F1 + nb*nb + drnew*nb) ;425ASSERT (Fdst == F2 + nb*nb + drnew*nb) ;426427/* move the L block */428Fsrc -= drnew * (nb - k) ;429Fdst -= drnew * (nb - k) ;430ASSERT (Fsrc == F1 + nb*nb + drnew*k) ;431ASSERT (Fdst == F2 + nb*nb + drnew*k) ;432gap = drnew - r ;433for (j = k-1 ; j >= 0 ; j--)434{435Fsrc -= gap ;436Fdst -= gap ;437for (i = r-1 ; i >= 0 ; i--)438{439*--Fdst = *--Fsrc ;440}441}442ASSERT (Fsrc == F1 + nb*nb) ;443ASSERT (Fdst == F2 + nb*nb) ;444445/* move the LU block */446Fsrc -= nb * (nb - k) ;447Fdst -= nb * (nb - k) ;448ASSERT (Fsrc == F1 + nb*k) ;449ASSERT (Fdst == F2 + nb*k) ;450gap = nb - k ;451for (j = k-1 ; j >= 0 ; j--)452{453Fsrc -= gap ;454Fdst -= gap ;455for (i = k-1 ; i >= 0 ; i--)456{457*--Fdst = *--Fsrc ;458}459}460ASSERT (Fsrc == F1) ;461ASSERT (Fdst == F2) ;462463E [0] = (pdest + 1) - Numeric->Memory ;464465Work->Flublock = (Entry *) (Numeric->Memory + E [0]) ;466ASSERT (Work->Flublock == F2) ;467Work->Flblock = Work->Flublock + nb * nb ;468Work->Fublock = Work->Flblock + drnew * nb ;469Work->Fcblock = Work->Fublock + nb * dcnew ;470471pdest->header.prevsize = 0 ;472pdest->header.size = size ;473474#ifndef NDEBUG475DEBUG7 (("After moving compressed current frontal matrix:\n")) ;476DEBUG7 (("C block: ")) ;477UMF_dump_dense (Work->Fcblock, drnew, r, c) ;478DEBUG7 (("L block: ")) ;479UMF_dump_dense (Work->Flblock, drnew, r, k);480DEBUG7 (("U' block: ")) ;481UMF_dump_dense (Work->Fublock, dcnew, c, k) ;482DEBUG7 (("LU block: ")) ;483UMF_dump_dense (Work->Flublock, nb, k, k) ;484#endif485486}487else if (e > 0)488{489490/* -------------------------------------------------------------- */491/* this is an element, compress and move from psrc down to pdest */492/* -------------------------------------------------------------- */493494#ifndef NDEBUG495DEBUG7 (("\n")) ;496DEBUG7 ((ID":: Move element "ID": from: "ID" \n",497nmark, e, (Int) (psrc-Numeric->Memory))) ;498nmark-- ;499ASSERT (e <= nel) ;500ASSERT (E [e] == 0) ;501#endif502503/* -------------------------------------------------------------- */504/* get the element scalars, and pointers to C, Rows, and Cols: */505/* -------------------------------------------------------------- */506507p = psrc + 1 ;508GET_ELEMENT (epsrc, p, Cols, Rows, ncols, nrows, C) ;509nrowsleft = epsrc->nrowsleft ;510ncolsleft = epsrc->ncolsleft ;511cdeg = epsrc->cdeg ;512rdeg = epsrc->rdeg ;513514#ifndef NDEBUG515DEBUG7 ((" nrows "ID" nrowsleft "ID"\n", nrows, nrowsleft)) ;516DEBUG7 ((" ncols "ID" ncolsleft "ID"\n", ncols, ncolsleft)) ;517DEBUG8 ((" Rows:")) ;518for (i = 0 ; i < nrows ; i++) DEBUG8 ((" "ID, Rows [i])) ;519DEBUG8 (("\n Cols:")) ;520for (j = 0 ; j < ncols ; j++) DEBUG8 ((" "ID, Cols [j])) ;521DEBUG8 (("\n")) ;522#endif523524/* -------------------------------------------------------------- */525/* determine the layout of the new element */526/* -------------------------------------------------------------- */527528csize = nrowsleft * ncolsleft ;529size2 = UNITS (Element, 1)530+ UNITS (Int, nrowsleft + ncolsleft)531+ UNITS (Entry, csize) ;532533DEBUG7 (("Old size "ID" New size "ID"\n", size, size2)) ;534535pnext = pdest ;536pnext->header.prevsize = size2 ;537pdest -= (size2 + 1) ;538539ASSERT (size2 <= size) ;540ASSERT ((unsigned Int) psrc + 1 + size <= (unsigned Int) pnext) ;541ASSERT (psrc <= pdest) ;542543p = pdest + 1 ;544epdest = (Element *) p ;545p += UNITS (Element, 1) ;546Cols2 = (Int *) p ;547Rows2 = Cols2 + ncolsleft ;548p += UNITS (Int, nrowsleft + ncolsleft) ;549C2 = (Entry *) p ;550551ASSERT (epdest >= epsrc) ;552ASSERT (Rows2 >= Rows) ;553ASSERT (Cols2 >= Cols) ;554ASSERT (C2 >= C) ;555ASSERT (p + UNITS (Entry, csize) == pnext) ;556557/* -------------------------------------------------------------- */558/* move the contribution block */559/* -------------------------------------------------------------- */560561/* overlap = psrc + size + 1 > pdest ; */562563if (nrowsleft < nrows || ncolsleft < ncols)564{565566/* ---------------------------------------------------------- */567/* compress contribution block in place prior to moving it */568/* ---------------------------------------------------------- */569570DEBUG7 (("Compress C in place prior to move:\n"));571#ifndef NDEBUG572UMF_dump_dense (C, nrows, nrows, ncols) ;573#endif574C1 = C ;575C3 = C ;576for (j = 0 ; j < ncols ; j++)577{578if (Cols [j] >= 0)579{580for (i = 0 ; i < nrows ; i++)581{582if (Rows [i] >= 0)583{584*C3++ = C1 [i] ;585}586}587}588C1 += nrows ;589}590ASSERT (C3-C == csize) ;591DEBUG8 (("Newly compressed contrib. block (all in use):\n")) ;592#ifndef NDEBUG593UMF_dump_dense (C, nrowsleft, nrowsleft, ncolsleft) ;594#endif595}596597/* shift the contribution block down */598C += csize ;599C2 += csize ;600for (i = 0 ; i < csize ; i++)601{602*--C2 = *--C ;603}604605/* -------------------------------------------------------------- */606/* move the row indices */607/* -------------------------------------------------------------- */608609i2 = nrowsleft ;610for (i = nrows - 1 ; i >= 0 ; i--)611{612ASSERT (Rows2+i2 >= Rows+i) ;613if (Rows [i] >= 0)614{615Rows2 [--i2] = Rows [i] ;616}617}618ASSERT (i2 == 0) ;619620j2 = ncolsleft ;621for (j = ncols - 1 ; j >= 0 ; j--)622{623ASSERT (Cols2+j2 >= Cols+j) ;624if (Cols [j] >= 0)625{626Cols2 [--j2] = Cols [j] ;627}628}629ASSERT (j2 == 0) ;630631/* -------------------------------------------------------------- */632/* construct the new header */633/* -------------------------------------------------------------- */634635/* E [0...e] is now valid */636E [e] = (pdest + 1) - Numeric->Memory ;637epdest = (Element *) (pdest + 1) ;638639epdest->next = EMPTY ; /* destroys the son list */640epdest->ncols = ncolsleft ;641epdest->nrows = nrowsleft ;642epdest->ncolsleft = ncolsleft ;643epdest->nrowsleft = nrowsleft ;644epdest->rdeg = rdeg ;645epdest->cdeg = cdeg ;646647ASSERT (size2 <= size) ;648pdest->header.prevsize = 0 ;649pdest->header.size = size2 ;650651DEBUG7 (("After moving it:\n")) ;652#ifndef NDEBUG653UMF_dump_element (Numeric, Work, e, FALSE) ;654#endif655}656657#ifndef NDEBUG658else659{660DEBUG8 ((" free\n")) ;661}662#endif663DEBUG7 (("psrc "ID" tail "ID"\n",664(Int) (psrc-Numeric->Memory), Numeric->itail)) ;665}666667ASSERT (psrc == Numeric->Memory + Numeric->itail) ;668ASSERT (nmark == 0) ;669670/* ---------------------------------------------------------------------- */671/* final tail pointer */672/* ---------------------------------------------------------------------- */673674ASSERT (pdest >= Numeric->Memory + Numeric->itail) ;675Numeric->itail = pdest - Numeric->Memory ;676pdest->header.prevsize = 0 ;677Numeric->ibig = EMPTY ;678Numeric->tail_usage = Numeric->size - Numeric->itail ;679680/* ---------------------------------------------------------------------- */681/* clear the unused E [nel+1 .. Work->elen - 1] */682/* ---------------------------------------------------------------------- */683684for (e = nel+1 ; e < Work->elen ; e++)685{686E [e] = 0 ;687}688689#ifndef NDEBUG690UMF_dump_packed_memory (Numeric, Work) ;691#endif692693DEBUG8 (("::::GARBAGE COLLECTION DONE::::\n")) ;694}695696697