diff liboctave/UMFPACK/UMFPACK/Source/umf_mem_free_tail_block.c @ 5164:57077d0ddc8e

[project @ 2005-02-25 19:55:24 by jwe]
author jwe
date Fri, 25 Feb 2005 19:55:28 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/UMFPACK/UMFPACK/Source/umf_mem_free_tail_block.c	Fri Feb 25 19:55:28 2005 +0000
@@ -0,0 +1,142 @@
+/* ========================================================================== */
+/* === UMF_mem_free_tail_block ============================================== */
+/* ========================================================================== */
+
+/* -------------------------------------------------------------------------- */
+/* UMFPACK Version 4.4, 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                       */
+/* -------------------------------------------------------------------------- */
+
+/* The UMF_mem_* routines manage the Numeric->Memory memory space. */
+
+/* free a block from the tail of Numeric->memory */
+
+#include "umf_internal.h"
+
+GLOBAL void UMF_mem_free_tail_block
+(
+    NumericType *Numeric,
+    Int i
+)
+{
+    Unit *pprev, *pnext, *p, *pbig ;
+    Int sprev ;
+
+    ASSERT (Numeric != (NumericType *) NULL) ;
+    ASSERT (Numeric->Memory != (Unit *) NULL) ;
+    if (i == EMPTY || i == 0) return ;	/* already deallocated */
+
+    /* ---------------------------------------------------------------------- */
+    /* get the block */
+    /* ---------------------------------------------------------------------- */
+
+    p = Numeric->Memory + i ;
+
+    p-- ;	/* get the corresponding header */
+    DEBUG2 (("free block: p: "ID, (Int) (p-Numeric->Memory))) ;
+    ASSERT (p >= Numeric->Memory + Numeric->itail) ;
+    ASSERT (p < Numeric->Memory + Numeric->size) ;
+    ASSERT (p->header.size > 0) ;		/* block not already free */
+    ASSERT (p->header.prevsize >= 0) ;
+
+    Numeric->tail_usage -= p->header.size + 1 ;
+
+    /* ---------------------------------------------------------------------- */
+    /* merge with next free block, if any */
+    /* ---------------------------------------------------------------------- */
+
+    pnext = p + 1 + p->header.size ;
+    DEBUG2 (("size: "ID" next: "ID" ", p->header.size,
+	(Int) (pnext-Numeric->Memory))) ;
+    ASSERT (pnext < Numeric->Memory + Numeric->size) ;
+    ASSERT (pnext->header.prevsize == p->header.size) ;
+    ASSERT (pnext->header.size != 0) ;
+
+    if (pnext->header.size < 0)
+    {
+	/* next block is also free - merge with current block */
+	p->header.size += (-(pnext->header.size)) + 1 ;
+	DEBUG2 ((" NEXT FREE ")) ;
+    }
+
+    /* ---------------------------------------------------------------------- */
+    /* merge with previous free block, if any */
+    /* ---------------------------------------------------------------------- */
+
+#ifndef NDEBUG
+    if (p == Numeric->Memory + Numeric->itail)
+    {
+	DEBUG2 ((" at top of tail ")) ;
+	ASSERT (p->header.prevsize == 0) ;
+    }
+#endif
+
+    if (p > Numeric->Memory + Numeric->itail)
+    {
+	ASSERT (p->header.prevsize > 0) ;
+	pprev = p - 1 - p->header.prevsize ;
+	DEBUG2 ((" prev: "ID" ", (Int) (pprev-Numeric->Memory))) ;
+	ASSERT (pprev >= Numeric->Memory + Numeric->itail) ;
+	sprev = pprev->header.size ;
+	if (sprev < 0)
+	{
+	    /* previous block is also free - merge it with current block */
+	    ASSERT (p->header.prevsize == -sprev) ;
+	    pprev->header.size = p->header.size + (-sprev) + 1 ;
+	    p = pprev ;
+	    DEBUG2 ((" PREV FREE ")) ;
+	    /* note that p may now point to Numeric->itail */
+	}
+#ifndef NDEBUG
+	else
+	{
+	    ASSERT (p->header.prevsize == sprev) ;
+	}
+#endif
+    }
+
+    /* ---------------------------------------------------------------------- */
+    /* free the block, p */
+    /* ---------------------------------------------------------------------- */
+
+    pnext = p + 1 + p->header.size ;
+    ASSERT (pnext < Numeric->Memory + Numeric->size) ;
+
+    if (p == Numeric->Memory + Numeric->itail)
+    {
+	/* top block in list is freed */
+	Numeric->itail = pnext - Numeric->Memory ;
+	pnext->header.prevsize = 0 ;
+	DEBUG2 ((" NEW TAIL : "ID" ", Numeric->itail)) ;
+	ASSERT (pnext->header.size > 0) ;
+	if (Numeric->ibig != EMPTY && Numeric->ibig <= Numeric->itail)
+	{
+	    /* the big free block is now above the tail */
+	    Numeric->ibig = EMPTY ;
+	}
+    }
+    else
+    {
+	/* keep track of the biggest free block seen */
+	if (Numeric->ibig == EMPTY)
+	{
+	    Numeric->ibig = p - Numeric->Memory ;
+	}
+	else
+	{
+	    pbig = Numeric->Memory + Numeric->ibig ;
+	    if (-(pbig->header.size) < p->header.size)
+	    {
+		Numeric->ibig = p - Numeric->Memory ;
+	    }
+	}
+	/* flag the block as free, somewhere in the middle of the tail */
+	pnext->header.prevsize = p->header.size ;
+	p->header.size = -(p->header.size) ;
+    }
+
+    DEBUG2 (("new p: "ID" freesize: "ID"\n", (Int) (p-Numeric->Memory),
+	-(p->header.size))) ;
+
+}