Mercurial > hg > octave-nkf
comparison liboctave/Array-d.cc @ 7433:402168152bb9
[project @ 2008-01-31 18:59:09 by dbateman]
author | dbateman |
---|---|
date | Thu, 31 Jan 2008 18:59:11 +0000 |
parents | a1dbe9d80eee |
children | d98dea7d16b0 |
comparison
equal
deleted
inserted
replaced
7432:3c999b2b5de8 | 7433:402168152bb9 |
---|---|
27 | 27 |
28 // Instantiate Arrays of double values. | 28 // Instantiate Arrays of double values. |
29 | 29 |
30 #include "Array.h" | 30 #include "Array.h" |
31 #include "Array.cc" | 31 #include "Array.cc" |
32 #include "oct-sort.cc" | |
33 | |
34 #if defined (HAVE_IEEE754_DATA_FORMAT) | |
35 | |
36 static inline uint64_t | |
37 FloatFlip (uint64_t f) | |
38 { | |
39 uint64_t mask | |
40 = -static_cast<int64_t>(f >> 63) | 0x8000000000000000ULL; | |
41 | |
42 return f ^ mask; | |
43 } | |
44 | |
45 static inline uint64_t | |
46 IFloatFlip (uint64_t f) | |
47 { | |
48 uint64_t mask = ((f >> 63) - 1) | 0x8000000000000000ULL; | |
49 | |
50 return f ^ mask; | |
51 } | |
52 | |
53 template <> | |
54 bool | |
55 ascending_compare (double a, double b) | |
56 { | |
57 return (xisnan (b) || (a < b)); | |
58 } | |
59 | |
60 template <> | |
61 bool | |
62 ascending_compare (vec_index<double> *a, vec_index<double> *b) | |
63 { | |
64 return (xisnan (b->vec) || (a->vec < b->vec)); | |
65 } | |
66 | |
67 template <> | |
68 bool | |
69 descending_compare (double a, double b) | |
70 { | |
71 return (xisnan (a) || (a > b)); | |
72 } | |
73 | |
74 template <> | |
75 bool | |
76 descending_compare (vec_index<double> *a, vec_index<double> *b) | |
77 { | |
78 return (xisnan (b->vec) || (a->vec > b->vec)); | |
79 } | |
80 | |
81 INSTANTIATE_ARRAY_SORT (uint64_t); | |
82 | |
83 template <> | |
84 Array<double> | |
85 Array<double>::sort (octave_idx_type dim, sortmode mode) const | |
86 { | |
87 Array<double> m = *this; | |
88 | |
89 dim_vector dv = m.dims (); | |
90 | |
91 if (m.length () < 1) | |
92 return m; | |
93 | |
94 octave_idx_type ns = dv(dim); | |
95 octave_idx_type iter = dv.numel () / ns; | |
96 octave_idx_type stride = 1; | |
97 for (int i = 0; i < dim; i++) | |
98 stride *= dv(i); | |
99 | |
100 double *v = m.fortran_vec (); | |
101 | |
102 uint64_t *p = reinterpret_cast<uint64_t *> (v); | |
103 | |
104 octave_sort<uint64_t> lsort; | |
105 | |
106 if (mode == ASCENDING) | |
107 lsort.set_compare (ascending_compare); | |
108 else if (mode == DESCENDING) | |
109 lsort.set_compare (descending_compare); | |
110 | |
111 if (stride == 1) | |
112 { | |
113 for (octave_idx_type j = 0; j < iter; j++) | |
114 { | |
115 // Flip the data in the vector so that int compares on | |
116 // IEEE754 give the correct ordering. | |
117 | |
118 for (octave_idx_type i = 0; i < ns; i++) | |
119 p[i] = FloatFlip (p[i]); | |
120 | |
121 lsort.sort (p, ns); | |
122 | |
123 // Flip the data out of the vector so that int compares | |
124 // on IEEE754 give the correct ordering. | |
125 | |
126 for (octave_idx_type i = 0; i < ns; i++) | |
127 p[i] = IFloatFlip (p[i]); | |
128 | |
129 // There are two representations of NaN. One will be | |
130 // sorted to the beginning of the vector and the other | |
131 // to the end. If it will be sorted incorrectly, fix | |
132 // things up. | |
133 | |
134 if (lo_ieee_signbit (octave_NaN)) | |
135 { | |
136 if (mode == UNDEFINED || mode == ASCENDING) | |
137 { | |
138 octave_idx_type i = 0; | |
139 double *vtmp = reinterpret_cast<double *> (p); | |
140 while (xisnan (vtmp[i++]) && i < ns); | |
141 for (octave_idx_type l = 0; l < ns - i + 1; l++) | |
142 vtmp[l] = vtmp[l+i-1]; | |
143 for (octave_idx_type l = ns - i + 1; l < ns; l++) | |
144 vtmp[l] = octave_NaN; | |
145 } | |
146 else | |
147 { | |
148 octave_idx_type i = ns; | |
149 double *vtmp = reinterpret_cast<double *> (p); | |
150 while (xisnan (vtmp[--i]) && i > 0); | |
151 for (octave_idx_type l = i; l >= 0; l--) | |
152 vtmp[l-i+ns-1] = vtmp[l]; | |
153 for (octave_idx_type l = 0; l < ns - i - 1; l++) | |
154 vtmp[l] = octave_NaN; | |
155 } | |
156 } | |
157 | |
158 p += ns; | |
159 } | |
160 } | |
161 else | |
162 { | |
163 OCTAVE_LOCAL_BUFFER (uint64_t, vi, ns); | |
164 | |
165 for (octave_idx_type j = 0; j < iter; j++) | |
166 { | |
167 octave_idx_type offset = j; | |
168 octave_idx_type offset2 = 0; | |
169 while (offset >= stride) | |
170 { | |
171 offset -= stride; | |
172 offset2++; | |
173 } | |
174 offset += offset2 * stride * ns; | |
175 | |
176 // Flip the data in the vector so that int compares on | |
177 // IEEE754 give the correct ordering. | |
178 | |
179 for (octave_idx_type i = 0; i < ns; i++) | |
180 vi[i] = FloatFlip (p[i*stride + offset]); | |
181 | |
182 lsort.sort (vi, ns); | |
183 | |
184 // Flip the data out of the vector so that int compares | |
185 // on IEEE754 give the correct ordering. | |
186 | |
187 for (octave_idx_type i = 0; i < ns; i++) | |
188 p[i*stride + offset] = IFloatFlip (vi[i]); | |
189 | |
190 // There are two representations of NaN. One will be | |
191 // sorted to the beginning of the vector and the other | |
192 // to the end. If it will be sorted to the beginning, | |
193 // fix things up. | |
194 | |
195 if (lo_ieee_signbit (octave_NaN)) | |
196 { | |
197 if (mode == UNDEFINED || mode == ASCENDING) | |
198 { | |
199 octave_idx_type i = 0; | |
200 while (xisnan (v[i++*stride + offset]) && i < ns); | |
201 for (octave_idx_type l = 0; l < ns - i + 1; l++) | |
202 v[l*stride + offset] = v[(l+i-1)*stride + offset]; | |
203 for (octave_idx_type l = ns - i + 1; l < ns; l++) | |
204 v[l*stride + offset] = octave_NaN; | |
205 } | |
206 else | |
207 { | |
208 octave_idx_type i = ns; | |
209 while (xisnan (v[--i*stride + offset]) && i > 0); | |
210 for (octave_idx_type l = i; l >= 0; l--) | |
211 v[(l-i+ns-1)*stride + offset] = v[l*stride + offset]; | |
212 for (octave_idx_type l = 0; l < ns - i - 1; l++) | |
213 v[l*stride + offset] = octave_NaN; | |
214 } | |
215 } | |
216 } | |
217 } | |
218 | |
219 return m; | |
220 } | |
221 | |
222 template <> | |
223 Array<double> | |
224 Array<double>::sort (Array<octave_idx_type> &sidx, octave_idx_type dim, | |
225 sortmode mode) const | |
226 { | |
227 Array<double> m = *this; | |
228 | |
229 dim_vector dv = m.dims (); | |
230 | |
231 if (m.length () < 1) | |
232 { | |
233 sidx = Array<octave_idx_type> (dv); | |
234 return m; | |
235 } | |
236 | |
237 octave_idx_type ns = dv(dim); | |
238 octave_idx_type iter = dv.numel () / ns; | |
239 octave_idx_type stride = 1; | |
240 for (int i = 0; i < dim; i++) | |
241 stride *= dv(i); | |
242 | |
243 double *v = m.fortran_vec (); | |
244 | |
245 uint64_t *p = reinterpret_cast<uint64_t *> (v); | |
246 | |
247 octave_sort<vec_index<uint64_t> *> indexed_sort; | |
248 | |
249 if (mode == ASCENDING) | |
250 indexed_sort.set_compare (ascending_compare); | |
251 else if (mode == DESCENDING) | |
252 indexed_sort.set_compare (descending_compare); | |
253 | |
254 OCTAVE_LOCAL_BUFFER (vec_index<uint64_t> *, vi, ns); | |
255 OCTAVE_LOCAL_BUFFER (vec_index<uint64_t>, vix, ns); | |
256 | |
257 for (octave_idx_type i = 0; i < ns; i++) | |
258 vi[i] = &vix[i]; | |
259 | |
260 sidx = Array<octave_idx_type> (dv); | |
261 | |
262 for (octave_idx_type j = 0; j < iter; j++) | |
263 { | |
264 octave_idx_type offset = j; | |
265 octave_idx_type offset2 = 0; | |
266 while (offset >= stride) | |
267 { | |
268 offset -= stride; | |
269 offset2++; | |
270 } | |
271 offset += offset2 * stride * ns; | |
272 | |
273 // Flip the data in the vector so that int compares on | |
274 // IEEE754 give the correct ordering. | |
275 | |
276 for (octave_idx_type i = 0; i < ns; i++) | |
277 { | |
278 vi[i]->vec = FloatFlip (p[i*stride + offset]); | |
279 vi[i]->indx = i; | |
280 } | |
281 | |
282 indexed_sort.sort (vi, ns); | |
283 | |
284 // Flip the data out of the vector so that int compares on | |
285 // IEEE754 give the correct ordering | |
286 | |
287 for (octave_idx_type i = 0; i < ns; i++) | |
288 { | |
289 p[i*stride + offset] = IFloatFlip (vi[i]->vec); | |
290 sidx(i*stride + offset) = vi[i]->indx; | |
291 } | |
292 | |
293 // There are two representations of NaN. One will be sorted | |
294 // to the beginning of the vector and the other to the end. | |
295 // If it will be sorted to the beginning, fix things up. | |
296 | |
297 if (lo_ieee_signbit (octave_NaN)) | |
298 { | |
299 if (mode == UNDEFINED || mode == ASCENDING) | |
300 { | |
301 octave_idx_type i = 0; | |
302 while (xisnan (v[i++*stride+offset]) && i < ns); | |
303 OCTAVE_LOCAL_BUFFER (double, itmp, i - 1); | |
304 for (octave_idx_type l = 0; l < i -1; l++) | |
305 itmp[l] = sidx(l*stride + offset); | |
306 for (octave_idx_type l = 0; l < ns - i + 1; l++) | |
307 { | |
308 v[l*stride + offset] = v[(l+i-1)*stride + offset]; | |
309 sidx(l*stride + offset) = sidx((l+i-1)*stride + offset); | |
310 } | |
311 for (octave_idx_type k = 0, l = ns - i + 1; l < ns; l++, k++) | |
312 { | |
313 v[l*stride + offset] = octave_NaN; | |
314 sidx(l*stride + offset) = | |
315 static_cast<octave_idx_type>(itmp[k]); | |
316 } | |
317 } | |
318 else | |
319 { | |
320 octave_idx_type i = ns; | |
321 while (xisnan (v[--i*stride+offset]) && i > 0); | |
322 OCTAVE_LOCAL_BUFFER (double, itmp, ns - i - 1); | |
323 for (octave_idx_type l = 0; l < ns - i -1; l++) | |
324 itmp[l] = sidx((l+i+1)*stride + offset); | |
325 for (octave_idx_type l = i; l >= 0; l--) | |
326 { | |
327 v[(l-i+ns-1)*stride + offset] = v[l*stride + offset]; | |
328 sidx((l-i+ns-1)*stride + offset) = sidx(l*stride + offset); | |
329 } | |
330 for (octave_idx_type k = 0, l = 0; l < ns - i - 1; l++, k++) | |
331 { | |
332 v[l*stride + offset] = octave_NaN; | |
333 sidx(l*stride + offset) = | |
334 static_cast<octave_idx_type>(itmp[k]); | |
335 } | |
336 } | |
337 } | |
338 } | |
339 | |
340 return m; | |
341 } | |
342 | |
343 #else | |
344 | |
345 template <> | |
346 bool | |
347 Array<double>::ascending_compare (double a, double b) const | |
348 { | |
349 return (xisnan (b) || (a < b)); | |
350 } | |
351 | |
352 template <> | |
353 bool | |
354 Array<double>::ascending_compare (vec_index<double> *a, | |
355 vec_index<double> *b) const | |
356 { | |
357 return (xisnan (b->vec) || (a->vec < b->vec)); | |
358 } | |
359 | |
360 template <> | |
361 bool | |
362 Array<double>::descending_compare (double a, double b) const | |
363 { | |
364 return (xisnan (a) || (a > b)); | |
365 } | |
366 | |
367 template <> | |
368 bool | |
369 Array<double>::descending_compare (vec_index<double> *a, | |
370 vec_index<double> *b) const | |
371 { | |
372 return (xisnan (b->vec) || (a->vec > b->vec)); | |
373 } | |
374 | |
375 INSTANTIATE_ARRAY_SORT (double); | |
376 | |
377 #endif | |
32 | 378 |
33 INSTANTIATE_ARRAY_AND_ASSIGN (double, OCTAVE_API); | 379 INSTANTIATE_ARRAY_AND_ASSIGN (double, OCTAVE_API); |
34 | 380 |
35 INSTANTIATE_ARRAY_ASSIGN (double, int, OCTAVE_API); | 381 INSTANTIATE_ARRAY_ASSIGN (double, int, OCTAVE_API); |
36 INSTANTIATE_ARRAY_ASSIGN (double, short, OCTAVE_API); | 382 INSTANTIATE_ARRAY_ASSIGN (double, short, OCTAVE_API); |