Home My Page Projects Code Snippets Project Openings diderot
Summary Activity Tracker Tasks SCM

SCM Repository

[diderot] Annotation of /branches/vis12-cl/src/lib/common/dyn-seq.c
ViewVC logotype

Annotation of /branches/vis12-cl/src/lib/common/dyn-seq.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2402 - (view) (download) (as text)

1 : jhr 1733 /*! \file dyn-seq.c
2 :     *
3 :     * \author John Reppy
4 :     *
5 :     * An implementation of dynamic sequences.
6 :     */
7 :    
8 :     /*
9 :     * COPYRIGHT (c) 2012 The Diderot Project (http://diderot-language.cs.uchicago.edu)
10 :     * All rights reserved.
11 :     */
12 :    
13 :     #include "Diderot/diderot.h"
14 : jhr 1978 #include <teem/nrrd.h>
15 : jhr 1733
16 :     // compute the address of the i'th element in the sequence
17 :     STATIC_INLINE void* ElemAddr(void *base, size_t elemSz, unsigned int i)
18 :     {
19 :     return (void *)((char *)base + i*elemSz);
20 :     }
21 :    
22 :     //! append an element to a sequence
23 :     Diderot_DynSeq_t *Diderot_DynSeqAppend (size_t elemSz, Diderot_DynSeq_t *seq, void *item)
24 :     {
25 :     if (seq->nElems == seq->size) {
26 :     // grow the data array
27 :     unsigned int newSize = (seq->size < 64) ? seq->size + 8 : seq->size + 64;
28 :     void *newData = CheckedAlloc (elemSz * newSize);
29 :     Diderot_DynSeqCopy (elemSz, newData, seq);
30 :     seq->size = newSize;
31 :     seq->base = 0;
32 :     FREE(seq->data);
33 :     seq->data = newData;
34 :     }
35 :     unsigned int i = (seq->base + seq->nElems) % seq->size;
36 : jhr 1906 seq->nElems++;
37 : jhr 1733 memcpy(ElemAddr(seq->data, elemSz, i), item, elemSz);
38 :     return seq;
39 :     }
40 :    
41 :     //! prepend an element to a sequence
42 : jhr 2340 Diderot_DynSeq_t *Diderot_DynSeqPrepend (size_t elemSz, void *item, Diderot_DynSeq_t *seq)
43 :     {
44 :     if (seq->nElems == seq->size) {
45 :     // grow the data array; we leave room for item in the front
46 :     unsigned int newSize = (seq->size < 64) ? seq->size + 8 : seq->size + 64;
47 :     void *newData = CheckedAlloc (elemSz * newSize);
48 :     Diderot_DynSeqCopy (elemSz, ((char *)newData)+elemSz, seq);
49 :     seq->size = newSize;
50 :     seq->base = 1;
51 :     FREE(seq->data);
52 :     seq->data = newData;
53 :     }
54 :     unsigned int i = (seq->base == 0) ? (seq->size - 1) : (seq->base - 1);
55 :     seq->nElems++;
56 :     memcpy(ElemAddr(seq->data, elemSz, i), item, elemSz);
57 :     return seq;
58 :     }
59 : jhr 1733
60 :     //! concatenate two sequences
61 :     //Diderot_DynSeq_t *Diderot_DynSeqConcat (size_t elemSz, Diderot_DynSeq_t *, Diderot_DynSeq_t *);
62 :    
63 :     //! \brief copy the elements of a sequence to an array
64 :     //! \param elemSz the size of the sequence elements in bytes
65 :     //! \param dst the destination array
66 :     //! \param seq the source sequence
67 :     //! \return the address of the element that follows the array
68 :     void *Diderot_DynSeqCopy (size_t elemSz, void *dst, Diderot_DynSeq_t *seq)
69 :     {
70 :     unsigned int n = seq->nElems;
71 :     if (seq->base + n > seq->size) {
72 :     // sequence wraps around, so we need to copy it in two steps
73 :     n = seq->size - seq->base;
74 :     memcpy (dst, ElemAddr(seq->data, elemSz, seq->base), n*elemSz);
75 :     dst = (void *)((char *)dst + n*elemSz);
76 :     n = seq->nElems - n;
77 :     memcpy (dst, ElemAddr(seq->data, elemSz, 0), n*elemSz);
78 :     return (void *)((char *)dst + n*elemSz);
79 :     }
80 :     else {
81 :     size_t cpySz = n*elemSz;
82 :     memcpy (dst, ElemAddr(seq->data, elemSz, seq->base), cpySz);
83 :     return (void *)((char *)dst + cpySz);
84 :     }
85 :     }
86 : jhr 1978
87 :     static struct {
88 :     bool isFloat;
89 :     unsigned int sizeb;
90 :     } NrrdTypeInfo[nrrdTypeLast] = {
91 :     [nrrdTypeDefault] = {false, 0}, /* 0: signifies "determine output type for me" */
92 :     [nrrdTypeChar] = {false, 1}, /* 1: signed 1-byte integer */
93 :     [nrrdTypeUChar] = {false, 1}, /* 2: unsigned 1-byte integer */
94 :     [nrrdTypeShort] = {false, 2}, /* 3: signed 2-byte integer */
95 :     [nrrdTypeUShort] = {false, 2}, /* 4: unsigned 2-byte integer */
96 :     [nrrdTypeInt] = {false, 4}, /* 5: signed 4-byte integer */
97 :     [nrrdTypeUInt] = {false, 4}, /* 6: unsigned 4-byte integer */
98 :     [nrrdTypeLLong] = {false, 8}, /* 7: signed 8-byte integer */
99 :     [nrrdTypeULLong] = {false, 8}, /* 8: unsigned 8-byte integer */
100 :     [nrrdTypeFloat] = {true, 4}, /* 9: 4-byte floating point */
101 :     [nrrdTypeDouble] = {true, 8}, /* 10: 8-byte floating point */
102 :     [nrrdTypeBlock] = {false, 0}, /* 11: size user defined at run time; MUST BE LAST */
103 :     };
104 :    
105 :     //! Check that a nrrd has the expected structure for loading into a dynamic sequence
106 :     //! \param wrld the world; used to report errors
107 :     //! \param nin the nrrd to check
108 :     //! \param nDims the number of dimensions in the sequence elements
109 :     //! \param dims the array of sequence element dimensions
110 :     //! \return the number of values per element, or zero on error
111 :     static unsigned int CheckNrrd (
112 :     WorldPrefix_t *wrld,
113 :     Nrrd *nin,
114 :     unsigned int nDims,
115 :     unsigned int *dims)
116 :     {
117 :    
118 :     // compute the expected number of values per sequence element
119 :     unsigned int nValuesPerElem = 1;
120 :     for (unsigned int i = 0; i < nDims; i++) {
121 :     nValuesPerElem *= dims[i];
122 :     }
123 :    
124 :     // check the structure of the nrrd file
125 : jhr 2038 if (nin->spaceDim != 0) {
126 :     Diderot_Error (wrld, "unexpected number of axes in nrrd; expected 0, found %d\n",
127 : jhr 1978 nin->spaceDim);
128 :     return 0;
129 :     }
130 :     if (nin->dim - 1 != nDims) {
131 :     Diderot_Error (wrld, "unexpected nrrd dimension; expected %d, found %d\n",
132 :     nDims, nin->dim-1);
133 :     return 0;
134 :     }
135 :     for (unsigned int i = 0; i < nDims; i++) {
136 : jhr 2213 if (dims[i] != nin->axis[i].size) {
137 :     Diderot_Error (wrld,
138 :     "nrrd axis %d does not match expected dimension: %d != %d\n",
139 :     i+1, dims[i], nin->axis[i].size);
140 : jhr 1978 return 0;
141 :     }
142 :     }
143 : jhr 1979 if (NrrdTypeInfo[nin->type].sizeb == 0) {
144 : jhr 1978 Diderot_Error (wrld, "bogus element type %d in nrrd\n", nin->type);
145 :     return 0;
146 :     }
147 :    
148 :     return nValuesPerElem;
149 :     }
150 :    
151 : jhr 2033
152 : jhr 1978 //! load a dynamic sequence from a Nrrd file, where the sequence elements have real ground type.
153 :     //! \param wrld the world; used to report errors
154 :     //! \param nin the nrrd to check
155 :     //! \param nDims the number of dimensions in the sequence elements
156 :     //! \param dims the array of sequence element dimensions
157 :     //! \return the dynamic sequence, or zero on error
158 :     Diderot_DynSeq_t *Diderot_DynSeqLoadReal (
159 :     WorldPrefix_t *wrld,
160 :     Nrrd *nin,
161 :     unsigned int nDims,
162 :     unsigned int *dims)
163 :     {
164 :     unsigned int nValuesPerElem = CheckNrrd(wrld, nin, nDims, dims);
165 :     size_t elemSz = SIZEOF_DIDEROT_REAL * nValuesPerElem;
166 :    
167 :     if (nValuesPerElem == 0)
168 :     return (Diderot_DynSeq_t *)0;
169 :    
170 :     // get the number of elements
171 : jhr 2213 size_t nElems = nin->axis[nDims].size;
172 : jhr 1978
173 :     // allocate the dynamic sequence
174 :     Diderot_DynSeq_t *seq = Diderot_DynSeqAlloc(elemSz, nElems);
175 :    
176 :     // initialize the sequence from the nrrd
177 : jhr 1979 if (! NrrdTypeInfo[nin->type].isFloat || (NrrdTypeInfo[nin->type].sizeb != SIZEOF_DIDEROT_REAL)) {
178 : jhr 1978 // this is the slow path; we have to convert values as they are copied from the nrrd
179 :     #if defined(DIDEROT_DOUBLE_PRECISION)
180 :     double (*loadFn)(const void *) = nrrdDLoad[nin->type];
181 :     #else
182 :     float (*loadFn)(const void *) = nrrdFLoad[nin->type];
183 :     #endif
184 :     Diderot_real_t *dst = (Diderot_real_t *)seq->data;
185 :     char *src = (char *)nin->data;
186 : jhr 1979 size_t srcElemSz = NrrdTypeInfo[nin->type].sizeb;
187 : jhr 1978 for (size_t i = 0; i < nElems * nValuesPerElem; i++) {
188 :     *dst++ = loadFn(src);
189 :     src += srcElemSz;
190 :     }
191 :     }
192 :     else {
193 :     // this is the fast path, where we can just do a bulk memcpy
194 :     memcpy (seq->data, nin->data, nElems * elemSz);
195 :     }
196 :    
197 :     return seq;
198 :    
199 :     }
200 :    
201 :    
202 : jhr 2033 //! load a dynamic sequence from a Nrrd file, where the sequence elements have real ground type.
203 :     //! \param wrld the world; used to report errors
204 :     //! \param name the name of the nrrd file
205 :     //! \param nDims the number of dimensions in the sequence elements
206 :     //! \param dims the array of sequence element dimensions
207 :     //! \return the dynamic sequence, or zero on error
208 :     Diderot_DynSeq_t *Diderot_DynSeqLoadRealFromFile (
209 :     WorldPrefix_t *wrld,
210 :     const char *name,
211 :     unsigned int nDims,
212 :     unsigned int *dims)
213 :     {
214 :     Nrrd *nin = Diderot_LoadNrrdFile (wrld, name);
215 :     if (nin == 0)
216 :     return 0;
217 :     else
218 :     return Diderot_DynSeqLoadReal(wrld, nin, nDims, dims);
219 :    
220 :     }
221 :    
222 :    
223 : jhr 1978 //! load a dynamic sequence from a Nrrd file, where the sequence elements have int ground type.
224 :     //! \param wrld the world; used to report errors
225 :     //! \param nin the nrrd to check
226 :     //! \param nDims the number of dimensions in the sequence elements
227 :     //! \param dims the array of sequence element dimensions
228 :     //! \return the dynamic sequence, or zero on error
229 :     Diderot_DynSeq_t *Diderot_DynSeqLoadInt (
230 :     WorldPrefix_t *wrld,
231 :     Nrrd *nin,
232 :     unsigned int nDims,
233 :     unsigned int *dims)
234 :     {
235 :     unsigned int nValuesPerElem = CheckNrrd(wrld, nin, nDims, dims);
236 :     size_t elemSz = SIZEOF_DIDEROT_INT * nValuesPerElem;
237 :    
238 :     if (nValuesPerElem == 0)
239 :     return (Diderot_DynSeq_t *)0;
240 :    
241 : jhr 1979 if (NrrdTypeInfo[nin->type].isFloat) {
242 : jhr 1978 Diderot_Error (wrld, "expected integer element type for int sequence, but found %d\n", nin->type);
243 :     return 0;
244 :     }
245 :    
246 :     // get the number of elements
247 :     size_t nElems = nin->axis[0].size;
248 :    
249 :     // allocate the dynamic sequence
250 :     Diderot_DynSeq_t *seq = Diderot_DynSeqAlloc(elemSz, nElems);
251 :    
252 :     // initialize the sequence from the nrrd
253 : jhr 1979 if (NrrdTypeInfo[nin->type].sizeb != SIZEOF_DIDEROT_INT) {
254 : jhr 1978 // this is the slow path; we have to convert values as they are copied from the nrrd
255 :     int (*loadFn)(const void *) = nrrdILoad[nin->type];
256 :     Diderot_int_t *dst = (Diderot_int_t *)seq->data;
257 :     char *src = (char *)nin->data;
258 : jhr 1979 size_t srcElemSz = NrrdTypeInfo[nin->type].sizeb;
259 : jhr 1978 for (size_t i = 0; i < nElems * nValuesPerElem; i++) {
260 :     *dst++ = loadFn(src);
261 :     src += srcElemSz;
262 :     }
263 :     }
264 :     else {
265 :     // this is the fast path, where we can just do a bulk memcpy
266 :     memcpy (seq->data, nin->data, nElems * elemSz);
267 :     }
268 :    
269 :     return seq;
270 :    
271 :     }
272 :    
273 :    
274 : jhr 2033 //! load a dynamic sequence from a Nrrd file, where the sequence elements have int ground type.
275 :     //! \param wrld the world; used to report errors
276 :     //! \param name the name of the nrrd file
277 :     //! \param nDims the number of dimensions in the sequence elements
278 :     //! \param dims the array of sequence element dimensions
279 :     //! \return the dynamic sequence, or zero on error
280 :     Diderot_DynSeq_t *Diderot_DynSeqLoadIntFromFile (
281 :     WorldPrefix_t *wrld,
282 :     const char *name,
283 :     unsigned int nDims,
284 :     unsigned int *dims)
285 :     {
286 :     Nrrd *nin = Diderot_LoadNrrdFile (wrld, name);
287 :     if (nin == 0)
288 :     return 0;
289 :     else
290 :     return Diderot_DynSeqLoadInt(wrld, nin, nDims, dims);
291 :    
292 :     }
293 :    
294 :    
295 : jhr 1978 //! load a dynamic sequence from a Nrrd file, where the sequence elements have bool ground type.
296 :     //! \param wrld the world; used to report errors
297 :     //! \param nin the nrrd to check
298 :     //! \param nDims the number of dimensions in the sequence elements
299 :     //! \param dims the array of sequence element dimensions
300 :     //! \return the dynamic sequence, or zero on error
301 :     Diderot_DynSeq_t *Diderot_DynSeqLoadBool (
302 :     WorldPrefix_t *wrld,
303 :     Nrrd *nin,
304 :     unsigned int nDims,
305 :     unsigned int *dims)
306 :     {
307 :     unsigned int nValuesPerElem = CheckNrrd(wrld, nin, nDims, dims);
308 : jhr 1979 size_t elemSz = sizeof(bool) * nValuesPerElem;
309 : jhr 1978
310 :     if (nValuesPerElem == 0)
311 :     return (Diderot_DynSeq_t *)0;
312 :    
313 : jhr 1979 if (NrrdTypeInfo[nin->type].isFloat) {
314 : jhr 1978 Diderot_Error (wrld, "expected integer element type for bool sequence, but found %d\n", nin->type);
315 :     return 0;
316 :     }
317 :    
318 :     // get the number of elements
319 :     size_t nElems = nin->axis[0].size;
320 :    
321 :     // allocate the dynamic sequence
322 :     Diderot_DynSeq_t *seq = Diderot_DynSeqAlloc(elemSz, nElems);
323 :    
324 :     // initialize the sequence from the nrrd
325 : jhr 1979 if (NrrdTypeInfo[nin->type].sizeb != sizeof(bool)) {
326 : jhr 1978 // this is the slow path; we have to convert values as they are copied from the nrrd
327 :     int (*loadFn)(const void *) = nrrdILoad[nin->type];
328 :     bool *dst = (bool *)seq->data;
329 :     char *src = (char *)nin->data;
330 : jhr 1979 size_t srcElemSz = NrrdTypeInfo[nin->type].sizeb;
331 : jhr 1978 for (size_t i = 0; i < nElems * nValuesPerElem; i++) {
332 :     *dst++ = loadFn(src) ? true : false;
333 :     src += srcElemSz;
334 :     }
335 :     }
336 :     else {
337 :     // this is the fast path, where we can just do a bulk memcpy
338 :     memcpy (seq->data, nin->data, nElems * elemSz);
339 :     }
340 :    
341 :     return seq;
342 :    
343 :     }
344 : jhr 2033
345 :     //! load a dynamic sequence from a Nrrd file, where the sequence elements have bool ground type.
346 :     //! \param wrld the world; used to report errors
347 :     //! \param name the name of the nrrd file
348 :     //! \param nDims the number of dimensions in the sequence elements
349 :     //! \param dims the array of sequence element dimensions
350 :     //! \return the dynamic sequence, or zero on error
351 :     Diderot_DynSeq_t *Diderot_DynSeqLoadBoolFromFile (
352 :     WorldPrefix_t *wrld,
353 :     const char *name,
354 :     unsigned int nDims,
355 :     unsigned int *dims)
356 :     {
357 :     Nrrd *nin = Diderot_LoadNrrdFile (wrld, name);
358 :     if (nin == 0)
359 :     return 0;
360 :     else
361 :     return Diderot_DynSeqLoadBool(wrld, nin, nDims, dims);
362 :    
363 :     }

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0