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

SCM Repository

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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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