Amesos Package Browser (Single Doxygen Collection) Development
amesos_klu_l_memory.c
Go to the documentation of this file.
00001 /* ========================================================================== */
00002 /* === KLU_memory =========================================================== */
00003 /* ========================================================================== */
00004 
00005 /* KLU memory management routines:
00006  *
00007  * KLU_malloc     malloc wrapper
00008  * KLU_free     free wrapper
00009  * KLU_realloc      realloc wrapper
00010  */
00011 
00012 /* This file should make the long int version of KLU */
00013 #define DLONG 1
00014 
00015 #include "amesos_klu_internal.h"
00016 
00017 /* ========================================================================== */
00018 /* === KLU_add_size_t ======================================================= */
00019 /* ========================================================================== */
00020 
00021 /* Safely compute a+b, and check for size_t overflow */
00022 
00023 size_t KLU_add_size_t (size_t a, size_t b, Int *ok)
00024 {
00025     (*ok) = (*ok) && ((a + b) >= MAX (a,b)) ;
00026     return ((*ok) ? (a + b) : ((size_t) -1)) ;
00027 }
00028 
00029 /* ========================================================================== */
00030 /* === KLU_mult_size_t ====================================================== */
00031 /* ========================================================================== */
00032 
00033 /* Safely compute a*k, where k should be small, and check for size_t overflow */
00034 
00035 size_t KLU_mult_size_t (size_t a, size_t k, Int *ok)
00036 {
00037     size_t i, s = 0 ;
00038     for (i = 0 ; i < k ; i++)
00039     {
00040   s = KLU_add_size_t (s, a, ok) ;
00041     }
00042     return ((*ok) ? s : ((size_t) -1)) ;
00043 }
00044 
00045 /* ========================================================================== */
00046 /* === KLU_malloc =========================================================== */
00047 /* ========================================================================== */
00048 
00049 /* Wrapper around malloc routine (mxMalloc for a mexFunction).  Allocates
00050  * space of size MAX(1,n)*size, where size is normally a sizeof (...).
00051  *
00052  * This routine and KLU_realloc do not set Common->status to KLU_OK on success,
00053  * so that a sequence of KLU_malloc's or KLU_realloc's can be used.  If any of
00054  * them fails, the Common->status will hold the most recent error status.
00055  *
00056  * Usage, for a pointer to Int:
00057  *
00058  *  p = KLU_malloc (n, sizeof (Int), Common)
00059  *
00060  * Uses a pointer to the malloc routine (or its equivalent) defined in Common.
00061  */
00062 
00063 void *KLU_malloc  /* returns pointer to the newly malloc'd block */
00064 (
00065     /* ---- input ---- */
00066     size_t n,   /* number of items */
00067     size_t size,  /* size of each item */
00068     /* --------------- */
00069     KLU_common *Common
00070 )
00071 {
00072     void *p ;
00073     size_t s ;
00074     Int ok = TRUE ;
00075 
00076     if (Common == NULL)
00077     {
00078   p = NULL ;
00079     }
00080     else if (size == 0)
00081     {
00082   /* size must be > 0 */
00083   Common->status = KLU_INVALID ;
00084   p = NULL ;
00085     }
00086     else if (n >= INT_MAX)
00087     {
00088   /* object is too big to allocate; p[i] where i is an Int will not
00089    * be enough. */
00090   Common->status = KLU_TOO_LARGE ;
00091   p = NULL ;
00092     }
00093     else
00094     {
00095   /* call malloc, or its equivalent */
00096   s = KLU_mult_size_t (MAX (1,n), size, &ok) ;
00097   p = ok ? ((Common->malloc_memory) (s)) : NULL ;
00098   if (p == NULL)
00099   {
00100       /* failure: out of memory */
00101       Common->status = KLU_OUT_OF_MEMORY ;
00102   }
00103   else
00104   {
00105       Common->memusage += s ;
00106       Common->mempeak = MAX (Common->mempeak, Common->memusage) ;
00107   }
00108     }
00109     return (p) ;
00110 }
00111 
00112 
00113 /* ========================================================================== */
00114 /* === KLU_free ============================================================= */
00115 /* ========================================================================== */
00116 
00117 /* Wrapper around free routine (mxFree for a mexFunction).  Returns NULL,
00118  * which can be assigned to the pointer being freed, as in:
00119  *
00120  *  p = KLU_free (p, n, sizeof (int), Common) ;
00121  */
00122 
00123 void *KLU_free    /* always returns NULL */
00124 (
00125     /* ---- in/out --- */
00126     void *p,    /* block of memory to free */
00127     /* ---- input --- */
00128     size_t n,   /* size of block to free, in # of items */
00129     size_t size,  /* size of each item */
00130     /* --------------- */
00131     KLU_common *Common
00132 )
00133 {
00134     size_t s ;
00135     Int ok = TRUE ;
00136     if (p != NULL && Common != NULL)
00137     {
00138   /* only free the object if the pointer is not NULL */
00139   /* call free, or its equivalent */
00140   (Common->free_memory) (p) ;
00141   s = KLU_mult_size_t (MAX (1,n), size, &ok) ;
00142   Common->memusage -= s ;
00143     }
00144     /* return NULL, and the caller should assign this to p.  This avoids
00145      * freeing the same pointer twice. */
00146     return (NULL) ;
00147 }
00148 
00149 
00150 /* ========================================================================== */
00151 /* === KLU_realloc ========================================================== */
00152 /* ========================================================================== */
00153 
00154 /* Wrapper around realloc routine (mxRealloc for a mexFunction).  Given a
00155  * pointer p to a block allocated by KLU_malloc, it changes the size of the
00156  * block pointed to by p to be MAX(1,nnew)*size in size.  It may return a
00157  * pointer different than p.  This should be used as (for a pointer to Int):
00158  *
00159  *  p = KLU_realloc (nnew, nold, sizeof (Int), p, Common) ;
00160  *
00161  * If p is NULL, this is the same as p = KLU_malloc (...).
00162  * A size of nnew=0 is treated as nnew=1.
00163  *
00164  * If the realloc fails, p is returned unchanged and Common->status is set
00165  * to KLU_OUT_OF_MEMORY.  If successful, Common->status is not modified,
00166  * and p is returned (possibly changed) and pointing to a large block of memory.
00167  *
00168  * Uses a pointer to the realloc routine (or its equivalent) defined in Common.
00169  */
00170 
00171 void *KLU_realloc /* returns pointer to reallocated block */
00172 (
00173     /* ---- input ---- */
00174     size_t nnew,  /* requested # of items in reallocated block */
00175     size_t nold,  /* old # of items */
00176     size_t size,  /* size of each item */
00177     /* ---- in/out --- */
00178     void *p,    /* block of memory to realloc */
00179     /* --------------- */
00180     KLU_common *Common
00181 )
00182 {
00183     void *pnew ;
00184     size_t snew, sold ;
00185     Int ok = TRUE ;
00186 
00187     if (Common == NULL)
00188     {
00189   p = NULL ;
00190     }
00191     else if (size == 0)
00192     {
00193   /* size must be > 0 */
00194   Common->status = KLU_INVALID ;
00195   p = NULL ;
00196     }
00197     else if (p == NULL)
00198     {
00199   /* A fresh object is being allocated. */
00200   p = KLU_malloc (nnew, size, Common) ;
00201     }
00202     else if (nnew >= INT_MAX)
00203     {
00204   /* failure: nnew is too big.  Do not change p */
00205   Common->status = KLU_TOO_LARGE ;
00206     }
00207     else
00208     {
00209   /* The object exists, and is changing to some other nonzero size. */
00210   /* call realloc, or its equivalent */
00211   snew = KLU_mult_size_t (MAX (1,nnew), size, &ok) ;
00212   sold = KLU_mult_size_t (MAX (1,nold), size, &ok) ;
00213   pnew = ok ? ((Common->realloc_memory) (p, snew)) : NULL ;
00214   if (pnew == NULL)
00215   {
00216       /* Do not change p, since it still points to allocated memory */
00217       Common->status = KLU_OUT_OF_MEMORY ;
00218   }
00219   else
00220   {
00221       /* success: return the new p and change the size of the block */
00222       Common->memusage += (snew - sold) ;
00223       Common->mempeak = MAX (Common->mempeak, Common->memusage) ;
00224       p = pnew ;
00225   }
00226     }
00227     return (p) ;
00228 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines