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