GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* |
||
2 |
Teem: Tools to process and visualize scientific data and images . |
||
3 |
Copyright (C) 2013, 2012, 2011, 2010, 2009 University of Chicago |
||
4 |
Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann |
||
5 |
Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah |
||
6 |
|||
7 |
This library is free software; you can redistribute it and/or |
||
8 |
modify it under the terms of the GNU Lesser General Public License |
||
9 |
(LGPL) as published by the Free Software Foundation; either |
||
10 |
version 2.1 of the License, or (at your option) any later version. |
||
11 |
The terms of redistributing and/or modifying this software also |
||
12 |
include exceptions to the LGPL that facilitate static linking. |
||
13 |
|||
14 |
This library is distributed in the hope that it will be useful, |
||
15 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
16 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||
17 |
Lesser General Public License for more details. |
||
18 |
|||
19 |
You should have received a copy of the GNU Lesser General Public License |
||
20 |
along with this library; if not, write to Free Software Foundation, Inc., |
||
21 |
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||
22 |
*/ |
||
23 |
|||
24 |
#include "gage.h" |
||
25 |
#include "privateGage.h" |
||
26 |
|||
27 |
/* |
||
28 |
******** gageVolumeCheck() |
||
29 |
** |
||
30 |
** checks whether a given volume is valid for the given kind |
||
31 |
** and the given parameter settings in the context |
||
32 |
** |
||
33 |
** Note that ctx is simply passed to _gageShapeSet(), with no NULL-ity |
||
34 |
** test- which is fine- it just means that the check is not specific |
||
35 |
** to the parameters that can be set in the gageContext. |
||
36 |
*/ |
||
37 |
int |
||
38 |
gageVolumeCheck(const gageContext *ctx, const Nrrd *nin, |
||
39 |
const gageKind *kind) { |
||
40 |
static const char me[]="gageVolumeCheck"; |
||
41 |
694 |
gageShape shape; |
|
42 |
|||
43 |
347 |
gageShapeReset(&shape); |
|
44 |
✗✓ | 347 |
if (_gageShapeSet(ctx, &shape, nin, kind->baseDim)) { |
45 |
biffAddf(GAGE, "%s: trouble setting volume as %s kind", me, kind->name); |
||
46 |
return 1; |
||
47 |
} |
||
48 |
347 |
return 0; |
|
49 |
347 |
} |
|
50 |
|||
51 |
/* |
||
52 |
******** gagePerVolumeNew() |
||
53 |
** |
||
54 |
** creates a new pervolume of a known kind, but nothing besides the |
||
55 |
** answer array is allocated |
||
56 |
** |
||
57 |
** uses biff primarily because of the error checking in gageVolumeCheck() |
||
58 |
*/ |
||
59 |
gagePerVolume * |
||
60 |
gagePerVolumeNew(gageContext *ctx, const Nrrd *nin, const gageKind *kind) { |
||
61 |
static const char me[]="gagePerVolumeNew"; |
||
62 |
gagePerVolume *pvl; |
||
63 |
int ii; |
||
64 |
airArray *mop; |
||
65 |
|||
66 |
✗✓ | 694 |
if (!( nin && kind )) { |
67 |
biffAddf(GAGE, "%s: got NULL pointer (%p, %p, or %p)", me, |
||
68 |
AIR_VOIDP(ctx), AIR_CVOIDP(nin), AIR_CVOIDP(kind)); |
||
69 |
return NULL; |
||
70 |
} |
||
71 |
/* Craziness: since circa 2003, the test below was to call gageVolumeCheck, |
||
72 |
which is now just a wrapper around _gageShapeSet(), and which never |
||
73 |
actually does the important checks of gageKindVolumeCheck (which in turn |
||
74 |
eventually calls gageVolumeCheck). This means that basic errors were not |
||
75 |
being caught, like having the wrong number of samples along axis 0 for |
||
76 |
non-scalar kinds. These various functions need to be simplified soon */ |
||
77 |
✗✓ | 347 |
if (gageKindVolumeCheck(kind, nin)) { |
78 |
biffAddf(GAGE, "%s: problem with volume as %s kind", me, kind->name); |
||
79 |
return NULL; |
||
80 |
} |
||
81 |
347 |
pvl = AIR_CALLOC(1, gagePerVolume); |
|
82 |
✗✓ | 347 |
if (!pvl) { |
83 |
biffAddf(GAGE, "%s: couldn't alloc gagePerVolume", me); |
||
84 |
return NULL; |
||
85 |
} |
||
86 |
347 |
mop = airMopNew(); |
|
87 |
347 |
airMopAdd(mop, pvl, airFree, airMopOnError); |
|
88 |
347 |
pvl->verbose = gageDefVerbose; |
|
89 |
347 |
pvl->kind = kind; |
|
90 |
347 |
GAGE_QUERY_RESET(pvl->query); |
|
91 |
✓✓ | 2776 |
for (ii=0; ii<=GAGE_DERIV_MAX; ii++) { |
92 |
1041 |
ctx->needD[ii] = AIR_FALSE; |
|
93 |
} |
||
94 |
347 |
pvl->nin = nin; |
|
95 |
✓✓ | 2776 |
for (ii=gagePvlFlagUnknown+1; ii<gagePvlFlagLast; ii++) { |
96 |
1041 |
pvl->flag[ii] = AIR_FALSE; |
|
97 |
} |
||
98 |
347 |
pvl->iv3 = pvl->iv2 = pvl->iv1 = NULL; |
|
99 |
347 |
pvl->lup = nrrdDLookup[nin->type]; |
|
100 |
347 |
pvl->answer = AIR_CALLOC(gageKindTotalAnswerLength(kind), double); |
|
101 |
347 |
airMopAdd(mop, pvl->answer, airFree, airMopOnError); |
|
102 |
347 |
pvl->directAnswer = AIR_CALLOC(kind->itemMax+1, double*); |
|
103 |
347 |
airMopAdd(mop, pvl->directAnswer, airFree, airMopOnError); |
|
104 |
✓✗✗✓ |
694 |
if (!(pvl->answer && pvl->directAnswer)) { |
105 |
biffAddf(GAGE, "%s: couldn't alloc answer and directAnswer arrays", me); |
||
106 |
airMopError(mop); return NULL; |
||
107 |
} |
||
108 |
✓✓ | 28318 |
for (ii=1; ii<=kind->itemMax; ii++) { |
109 |
13812 |
pvl->directAnswer[ii] = pvl->answer + gageKindAnswerOffset(kind, ii); |
|
110 |
} |
||
111 |
347 |
pvl->flag[gagePvlFlagVolume] = AIR_TRUE; |
|
112 |
✓✓ | 347 |
if (kind->pvlDataNew) { |
113 |
✗✓ | 16 |
if (!(pvl->data = kind->pvlDataNew(kind))) { |
114 |
biffAddf(GAGE, "%s: double creating gagePerVolume data", me); |
||
115 |
airMopError(mop); return NULL; |
||
116 |
} |
||
117 |
} else { |
||
118 |
331 |
pvl->data = NULL; |
|
119 |
} |
||
120 |
|||
121 |
347 |
airMopOkay(mop); |
|
122 |
347 |
return pvl; |
|
123 |
347 |
} |
|
124 |
|||
125 |
/* |
||
126 |
** _gagePerVolumeCopy() |
||
127 |
** |
||
128 |
** copies a pervolume for use in a copied context, and probably |
||
129 |
** should only be called by gageContextCopy() |
||
130 |
*/ |
||
131 |
gagePerVolume * |
||
132 |
_gagePerVolumeCopy(gagePerVolume *pvl, unsigned int fd) { |
||
133 |
static const char me[]="gagePerVolumeCopy"; |
||
134 |
gagePerVolume *nvl; |
||
135 |
int ii; |
||
136 |
airArray *mop; |
||
137 |
|||
138 |
616 |
nvl = AIR_CALLOC(1, gagePerVolume); |
|
139 |
✗✓ | 308 |
if (!nvl) { |
140 |
biffAddf(GAGE, "%s: couldn't create new pervolume", me); |
||
141 |
return NULL; |
||
142 |
} |
||
143 |
308 |
mop = airMopNew(); |
|
144 |
308 |
airMopAdd(mop, nvl, airFree, airMopOnError); |
|
145 |
/* we should probably restrict ourselves to gage API calls, but given the |
||
146 |
constant state of gage construction, this seems much simpler. |
||
147 |
Pointers to per-pervolume-allocated arrays are fixed below */ |
||
148 |
308 |
memcpy(nvl, pvl, sizeof(gagePerVolume)); |
|
149 |
308 |
nvl->iv3 = AIR_CALLOC(fd*fd*fd*nvl->kind->valLen, double); |
|
150 |
308 |
nvl->iv2 = AIR_CALLOC(fd*fd*nvl->kind->valLen, double); |
|
151 |
308 |
nvl->iv1 = AIR_CALLOC(fd*nvl->kind->valLen, double); |
|
152 |
308 |
airMopAdd(mop, nvl->iv3, airFree, airMopOnError); |
|
153 |
308 |
airMopAdd(mop, nvl->iv2, airFree, airMopOnError); |
|
154 |
308 |
airMopAdd(mop, nvl->iv1, airFree, airMopOnError); |
|
155 |
308 |
nvl->answer = AIR_CALLOC(gageKindTotalAnswerLength(nvl->kind), double); |
|
156 |
308 |
airMopAdd(mop, nvl->answer, airFree, airMopOnError); |
|
157 |
308 |
nvl->directAnswer = AIR_CALLOC(nvl->kind->itemMax+1, double*); |
|
158 |
308 |
airMopAdd(mop, nvl->directAnswer, airFree, airMopOnError); |
|
159 |
✓✗✓✗ ✗✓ |
1232 |
if (!( nvl->iv3 && nvl->iv2 && nvl->iv1 |
160 |
✓✗✓✗ |
924 |
&& nvl->answer && nvl->directAnswer )) { |
161 |
biffAddf(GAGE, "%s: couldn't allocate all caches " |
||
162 |
"(fd=%u, valLen=%u, totAnsLen=%u, itemMax=%u)", me, |
||
163 |
fd, nvl->kind->valLen, gageKindTotalAnswerLength(nvl->kind), |
||
164 |
nvl->kind->itemMax); |
||
165 |
airMopError(mop); return NULL; |
||
166 |
} |
||
167 |
✓✓ | 25432 |
for (ii=1; ii<=pvl->kind->itemMax; ii++) { |
168 |
12408 |
nvl->directAnswer[ii] = nvl->answer + gageKindAnswerOffset(pvl->kind, ii); |
|
169 |
} |
||
170 |
✓✓ | 308 |
if (pvl->kind->pvlDataCopy) { |
171 |
✗✓ | 16 |
if (!(nvl->data = pvl->kind->pvlDataCopy(pvl->kind, pvl->data))) { |
172 |
biffAddf(GAGE, "%s: double copying gagePerVolume data", me); |
||
173 |
airMopError(mop); return NULL; |
||
174 |
} |
||
175 |
/* HEY: pvlDataNix takes 2 arguments; so we can't mop nvl->data, |
||
176 |
so its a good thing that we created nvl->data last */ |
||
177 |
} else { |
||
178 |
292 |
nvl->data = NULL; |
|
179 |
} |
||
180 |
|||
181 |
308 |
airMopOkay(mop); |
|
182 |
308 |
return nvl; |
|
183 |
308 |
} |
|
184 |
|||
185 |
/* |
||
186 |
******** gagePerVolumeNix() |
||
187 |
** |
||
188 |
** frees all dynamically allocated memory assocated with a pervolume |
||
189 |
** |
||
190 |
** does not use biff |
||
191 |
*/ |
||
192 |
gagePerVolume * |
||
193 |
gagePerVolumeNix(gagePerVolume *pvl) { |
||
194 |
|||
195 |
✓✗ | 1110 |
if (pvl) { |
196 |
✓✓ | 555 |
if (pvl->kind->pvlDataNix) { |
197 |
32 |
pvl->data = pvl->kind->pvlDataNix(pvl->kind, pvl->data); |
|
198 |
32 |
} |
|
199 |
555 |
pvl->iv3 = (double *)airFree(pvl->iv3); |
|
200 |
555 |
pvl->iv2 = (double *)airFree(pvl->iv2); |
|
201 |
555 |
pvl->iv1 = (double *)airFree(pvl->iv1); |
|
202 |
555 |
pvl->answer = (double *)airFree(pvl->answer); |
|
203 |
555 |
pvl->directAnswer = (double **)airFree(pvl->directAnswer); |
|
204 |
555 |
airFree(pvl); |
|
205 |
555 |
} |
|
206 |
555 |
return NULL; |
|
207 |
} |
||
208 |
|||
209 |
/* |
||
210 |
******** gageAnswerPointer() |
||
211 |
** |
||
212 |
** way of getting a pointer to a specific answer in a pervolume's ans array |
||
213 |
** |
||
214 |
** Returns NULL if the item is invalid, but there is no other error checking. |
||
215 |
** In particular, this does not let you know if the item is actually part |
||
216 |
** of the current query. |
||
217 |
** |
||
218 |
*/ |
||
219 |
const double * |
||
220 |
gageAnswerPointer(const gageContext *ctx, const gagePerVolume *pvl, int item) { |
||
221 |
const double *ret; |
||
222 |
|||
223 |
AIR_UNUSED(ctx); |
||
224 |
✓✗✓✗ |
6519 |
if (pvl && !airEnumValCheck(pvl->kind->enm, item)) { |
225 |
2173 |
ret = pvl->answer + gageKindAnswerOffset(pvl->kind, item); |
|
226 |
2173 |
} else { |
|
227 |
ret = NULL; |
||
228 |
} |
||
229 |
2173 |
return ret; |
|
230 |
} |
||
231 |
|||
232 |
/* non-const version of the above */ |
||
233 |
double * |
||
234 |
_gageAnswerPointer(const gageContext *ctx, gagePerVolume *pvl, int item) { |
||
235 |
double *ret; |
||
236 |
|||
237 |
AIR_UNUSED(ctx); |
||
238 |
if (pvl && !airEnumValCheck(pvl->kind->enm, item)) { |
||
239 |
ret = pvl->answer + gageKindAnswerOffset(pvl->kind, item); |
||
240 |
} else { |
||
241 |
ret = NULL; |
||
242 |
} |
||
243 |
return ret; |
||
244 |
} |
||
245 |
|||
246 |
unsigned int |
||
247 |
gageAnswerLength(const gageContext *ctx, const gagePerVolume *pvl, int item) { |
||
248 |
unsigned int ret; |
||
249 |
|||
250 |
AIR_UNUSED(ctx); |
||
251 |
✓✗✓✗ |
3888 |
if (pvl && !airEnumValCheck(pvl->kind->enm, item)) { |
252 |
1296 |
ret = gageKindAnswerLength(pvl->kind, item); |
|
253 |
1296 |
} else { |
|
254 |
ret = 0; |
||
255 |
} |
||
256 |
1296 |
return ret; |
|
257 |
} |
||
258 |
|||
259 |
int |
||
260 |
gageQueryReset(gageContext *ctx, gagePerVolume *pvl) { |
||
261 |
static const char me[]="gageQueryReset"; |
||
262 |
|||
263 |
AIR_UNUSED(ctx); |
||
264 |
if (!( pvl )) { |
||
265 |
biffAddf(GAGE, "%s: got NULL pointer", me); |
||
266 |
return 1; |
||
267 |
} |
||
268 |
|||
269 |
GAGE_QUERY_RESET(pvl->query); |
||
270 |
|||
271 |
return 0; |
||
272 |
} |
||
273 |
|||
274 |
|||
275 |
/* |
||
276 |
******** gageQuerySet() |
||
277 |
** |
||
278 |
** sets a query in a pervolume. Does recursive expansion of query |
||
279 |
** to cover all prerequisite measures. |
||
280 |
** |
||
281 |
** Sets: pvl->query |
||
282 |
** |
||
283 |
** the gageContext is not actually used here, but I'm cautiously |
||
284 |
** including it in case its used in the future. |
||
285 |
*/ |
||
286 |
int |
||
287 |
gageQuerySet(gageContext *ctx, gagePerVolume *pvl, gageQuery query) { |
||
288 |
static const char me[]="gageQuerySet"; |
||
289 |
gageQuery lastQuery; |
||
290 |
int pi, ii; |
||
291 |
|||
292 |
AIR_UNUSED(ctx); |
||
293 |
✗✓ | 2498 |
if (!( pvl )) { |
294 |
biffAddf(GAGE, "%s: got NULL pointer", me); |
||
295 |
return 1; |
||
296 |
} |
||
297 |
1249 |
GAGE_QUERY_COPY(pvl->query, query); |
|
298 |
✗✓ | 1249 |
if (pvl->verbose) { |
299 |
fprintf(stderr, "%s: original ", me); |
||
300 |
gageQueryPrint(stderr, pvl->kind, pvl->query); |
||
301 |
} |
||
302 |
/* recursive expansion of prerequisites */ |
||
303 |
do { |
||
304 |
1257 |
GAGE_QUERY_COPY(lastQuery, pvl->query); |
|
305 |
1257 |
ii = pvl->kind->itemMax+1; |
|
306 |
1257 |
do { |
|
307 |
54573 |
ii--; |
|
308 |
✓✓ | 54573 |
if (GAGE_QUERY_ITEM_TEST(pvl->query, ii)) { |
309 |
✓✓ | 48420 |
for (pi=0; pi<GAGE_ITEM_PREREQ_MAXNUM; pi++) { |
310 |
✓✓ | 21520 |
if (0 != pvl->kind->table[ii].prereq[pi]) { |
311 |
571 |
GAGE_QUERY_ITEM_ON(pvl->query, pvl->kind->table[ii].prereq[pi]); |
|
312 |
571 |
} |
|
313 |
} |
||
314 |
} |
||
315 |
✓✓ | 54573 |
} while (ii); |
316 |
✓✓✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✓ |
41233 |
} while (!GAGE_QUERY_EQUAL(pvl->query, lastQuery)); |
317 |
✗✓ | 1249 |
if (pvl->verbose) { |
318 |
fprintf(stderr, "%s: expanded ", me); |
||
319 |
gageQueryPrint(stderr, pvl->kind, pvl->query); |
||
320 |
} |
||
321 |
|||
322 |
/* doing this kind of error checking here is not really |
||
323 |
the way gage should work-- it should be done at the |
||
324 |
time of gageUpdate()-- but the novelty of pvl->data |
||
325 |
encourages putting new smarts at superficial levels |
||
326 |
instead of deeper levels */ |
||
327 |
✓✓ | 1249 |
if (!pvl->data) { |
328 |
✓✓ | 87450 |
for (ii=1; ii<=pvl->kind->itemMax; ii++) { |
329 |
✗✓ | 45006 |
if (GAGE_QUERY_ITEM_TEST(pvl->query, ii) |
330 |
✓✓ | 45006 |
&& pvl->kind->table[ii].needData) { |
331 |
biffAddf(GAGE, "%s: item %d (%s) needs data, but pvl->data is NULL", |
||
332 |
me, ii, airEnumStr(pvl->kind->enm, ii)); |
||
333 |
return 1; |
||
334 |
} |
||
335 |
} |
||
336 |
} |
||
337 |
|||
338 |
1249 |
pvl->flag[gagePvlFlagQuery] = AIR_TRUE; |
|
339 |
|||
340 |
1249 |
return 0; |
|
341 |
1249 |
} |
|
342 |
|||
343 |
int |
||
344 |
gageQueryAdd(gageContext *ctx, gagePerVolume *pvl, gageQuery query) { |
||
345 |
static const char me[]="gageQueryAdd"; |
||
346 |
|||
347 |
if (!( pvl )) { |
||
348 |
biffAddf(GAGE, "%s: got NULL pointer", me); |
||
349 |
return 1; |
||
350 |
} |
||
351 |
|||
352 |
GAGE_QUERY_ADD(pvl->query, query); |
||
353 |
if (gageQuerySet(ctx, pvl, pvl->query)) { |
||
354 |
biffAddf(GAGE, "%s: trouble", me); |
||
355 |
return 1; |
||
356 |
} |
||
357 |
|||
358 |
return 0; |
||
359 |
} |
||
360 |
|||
361 |
int |
||
362 |
gageQueryItemOn(gageContext *ctx, gagePerVolume *pvl, int item) { |
||
363 |
static const char me[]="gageQueryItemOn"; |
||
364 |
|||
365 |
✗✓ | 2498 |
if (!( pvl )) { |
366 |
biffAddf(GAGE, "%s: got NULL pointer", me); |
||
367 |
return 1; |
||
368 |
} |
||
369 |
|||
370 |
✗✓ | 1249 |
if (airEnumValCheck(pvl->kind->enm, item)) { |
371 |
biffAddf(GAGE, "%s: %d not a valid %s value", me, |
||
372 |
item, pvl->kind->enm->name); |
||
373 |
return 1; |
||
374 |
} |
||
375 |
1249 |
GAGE_QUERY_ITEM_ON(pvl->query, item); |
|
376 |
✗✓ | 1249 |
if (gageQuerySet(ctx, pvl, pvl->query)) { |
377 |
biffAddf(GAGE, "%s: trouble", me); |
||
378 |
return 1; |
||
379 |
} |
||
380 |
|||
381 |
1249 |
return 0; |
|
382 |
1249 |
} |
|
383 |
Generated by: GCOVR (Version 3.3) |