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