GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/gage/kind.c Lines: 55 126 43.7 %
Date: 2017-05-26 Branches: 43 80 53.8 %

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
******** gageKindCheck
29
**
30
** some some basic checking of the gageEntryItem array (the "table") for
31
** the sorts of mistakes that may be introduced by its hand-coding, although
32
** theoretically this is good for dynamically-generated gageKinds as well.
33
*/
34
int
35
gageKindCheck(const gageKind *kind) {
36
  static const char me[]="gageKindCheck";
37
  int pitem, pindex, alen;
38
  int ii, pi;
39
  gageItemEntry *item;
40
41
60688
  if (!kind) {
42
    biffAddf(GAGE, "%s: got NULL pointer", me);
43
    return 1;
44
  }
45
30344
  if (kind->itemMax > GAGE_ITEM_MAX) {
46
    biffAddf(GAGE, "%s: kind \"%s\" item max %d > GAGE_ITEM_MAX %d",
47
             me, kind->name, kind->itemMax, GAGE_ITEM_MAX);
48
    return 1;
49
  }
50
3449408
  for (ii=1; ii<=kind->itemMax; ii++) {
51
1694360
    item = kind->table + ii;
52
1694360
    if (ii != item->enumVal) {
53
      biffAddf(GAGE,
54
               "%s: \"%s\"-kind \"%s\" (item %d) has enumVal %d (not %d)",
55
               me, kind->name, airEnumStr(kind->enm, ii),
56
               ii, item->enumVal, ii);
57
      return 1;
58
    }
59
1694360
    alen = item->answerLength;
60
1694360
    if (!(1 <= alen)) {
61
      if (kind->dynamicAlloc) {
62
        biffAddf(GAGE, "%s: (dynamic) \"%s\"-kind \"%s\" (item %d) "
63
                 "answerLength (%d) not set?",
64
                 me, kind->name, airEnumStr(kind->enm, ii), ii, alen);
65
      } else {
66
        biffAddf(GAGE, "%s: \"%s\"-kind \"%s\" (item %d) has invalid "
67
                 "answerLength %d",
68
                 me, kind->name, airEnumStr(kind->enm, ii), ii, alen);
69
      }
70
      return 1;
71
    }
72

3388720
    if (!(AIR_IN_CL(0, item->needDeriv, GAGE_DERIV_MAX))) {
73
      biffAddf(GAGE,
74
               "%s: \"%s\"-kind \"%s\" (item %d) has invalid needDeriv %d "
75
               "(not in [0,%u])\n",
76
               me, kind->name, airEnumStr(kind->enm, ii),
77
               ii, item->needDeriv, GAGE_DERIV_MAX);
78
      return 1;
79
    }
80
30498480
    for (pi=0; pi<GAGE_ITEM_PREREQ_MAXNUM; pi++) {
81
13554880
      if (!( 0 <= item->prereq[pi] )) {
82
        if (kind->dynamicAlloc) {
83
          biffAddf(GAGE, "%s: (dynamic) \"%s\"-kind \"%s\" (item %d) "
84
                   "prereq %d (%d) not set?",
85
                   me, kind->name, airEnumStr(kind->enm, ii), ii,
86
                   pi, item->prereq[pi]);
87
        } else {
88
          biffAddf(GAGE, "%s: \"%s\"-kind \"%s\" (item %d) has invalid "
89
                   "prereq %d (%d)",
90
                   me, kind->name, airEnumStr(kind->enm, ii), ii,
91
                   pi, item->prereq[pi]);
92
        }
93
        return 1;
94
      }
95
    }
96
1694360
    pitem = item->parentItem;
97
1694360
    pindex = item->parentIndex;
98
1694360
    if (0 != pitem) {
99
330472
      if (1 == ii) {
100
        biffAddf(GAGE, "%s: first item (index 1) of \"%s\"-kind can't "
101
                 "be a sub-item (wanted parent index %d)",
102
                 me, kind->name, pitem);
103
        return 1;
104
      }
105

660944
      if (!(AIR_IN_CL(1, pitem, kind->itemMax))) {
106
        biffAddf(GAGE, "%s: item %d of \"%s\"-kind wants parent item %d "
107
                 "outside valid range [0..%d]",
108
                 me, ii, kind->name, pitem, kind->itemMax);
109
        return 1;
110
      }
111
330472
      if (0 != kind->table[pitem].parentItem) {
112
        biffAddf(GAGE, "%s: item %d of \"%s\"-kind has parent %d which "
113
                 "wants to have parent %d: can't have sub-sub-items",
114
                 me, ii, kind->name, pitem, kind->table[pitem].parentItem);
115
        return 1;
116
      }
117
660944
      if (!( 0 <= pindex
118
660944
             && ((unsigned int)pindex + alen
119
330472
                 <= kind->table[pitem].answerLength) )) {
120
        biffAddf(GAGE,
121
                 "%s: item %d of \"%s\"-kind wants index range [%d,%d] "
122
                 "of parent %d, which isn't in valid range [0,%d]",
123
                 me, ii, kind->name,
124
                 pindex, pindex + alen - 1,
125
                 pitem, kind->table[pitem].answerLength - 1);
126
        return 1;
127
      }
128
    }
129
  }
130
30344
  return 0;
131
30344
}
132
133
unsigned int
134
gageKindTotalAnswerLength(const gageKind *kind) {
135
  static const char me[]="gageKindTotalAnswerLength";
136
  char *err;
137
  unsigned int alen;
138
  int ii;
139
140
1310
  if (gageKindCheck(kind)) {
141
    err = biffGetDone(GAGE);
142
    fprintf(stderr, "%s: PANIC:\n %s", me, err);
143
    free(err); exit(1);
144
  }
145
  alen = 0;
146
53750
  for (ii=1; ii<=kind->itemMax; ii++) {
147
74138
    alen += (0 == kind->table[ii].parentItem
148
21698
             ? kind->table[ii].answerLength
149
             : 0);
150
  }
151
655
  return alen;
152
}
153
154
/*
155
** _gageKindAnswerOffset
156
**
157
** return the location of the item in the master answer array
158
**
159
** I don't think this will work if there are sub-sub-items
160
*/
161
int
162
_gageKindAnswerOffset(const gageKind *kind, int item) {
163
  int parent, ii;
164
165
1271820
  if (1 >= item) {
166
    /* the first item always has zero offset */
167
28393
    return 0;
168
  }
169
170
  /* else we're not the first */
171
607517
  parent = kind->table[item].parentItem;
172
607517
  if (0 != parent) {
173
    /* we're a sub-item */
174
9044
    return (kind->table[item].parentIndex
175
4522
            + _gageKindAnswerOffset(kind, parent));
176
  }
177
178
  /* else we're not a sub-item: find the first previous non-sub-item */
179
602995
  ii = item-1;
180
1479222
  while (0 != kind->table[ii].parentItem) {
181
    /* gageKindCheck ensures that item 1 is not a sub-item */
182
136616
    ii--;
183
  }
184
1205990
  return (kind->table[ii].answerLength
185
602995
          + _gageKindAnswerOffset(kind, ii));
186
635910
}
187
188
unsigned int
189
gageKindAnswerLength(const gageKind *kind, int item) {
190
  static const char me[]="gageKindAnswerLength";
191
  char *err;
192
193
2592
  if (gageKindCheck(kind)) {
194
    err = biffGetDone(GAGE);
195
    fprintf(stderr, "%s: PANIC:\n %s", me, err);
196
    free(err); exit(1);
197
  }
198
199
3888
  return (!airEnumValCheck(kind->enm, item)
200
1296
          ? kind->table[item].answerLength
201
          : 0);
202
}
203
204
int
205
gageKindAnswerOffset(const gageKind *kind, int item) {
206
  static const char me[]="gageKindAnswerOffset";
207
  char *err;
208
209
56786
  if (gageKindCheck(kind)) {
210
    err = biffGetDone(GAGE);
211
    fprintf(stderr, "%s: PANIC:\n %s", me, err);
212
    free(err); exit(1);
213
  }
214
215
28393
  return _gageKindAnswerOffset(kind, item);
216
}
217
218
/*
219
** so that you can see if a given volume will work as the given kind
220
*/
221
int
222
gageKindVolumeCheck(const gageKind *kind, const Nrrd *nrrd) {
223
  static const char me[]="gageKindVolumeCheck";
224
225
694
  if (!(kind && nrrd)) {
226
    biffAddf(GAGE, "%s: got NULL pointer", me);
227
    return 1;
228
  }
229
347
  if (nrrdCheck(nrrd)) {
230
    biffMovef(GAGE, NRRD, "%s: problem with nrrd", me);
231
    return 1;
232
  }
233
347
  if (!(nrrd->dim == 3 + kind->baseDim)) {
234
    biffAddf(GAGE, "%s: nrrd should be %u-D, not %u-D",
235
             me, 3 + kind->baseDim, nrrd->dim);
236
    return 1;
237
  }
238
347
  if (nrrdTypeBlock == nrrd->type) {
239
    biffAddf(GAGE, "%s: can't handle %s-type volumes", me,
240
             airEnumStr(nrrdType, nrrdTypeBlock));
241
    return 1;
242
  }
243
347
  if (kind->baseDim) {
244
24
    char stmp[AIR_STRLEN_SMALL];
245
24
    if (1 == kind->baseDim) {
246
24
      if (kind->valLen != nrrd->axis[0].size) {
247
        biffAddf(GAGE, "%s: %s kind needs %u axis 0 values, not %s", me,
248
                 kind->name, kind->valLen,
249
                 airSprintSize_t(stmp, nrrd->axis[0].size));
250
        return 1;
251
      }
252
    } else {
253
      /* actually there is yet to be a kind in Teem for which
254
         kind->baseDim > 1, but this code would work in that case */
255
      unsigned int axi;
256
      size_t numsub; /* number of samples sub base dim */
257
      numsub = 1;
258
      for (axi=0; axi<kind->baseDim; axi++) {
259
        numsub *= nrrd->axis[axi].size;
260
      }
261
      if (kind->valLen != numsub) {
262
        biffAddf(GAGE, "%s: %s kind needs %u values below baseDim axis %u, "
263
                 "not %s", me, kind->name,kind->valLen, kind->baseDim,
264
                 airSprintSize_t(stmp, numsub));
265
        return 1;
266
      }
267
    }
268
48
  }
269
  /* this eventually calls _gageShapeSet(), which, for purely historical
270
     reasons, does the brunt of the error checking, some of which is almost
271
     certainly redundant with checks above . . . */
272
347
  if (gageVolumeCheck(NULL, nrrd, kind)) {
273
    biffAddf(GAGE, "%s: trouble", me);
274
    return 1;
275
  }
276
347
  return 0;
277
347
}