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 1979 - (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 :     //Diderot_DynSeq_t *Diderot_DynSeqPrepend (size_t elemSz, void *, Diderot_DynSeq_t *);
43 :    
44 :     //! concatenate two sequences
45 :     //Diderot_DynSeq_t *Diderot_DynSeqConcat (size_t elemSz, Diderot_DynSeq_t *, Diderot_DynSeq_t *);
46 :    
47 :     //! \brief copy the elements of a sequence to an array
48 :     //! \param elemSz the size of the sequence elements in bytes
49 :     //! \param dst the destination array
50 :     //! \param seq the source sequence
51 :     //! \return the address of the element that follows the array
52 :     void *Diderot_DynSeqCopy (size_t elemSz, void *dst, Diderot_DynSeq_t *seq)
53 :     {
54 :     unsigned int n = seq->nElems;
55 :     if (seq->base + n > seq->size) {
56 :     // sequence wraps around, so we need to copy it in two steps
57 :     n = seq->size - seq->base;
58 :     memcpy (dst, ElemAddr(seq->data, elemSz, seq->base), n*elemSz);
59 :     dst = (void *)((char *)dst + n*elemSz);
60 :     n = seq->nElems - n;
61 :     memcpy (dst, ElemAddr(seq->data, elemSz, 0), n*elemSz);
62 :     return (void *)((char *)dst + n*elemSz);
63 :     }
64 :     else {
65 :     size_t cpySz = n*elemSz;
66 :     memcpy (dst, ElemAddr(seq->data, elemSz, seq->base), cpySz);
67 :     return (void *)((char *)dst + cpySz);
68 :     }
69 :     }
70 : jhr 1978
71 :     static struct {
72 :     bool isFloat;
73 :     unsigned int sizeb;
74 :     } NrrdTypeInfo[nrrdTypeLast] = {
75 :     [nrrdTypeDefault] = {false, 0}, /* 0: signifies "determine output type for me" */
76 :     [nrrdTypeChar] = {false, 1}, /* 1: signed 1-byte integer */
77 :     [nrrdTypeUChar] = {false, 1}, /* 2: unsigned 1-byte integer */
78 :     [nrrdTypeShort] = {false, 2}, /* 3: signed 2-byte integer */
79 :     [nrrdTypeUShort] = {false, 2}, /* 4: unsigned 2-byte integer */
80 :     [nrrdTypeInt] = {false, 4}, /* 5: signed 4-byte integer */
81 :     [nrrdTypeUInt] = {false, 4}, /* 6: unsigned 4-byte integer */
82 :     [nrrdTypeLLong] = {false, 8}, /* 7: signed 8-byte integer */
83 :     [nrrdTypeULLong] = {false, 8}, /* 8: unsigned 8-byte integer */
84 :     [nrrdTypeFloat] = {true, 4}, /* 9: 4-byte floating point */
85 :     [nrrdTypeDouble] = {true, 8}, /* 10: 8-byte floating point */
86 :     [nrrdTypeBlock] = {false, 0}, /* 11: size user defined at run time; MUST BE LAST */
87 :     };
88 :    
89 :     //! Check that a nrrd has the expected structure for loading into a dynamic sequence
90 :     //! \param wrld the world; used to report errors
91 :     //! \param nin the nrrd to check
92 :     //! \param nDims the number of dimensions in the sequence elements
93 :     //! \param dims the array of sequence element dimensions
94 :     //! \return the number of values per element, or zero on error
95 :     static unsigned int CheckNrrd (
96 :     WorldPrefix_t *wrld,
97 :     Nrrd *nin,
98 :     unsigned int nDims,
99 :     unsigned int *dims)
100 :     {
101 :    
102 :     // compute the expected number of values per sequence element
103 :     unsigned int nValuesPerElem = 1;
104 :     for (unsigned int i = 0; i < nDims; i++) {
105 :     nValuesPerElem *= dims[i];
106 :     }
107 :    
108 :     // check the structure of the nrrd file
109 :     if (nin->spaceDim != 1) {
110 :     Diderot_Error (wrld, "unexpected number of axes in nrrd; expected 1, found %d\n",
111 :     nin->spaceDim);
112 :     return 0;
113 :     }
114 :     if (nin->dim - 1 != nDims) {
115 :     Diderot_Error (wrld, "unexpected nrrd dimension; expected %d, found %d\n",
116 :     nDims, nin->dim-1);
117 :     return 0;
118 :     }
119 :     for (unsigned int i = 0; i < nDims; i++) {
120 :     if (dims[i] != nin->axis[i+1].size) {
121 :     Diderot_Error (wrld, "nrrd shape does not match expected structure\n");
122 :     return 0;
123 :     }
124 :     }
125 : jhr 1979 if (NrrdTypeInfo[nin->type].sizeb == 0) {
126 : jhr 1978 Diderot_Error (wrld, "bogus element type %d in nrrd\n", nin->type);
127 :     return 0;
128 :     }
129 :    
130 :     return nValuesPerElem;
131 :     }
132 :    
133 :     //! load a dynamic sequence from a Nrrd file, where the sequence elements have real ground type.
134 :     //! \param wrld the world; used to report errors
135 :     //! \param nin the nrrd to check
136 :     //! \param nDims the number of dimensions in the sequence elements
137 :     //! \param dims the array of sequence element dimensions
138 :     //! \return the dynamic sequence, or zero on error
139 :     Diderot_DynSeq_t *Diderot_DynSeqLoadReal (
140 :     WorldPrefix_t *wrld,
141 :     Nrrd *nin,
142 :     unsigned int nDims,
143 :     unsigned int *dims)
144 :     {
145 :     unsigned int nValuesPerElem = CheckNrrd(wrld, nin, nDims, dims);
146 :     size_t elemSz = SIZEOF_DIDEROT_REAL * nValuesPerElem;
147 :    
148 :     if (nValuesPerElem == 0)
149 :     return (Diderot_DynSeq_t *)0;
150 :    
151 :     // get the number of elements
152 :     size_t nElems = nin->axis[0].size;
153 :    
154 :     // allocate the dynamic sequence
155 :     Diderot_DynSeq_t *seq = Diderot_DynSeqAlloc(elemSz, nElems);
156 :    
157 :     // initialize the sequence from the nrrd
158 : jhr 1979 if (! NrrdTypeInfo[nin->type].isFloat || (NrrdTypeInfo[nin->type].sizeb != SIZEOF_DIDEROT_REAL)) {
159 : jhr 1978 // this is the slow path; we have to convert values as they are copied from the nrrd
160 :     #if defined(DIDEROT_DOUBLE_PRECISION)
161 :     double (*loadFn)(const void *) = nrrdDLoad[nin->type];
162 :     #else
163 :     float (*loadFn)(const void *) = nrrdFLoad[nin->type];
164 :     #endif
165 :     Diderot_real_t *dst = (Diderot_real_t *)seq->data;
166 :     char *src = (char *)nin->data;
167 : jhr 1979 size_t srcElemSz = NrrdTypeInfo[nin->type].sizeb;
168 : jhr 1978 for (size_t i = 0; i < nElems * nValuesPerElem; i++) {
169 :     *dst++ = loadFn(src);
170 :     src += srcElemSz;
171 :     }
172 :     }
173 :     else {
174 :     // this is the fast path, where we can just do a bulk memcpy
175 :     memcpy (seq->data, nin->data, nElems * elemSz);
176 :     }
177 :    
178 :     return seq;
179 :    
180 :     }
181 :    
182 :    
183 :     //! load a dynamic sequence from a Nrrd file, where the sequence elements have int ground type.
184 :     //! \param wrld the world; used to report errors
185 :     //! \param nin the nrrd to check
186 :     //! \param nDims the number of dimensions in the sequence elements
187 :     //! \param dims the array of sequence element dimensions
188 :     //! \return the dynamic sequence, or zero on error
189 :     Diderot_DynSeq_t *Diderot_DynSeqLoadInt (
190 :     WorldPrefix_t *wrld,
191 :     Nrrd *nin,
192 :     unsigned int nDims,
193 :     unsigned int *dims)
194 :     {
195 :     unsigned int nValuesPerElem = CheckNrrd(wrld, nin, nDims, dims);
196 :     size_t elemSz = SIZEOF_DIDEROT_INT * nValuesPerElem;
197 :    
198 :     if (nValuesPerElem == 0)
199 :     return (Diderot_DynSeq_t *)0;
200 :    
201 : jhr 1979 if (NrrdTypeInfo[nin->type].isFloat) {
202 : jhr 1978 Diderot_Error (wrld, "expected integer element type for int sequence, but found %d\n", nin->type);
203 :     return 0;
204 :     }
205 :    
206 :     // get the number of elements
207 :     size_t nElems = nin->axis[0].size;
208 :    
209 :     // allocate the dynamic sequence
210 :     Diderot_DynSeq_t *seq = Diderot_DynSeqAlloc(elemSz, nElems);
211 :    
212 :     // initialize the sequence from the nrrd
213 : jhr 1979 if (NrrdTypeInfo[nin->type].sizeb != SIZEOF_DIDEROT_INT) {
214 : jhr 1978 // this is the slow path; we have to convert values as they are copied from the nrrd
215 :     int (*loadFn)(const void *) = nrrdILoad[nin->type];
216 :     Diderot_int_t *dst = (Diderot_int_t *)seq->data;
217 :     char *src = (char *)nin->data;
218 : jhr 1979 size_t srcElemSz = NrrdTypeInfo[nin->type].sizeb;
219 : jhr 1978 for (size_t i = 0; i < nElems * nValuesPerElem; i++) {
220 :     *dst++ = loadFn(src);
221 :     src += srcElemSz;
222 :     }
223 :     }
224 :     else {
225 :     // this is the fast path, where we can just do a bulk memcpy
226 :     memcpy (seq->data, nin->data, nElems * elemSz);
227 :     }
228 :    
229 :     return seq;
230 :    
231 :     }
232 :    
233 :    
234 :     //! load a dynamic sequence from a Nrrd file, where the sequence elements have bool ground type.
235 :     //! \param wrld the world; used to report errors
236 :     //! \param nin the nrrd to check
237 :     //! \param nDims the number of dimensions in the sequence elements
238 :     //! \param dims the array of sequence element dimensions
239 :     //! \return the dynamic sequence, or zero on error
240 :     Diderot_DynSeq_t *Diderot_DynSeqLoadBool (
241 :     WorldPrefix_t *wrld,
242 :     Nrrd *nin,
243 :     unsigned int nDims,
244 :     unsigned int *dims)
245 :     {
246 :     unsigned int nValuesPerElem = CheckNrrd(wrld, nin, nDims, dims);
247 : jhr 1979 size_t elemSz = sizeof(bool) * nValuesPerElem;
248 : jhr 1978
249 :     if (nValuesPerElem == 0)
250 :     return (Diderot_DynSeq_t *)0;
251 :    
252 : jhr 1979 if (NrrdTypeInfo[nin->type].isFloat) {
253 : jhr 1978 Diderot_Error (wrld, "expected integer element type for bool sequence, but found %d\n", nin->type);
254 :     return 0;
255 :     }
256 :    
257 :     // get the number of elements
258 :     size_t nElems = nin->axis[0].size;
259 :    
260 :     // allocate the dynamic sequence
261 :     Diderot_DynSeq_t *seq = Diderot_DynSeqAlloc(elemSz, nElems);
262 :    
263 :     // initialize the sequence from the nrrd
264 : jhr 1979 if (NrrdTypeInfo[nin->type].sizeb != sizeof(bool)) {
265 : jhr 1978 // this is the slow path; we have to convert values as they are copied from the nrrd
266 :     int (*loadFn)(const void *) = nrrdILoad[nin->type];
267 :     bool *dst = (bool *)seq->data;
268 :     char *src = (char *)nin->data;
269 : jhr 1979 size_t srcElemSz = NrrdTypeInfo[nin->type].sizeb;
270 : jhr 1978 for (size_t i = 0; i < nElems * nValuesPerElem; i++) {
271 :     *dst++ = loadFn(src) ? true : false;
272 :     src += srcElemSz;
273 :     }
274 :     }
275 :     else {
276 :     // this is the fast path, where we can just do a bulk memcpy
277 :     memcpy (seq->data, nin->data, nElems * elemSz);
278 :     }
279 :    
280 :     return seq;
281 :    
282 :     }

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