Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_klu_memory.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === KLU_memory =========================================================== */
3 /* ========================================================================== */
4 
5 /* KLU memory management routines:
6  *
7  * KLU_malloc malloc wrapper
8  * KLU_free free wrapper
9  * KLU_realloc realloc wrapper
10  */
11 
12 #include "amesos_klu_internal.h"
13 
14 /* ========================================================================== */
15 /* === KLU_add_size_t ======================================================= */
16 /* ========================================================================== */
17 
18 /* Safely compute a+b, and check for size_t overflow */
19 
20 size_t KLU_add_size_t (size_t a, size_t b, Int *ok)
21 {
22  (*ok) = (*ok) && ((a + b) >= MAX (a,b)) ;
23  return ((*ok) ? (a + b) : ((size_t) -1)) ;
24 }
25 
26 /* ========================================================================== */
27 /* === KLU_mult_size_t ====================================================== */
28 /* ========================================================================== */
29 
30 /* Safely compute a*k, where k should be small, and check for size_t overflow */
31 
32 size_t KLU_mult_size_t (size_t a, size_t k, Int *ok)
33 {
34  size_t i, s = 0 ;
35  for (i = 0 ; i < k ; i++)
36  {
37  s = KLU_add_size_t (s, a, ok) ;
38  }
39  return ((*ok) ? s : ((size_t) -1)) ;
40 }
41 
42 /* ========================================================================== */
43 /* === KLU_malloc =========================================================== */
44 /* ========================================================================== */
45 
46 /* Wrapper around malloc routine (mxMalloc for a mexFunction). Allocates
47  * space of size MAX(1,n)*size, where size is normally a sizeof (...).
48  *
49  * This routine and KLU_realloc do not set Common->status to KLU_OK on success,
50  * so that a sequence of KLU_malloc's or KLU_realloc's can be used. If any of
51  * them fails, the Common->status will hold the most recent error status.
52  *
53  * Usage, for a pointer to Int:
54  *
55  * p = KLU_malloc (n, sizeof (Int), Common)
56  *
57  * Uses a pointer to the malloc routine (or its equivalent) defined in Common.
58  */
59 
60 void *KLU_malloc /* returns pointer to the newly malloc'd block */
61 (
62  /* ---- input ---- */
63  size_t n, /* number of items */
64  size_t size, /* size of each item */
65  /* --------------- */
66  KLU_common *Common
67 )
68 {
69  void *p ;
70  size_t s ;
71  Int ok = TRUE ;
72 
73  if (Common == NULL)
74  {
75  p = NULL ;
76  }
77  else if (size == 0)
78  {
79  /* size must be > 0 */
80  Common->status = KLU_INVALID ;
81  p = NULL ;
82  }
83  else if (n >= INT_MAX)
84  {
85  /* object is too big to allocate; p[i] where i is an Int will not
86  * be enough. */
87  Common->status = KLU_TOO_LARGE ;
88  p = NULL ;
89  }
90  else
91  {
92  /* call malloc, or its equivalent */
93  s = KLU_mult_size_t (MAX (1,n), size, &ok) ;
94  p = ok ? ((Common->malloc_memory) (s)) : NULL ;
95  if (p == NULL)
96  {
97  /* failure: out of memory */
98  Common->status = KLU_OUT_OF_MEMORY ;
99  }
100  else
101  {
102  Common->memusage += s ;
103  Common->mempeak = MAX (Common->mempeak, Common->memusage) ;
104  }
105  }
106  return (p) ;
107 }
108 
109 
110 /* ========================================================================== */
111 /* === KLU_free ============================================================= */
112 /* ========================================================================== */
113 
114 /* Wrapper around free routine (mxFree for a mexFunction). Returns NULL,
115  * which can be assigned to the pointer being freed, as in:
116  *
117  * p = KLU_free (p, n, sizeof (int), Common) ;
118  */
119 
120 void *KLU_free /* always returns NULL */
121 (
122  /* ---- in/out --- */
123  void *p, /* block of memory to free */
124  /* ---- input --- */
125  size_t n, /* size of block to free, in # of items */
126  size_t size, /* size of each item */
127  /* --------------- */
128  KLU_common *Common
129 )
130 {
131  size_t s ;
132  Int ok = TRUE ;
133  if (p != NULL && Common != NULL)
134  {
135  /* only free the object if the pointer is not NULL */
136  /* call free, or its equivalent */
137  (Common->free_memory) (p) ;
138  s = KLU_mult_size_t (MAX (1,n), size, &ok) ;
139  Common->memusage -= s ;
140  }
141  /* return NULL, and the caller should assign this to p. This avoids
142  * freeing the same pointer twice. */
143  return (NULL) ;
144 }
145 
146 
147 /* ========================================================================== */
148 /* === KLU_realloc ========================================================== */
149 /* ========================================================================== */
150 
151 /* Wrapper around realloc routine (mxRealloc for a mexFunction). Given a
152  * pointer p to a block allocated by KLU_malloc, it changes the size of the
153  * block pointed to by p to be MAX(1,nnew)*size in size. It may return a
154  * pointer different than p. This should be used as (for a pointer to Int):
155  *
156  * p = KLU_realloc (nnew, nold, sizeof (Int), p, Common) ;
157  *
158  * If p is NULL, this is the same as p = KLU_malloc (...).
159  * A size of nnew=0 is treated as nnew=1.
160  *
161  * If the realloc fails, p is returned unchanged and Common->status is set
162  * to KLU_OUT_OF_MEMORY. If successful, Common->status is not modified,
163  * and p is returned (possibly changed) and pointing to a large block of memory.
164  *
165  * Uses a pointer to the realloc routine (or its equivalent) defined in Common.
166  */
167 
168 void *KLU_realloc /* returns pointer to reallocated block */
169 (
170  /* ---- input ---- */
171  size_t nnew, /* requested # of items in reallocated block */
172  size_t nold, /* old # of items */
173  size_t size, /* size of each item */
174  /* ---- in/out --- */
175  void *p, /* block of memory to realloc */
176  /* --------------- */
177  KLU_common *Common
178 )
179 {
180  void *pnew ;
181  size_t snew, sold ;
182  Int ok = TRUE ;
183 
184  if (Common == NULL)
185  {
186  p = NULL ;
187  }
188  else if (size == 0)
189  {
190  /* size must be > 0 */
191  Common->status = KLU_INVALID ;
192  p = NULL ;
193  }
194  else if (p == NULL)
195  {
196  /* A fresh object is being allocated. */
197  p = KLU_malloc (nnew, size, Common) ;
198  }
199  else if (nnew >= INT_MAX)
200  {
201  /* failure: nnew is too big. Do not change p */
202  Common->status = KLU_TOO_LARGE ;
203  }
204  else
205  {
206  /* The object exists, and is changing to some other nonzero size. */
207  /* call realloc, or its equivalent */
208  snew = KLU_mult_size_t (MAX (1,nnew), size, &ok) ;
209  sold = KLU_mult_size_t (MAX (1,nold), size, &ok) ;
210  pnew = ok ? ((Common->realloc_memory) (p, snew)) : NULL ;
211  if (pnew == NULL)
212  {
213  /* Do not change p, since it still points to allocated memory */
214  Common->status = KLU_OUT_OF_MEMORY ;
215  }
216  else
217  {
218  /* success: return the new p and change the size of the block */
219  Common->memusage += (snew - sold) ;
220  Common->mempeak = MAX (Common->mempeak, Common->memusage) ;
221  p = pnew ;
222  }
223  }
224  return (p) ;
225 }
#define KLU_INVALID
size_t KLU_mult_size_t(size_t a, size_t k, Int *ok)
#define Int
void * KLU_malloc(size_t n, size_t size, KLU_common *Common)
size_t KLU_add_size_t(size_t a, size_t b, Int *ok)
#define MAX(a, b)
#define KLU_OUT_OF_MEMORY
void * KLU_realloc(size_t nnew, size_t nold, size_t size, void *p, KLU_common *Common)
#define NULL
#define KLU_TOO_LARGE
void * KLU_free(void *p, size_t n, size_t size, KLU_common *Common)
#define KLU_common
int n
#define TRUE