1 /*
2 copyright: Steve Dekorte, 2006. All rights reserved.
3 license: See _BSDLicense.txt.
4 */
5
6 #include "UArray.h"
7 #include <math.h>
8 #include <float.h>
9
10 #define IO_USE_SIMD 1
11
12 #ifdef IO_USE_SIMD
13
14 /*
15 #ifdef _MSC_VER
16 #pragma message("Note: IO_USE_SIMD on, attempting to use SIMD acceleration")
17 #else
18 #warning Note: IO_USE_SIMD on, attempting to use SIMD acceleration
19 #endif
20 */
21
22 #include "simd_cp.h"
23 #else
24
25 #ifdef _MSC_VER
26 #pragma message("Uncomment the IO_USE_SIMD define to turn on SIMD acceleration")
27 #else
28 #warning Uncomment the IO_USE_SIMD define to turn on SIMD acceleration
29 #endif
30
31 #define __UNK__EMU__
32 #include "simd_cp_emu.h"
33 #endif
34
35 #define VEC_SIZE 4
36
37 #define LLVEC_DUALARG_OP(VNAME, COP, TYPE) \
38 void v ## TYPE ## _ ## VNAME(TYPE ##_t *aa, TYPE ##_t *bb, size_t size)\
39 {\
40 size_t i = 0;\
41 simd_m128 *a = (simd_m128 *)aa;\
42 simd_m128 *b = (simd_m128 *)bb;\
43 size_t max = (size / VEC_SIZE);\
44 for(i = 0; i < max; i ++) { simd_4f_ ## VNAME (a[i], b[i], a[i]); }\
45 i = i * VEC_SIZE;\
46 while (i < size) { aa[i] COP bb[i]; i ++; }\
47 }
48
49 LLVEC_DUALARG_OP(add, +=, float32);
50 LLVEC_DUALARG_OP(sub, -=, float32);
51 LLVEC_DUALARG_OP(mult, *=, float32);
52 LLVEC_DUALARG_OP(div, /=, float32);
53
54 // set
55
UArray_round(UArray * self)56 void UArray_round(UArray *self)
57 {
58 UARRAY_FOREACHASSIGN(self, i, v, floor((double)(v+.5)));
59 }
60
UArray_clear(UArray * self)61 void UArray_clear(UArray *self)
62 {
63 UARRAY_FOREACHASSIGN_VALUE_UNUSED(self, i, 0);
64 }
65
UArray_setItemsToLong_(UArray * self,long x)66 void UArray_setItemsToLong_(UArray *self, long x)
67 {
68 UARRAY_FOREACHASSIGN_VALUE_UNUSED(self, i, x);
69 }
70
UArray_setItemsToDouble_(UArray * self,double x)71 void UArray_setItemsToDouble_(UArray *self, double x)
72 {
73 UARRAY_FOREACHASSIGN_VALUE_UNUSED(self, i, x);
74 }
75
UArray_rangeFill(UArray * self)76 void UArray_rangeFill(UArray *self)
77 {
78 UARRAY_FOREACHASSIGN_VALUE_UNUSED(self, i, i);
79 }
80
UArray_negate(const UArray * self)81 void UArray_negate(const UArray *self)
82 {
83 if(UArray_isSignedType(self))
84 {
85 UARRAY_FOREACHASSIGN(self, i, v, -v);
86 }
87 else
88 {
89 UArray_error_(self, "UArray_negate not supported on this type");
90 }
91 }
92
93 // basic vector math
94
UArray_add_(UArray * self,const UArray * other)95 void UArray_add_(UArray *self, const UArray *other)
96 {
97 if (self->itemType == CTYPE_float32_t && other->itemType == CTYPE_float32_t)
98 {
99 vfloat32_add((float32_t *)self->data, (float32_t *)other->data, UArray_minSizeWith_(self, other));
100 return;
101 }
102
103 DUARRAY_OP(UARRAY_BASICOP_TYPES, +=, self, other);
104 }
105
UArray_subtract_(UArray * self,const UArray * other)106 void UArray_subtract_(UArray *self, const UArray *other)
107 {
108 if (self->itemType == CTYPE_float32_t && other->itemType == CTYPE_float32_t)
109 {
110 vfloat32_sub((float32_t *)self->data, (float32_t *)other->data, UArray_minSizeWith_(self, other));
111 return;
112 }
113
114 DUARRAY_OP(UARRAY_BASICOP_TYPES, -=, self, other);
115 }
116
UArray_multiply_(UArray * self,const UArray * other)117 void UArray_multiply_(UArray *self, const UArray *other)
118 {
119 if (self->itemType == CTYPE_float32_t && other->itemType == CTYPE_float32_t)
120 {
121 vfloat32_mult((float32_t *)self->data, (float32_t *)other->data, UArray_minSizeWith_(self, other));
122 return;
123 }
124
125 DUARRAY_OP(UARRAY_BASICOP_TYPES, *=, self, other);
126 }
127
UArray_divide_(UArray * self,const UArray * other)128 void UArray_divide_(UArray *self, const UArray *other)
129 {
130 if (self->itemType == CTYPE_float32_t && other->itemType == CTYPE_float32_t)
131 {
132 vfloat32_div((float32_t *)self->data, (float32_t *)other->data, UArray_minSizeWith_(self, other));
133 return;
134 }
135
136 DUARRAY_OP(UARRAY_BASICOP_TYPES, /=, self, other);
137 }
138
UArray_power_(UArray * self,const UArray * other)139 void UArray_power_(UArray *self, const UArray *other)
140 {
141 /*
142 if (self->itemType == CTYPE_float32_t && other->itemType == CTYPE_float32_t)
143 {
144 vfloat32_div((float32_t *)self->data, (float32_t *)other->data, UArray_minSizeWith_(self, other));
145 return;
146 }
147 */
148 DUARRAY_OP(UARRAY_FUNCTION_TYPES, pow, self, other);
149 }
150
151 #define UARRAY_DOT(OP2, TYPE1, self, TYPE2, other)\
152 {\
153 double p = 0;\
154 size_t i, minSize = self->size < other->size ? self->size : other->size;\
155 for(i = 0; i < minSize; i ++)\
156 { p += ((TYPE1 *)self->data)[i] * ((TYPE2 *)other->data)[i]; }\
157 return p; \
158 }
159
160
UArray_dotProduct_(const UArray * self,const UArray * other)161 double UArray_dotProduct_(const UArray *self, const UArray *other)
162 {
163 DUARRAY_OP(UARRAY_DOT, NULL, self, other);
164 return 0; // to keep compiler from annoying us
165 }
166
167 // basic scalar math
168
UArray_addScalarDouble_(UArray * self,double value)169 void UArray_addScalarDouble_(UArray *self, double value)
170 {
171 UARRAY_FOREACHASSIGN(self, i, v, v + value);
172 }
173
UArray_subtractScalarDouble_(UArray * self,double value)174 void UArray_subtractScalarDouble_(UArray *self, double value)
175 {
176 UARRAY_FOREACHASSIGN(self, i, v, v - value);
177 }
178
UArray_multiplyScalarDouble_(UArray * self,double value)179 void UArray_multiplyScalarDouble_(UArray *self, double value)
180 {
181 UARRAY_FOREACHASSIGN(self, i, v, v * value);
182 }
183
UArray_divideScalarDouble_(UArray * self,double value)184 void UArray_divideScalarDouble_(UArray *self, double value)
185 {
186 UARRAY_FOREACHASSIGN(self, i, v, v / value);
187 }
188
UArray_powerScalarDouble_(UArray * self,double value)189 void UArray_powerScalarDouble_(UArray *self, double value)
190 {
191 UARRAY_FOREACHASSIGN(self, i, v, pow(v, value));
192 }
193
194 // bitwise
195
UArray_bitwiseOr_(UArray * self,const UArray * other)196 void UArray_bitwiseOr_(UArray *self, const UArray *other)
197 {
198 size_t i, max = UArray_minSizeInBytesWith_(self, other);
199 uint8_t *d1 = self->data;
200 uint8_t *d2 = other->data;
201 for (i = 0; i < max; i ++) { d1[i] |= d2[i]; }
202 }
203
UArray_bitwiseAnd_(UArray * self,const UArray * other)204 void UArray_bitwiseAnd_(UArray *self, const UArray *other)
205 {
206 size_t i, max = UArray_minSizeInBytesWith_(self, other);
207 uint8_t *d1 = self->data;
208 uint8_t *d2 = other->data;
209 for (i = 0; i < max; i ++) { d1[i] &= d2[i]; }
210 }
211
UArray_bitwiseXor_(UArray * self,const UArray * other)212 void UArray_bitwiseXor_(UArray *self, const UArray *other)
213 {
214 size_t i, max = UArray_minSizeInBytesWith_(self, other);
215 uint8_t *d1 = self->data;
216 uint8_t *d2 = other->data;
217 for (i = 0; i < max; i ++) { d1[i] ^= d2[i]; }
218 }
219
UArray_bitwiseNot(UArray * self)220 void UArray_bitwiseNot(UArray *self)
221 {
222 size_t i, max = UArray_sizeInBytes(self);
223 uint8_t *data = self->data;
224 for (i = 0; i < max; i ++) { data[i] = ~(data[i]); }
225 }
226
227 // bitwise ops
228
UArray_setAllBitsTo_(UArray * self,uint8_t aBool)229 void UArray_setAllBitsTo_(UArray *self, uint8_t aBool)
230 {
231 size_t i, max = UArray_sizeInBytes(self);
232 uint8_t *data = self->data;
233 uint8_t bits = aBool ? ~0 : 0;
234 for (i = 0; i < max; i ++) { data[i] = bits; }
235 }
236
237 // adjust for endianess?
238
UArray_bitAt_(UArray * self,size_t i)239 int UArray_bitAt_(UArray *self, size_t i)
240 {
241 size_t bytePos = i / 8;
242 size_t bitPos = i % 8;
243 if (bytePos >= UArray_sizeInBytes(self)) return 0;
244 return (self->data[bytePos] >> bitPos) & 0x1;
245 }
246
UArray_byteAt_(UArray * self,size_t i)247 uint8_t UArray_byteAt_(UArray *self, size_t i)
248 {
249 if (i < UArray_sizeInBytes(self)) return self->data[i];
250 return 0;
251 }
252
UArray_setBit_at_(UArray * self,int aBool,size_t i)253 void UArray_setBit_at_(UArray *self, int aBool, size_t i)
254 {
255 size_t bytePos = i / 8;
256 size_t bitPos = i % 8;
257 uint8_t n = 0x1 << bitPos;
258 uint8_t b;
259 if (bytePos >= UArray_sizeInBytes(self)) return;
260 b = self->data[bytePos];
261 b ^= n;
262 if (aBool) b |= (0x1 << bitPos);
263 self->data[bytePos] = b;
264 }
265
UArray_asBits(const UArray * self)266 UArray *UArray_asBits(const UArray *self)
267 {
268 UArray *out = UArray_new();
269 size_t i, max = UArray_sizeInBytes(self);
270 uint8_t *data = self->data;
271
272 for (i = 0; i < max; i ++)
273 {
274 uint8_t b = data[i];
275 int j;
276
277 for (j = 0; j < 8; j ++)
278 {
279 int v = (b >> j) & 0x1;
280 UArray_appendCString_(out, v ? "1" : "0");
281 }
282 }
283
284 return out;
285 }
286
UArray_bitCount(UArray * self)287 size_t UArray_bitCount(UArray *self)
288 {
289 const unsigned char map[] =
290 {
291 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
292 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
293 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
294 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
295 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
296 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
297 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
298 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
299 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
300 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
301 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
302 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
303 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
304 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
305 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
306 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
307 };
308
309 size_t i, max = UArray_sizeInBytes(self);
310 uint8_t *data = self->data;
311 size_t total = 0;
312
313 for (i = 0; i < max; i ++) { total += map[data[i]]; }
314
315 return total;
316 }
317
318 // logic
319
320 #define UARRAY_LOGICOP_TYPES(OP2, TYPE1, self, TYPE2, other)\
321 {\
322 size_t i, minSize = self->size < other->size ? self->size : other->size;\
323 for(i = 0; i < minSize; i ++)\
324 {\
325 ((TYPE1 *)self->data)[i] = ((TYPE1 *)self->data)[i] OP2 (TYPE1)((TYPE2 *)other->data)[i];\
326 }\
327 }
328
UArray_logicalOr_(UArray * self,const UArray * other)329 void UArray_logicalOr_(UArray *self, const UArray *other)
330 {
331 DUARRAY_INTOP(UARRAY_LOGICOP_TYPES, ||, self, other);
332 }
333
UArray_logicalAnd_(UArray * self,const UArray * other)334 void UArray_logicalAnd_(UArray *self, const UArray *other)
335 {
336 DUARRAY_INTOP(UARRAY_LOGICOP_TYPES, &&, self, other);
337 }
338
339 // trigonometry
340
341 #define UARRAY_DOP(OP) \
342 void UArray_ ## OP (UArray *self) { UARRAY_FOREACHASSIGN(self, i, v, OP((double)v)); }
343
344 UARRAY_DOP(sin);
345 UARRAY_DOP(cos);
346 UARRAY_DOP(tan);
347 UARRAY_DOP(asin);
348 UARRAY_DOP(acos);
349 UARRAY_DOP(atan);
350 UARRAY_DOP(sinh);
351 UARRAY_DOP(cosh);
352 UARRAY_DOP(tanh);
353 UARRAY_DOP(exp);
354 UARRAY_DOP(log);
355 UARRAY_DOP(log10);
356
357 UARRAY_DOP(sqrt);
358 UARRAY_DOP(ceil);
359 UARRAY_DOP(floor);
360 UARRAY_DOP(fabs);
361
UArray_abs(UArray * self)362 void UArray_abs(UArray *self)
363 {
364 UArray_fabs(self);
365 }
366
UArray_square(UArray * self)367 void UArray_square(UArray *self)
368 {
369 UArray_multiply_(self, self);
370 }
371
372 // extras
373
UArray_sumAsDouble(const UArray * self)374 double UArray_sumAsDouble(const UArray *self)
375 {
376 double sum = 0;
377 UARRAY_FOREACH(self, i, v, sum += v);
378 return sum;
379 }
380
UArray_productAsDouble(const UArray * self)381 double UArray_productAsDouble(const UArray *self)
382 {
383 double p = 1;
384 UARRAY_FOREACH(self, i, v, p *= v);
385 return p;
386 }
387
UArray_arithmeticMeanAsDouble(const UArray * self)388 double UArray_arithmeticMeanAsDouble(const UArray *self)
389 {
390 return UArray_sumAsDouble(self) / ((double)self->size);
391 }
392
UArray_arithmeticMeanSquareAsDouble(const UArray * self)393 double UArray_arithmeticMeanSquareAsDouble(const UArray *self)
394 {
395 double r;
396 UArray *s = UArray_clone(self);
397 UArray_square(s);
398 r = UArray_arithmeticMeanAsDouble(s);
399 UArray_free(s);
400 return r;
401 }
402
UArray_maxAsDouble(const UArray * self)403 double UArray_maxAsDouble(const UArray *self)
404 {
405 if(self->size > 0)
406 {
407 double max = DBL_MIN;
408 UARRAY_FOREACH(self, i, v, if(v > max) { max = v; });
409 return max;
410 }
411
412 return 0;
413 }
414
UArray_minAsDouble(const UArray * self)415 double UArray_minAsDouble(const UArray *self)
416 {
417 if(self->size > 0)
418 {
419 double max = DBL_MAX;
420 UARRAY_FOREACH(self, i, v, if(v < max) { max = v; });
421 return max;
422 }
423
424 return 0;
425 }
426
UArray_Max(UArray * self,const UArray * other)427 BASEKIT_API void UArray_Max(UArray *self, const UArray *other)
428 {
429 size_t i, minSize = self->size < other->size ? self->size : other->size;
430
431 for(i = 0; i < minSize; i ++)
432 {
433 double v1 = UArray_rawDoubleAt_(self, i);
434 double v2 = UArray_rawDoubleAt_(other, i);
435 double m = v1 > v2 ? v1 : v2;
436 UArray_at_putDouble_(self, i, m);
437 }
438 }
439
UArray_Min(UArray * self,const UArray * other)440 BASEKIT_API void UArray_Min(UArray *self, const UArray *other)
441 {
442 size_t i, minSize = self->size < other->size ? self->size : other->size;
443
444 for(i = 0; i < minSize; i ++)
445 {
446 double v1 = UArray_rawDoubleAt_(self, i);
447 double v2 = UArray_rawDoubleAt_(other, i);
448 double m = v1 < v2 ? v1 : v2;
449 UArray_at_putDouble_(self, i, m);
450 }
451 }
452
453
UArray_normalize(UArray * self)454 void UArray_normalize(UArray *self)
455 {
456 double a;
457 UArray *s = UArray_clone(self);
458 UArray_square(s);
459 a = UArray_sumAsDouble(s);
460 UArray_free(s);
461 a = sqrt(a);
462 //double max = UArray_maxAsDouble(self);
463 UArray_divideScalarDouble_(self, a);
464 }
465
UArray_crossProduct_(UArray * self,const UArray * other)466 void UArray_crossProduct_(UArray *self, const UArray *other)
467 {
468 if (self->itemType == CTYPE_float32_t &&
469 other->itemType == CTYPE_float32_t &&
470 self->size > 2 && other->size > 2)
471 {
472 float32_t *a = (float32_t *)self->data;
473 float32_t *b = (float32_t *)other->data;
474
475 float32_t i = (a[1]*b[2]) - (a[2]*b[1]);
476 float32_t j = (a[2]*b[0]) - (a[0]*b[2]);
477 float32_t k = (a[0]*b[1]) - (a[1]*b[0]);
478
479 a[0] = i;
480 a[1] = j;
481 a[2] = k;
482
483 UArray_changed(self);
484
485 return;
486 }
487 }
488
UArray_distanceTo_(const UArray * self,const UArray * other)489 double UArray_distanceTo_(const UArray *self, const UArray *other)
490 {
491 if (self->itemType == CTYPE_float32_t &&
492 other->itemType == CTYPE_float32_t)
493 {
494 float32_t *a = (float32_t *)self->data;
495 float32_t *b = (float32_t *)other->data;
496 size_t max = self->size > other->size ? self->size : other->size;
497 double sum = 0;
498
499 if (self->size == other->size)
500 {
501 size_t i;
502
503 for (i = 0; i < max; i ++)
504 {
505 float32_t d = a[i] - b[i];
506 sum += d * d;
507 }
508 }
509
510 return (double)sqrt((double)sum);
511 }
512 else if (self->itemType == CTYPE_float64_t &&
513 other->itemType == CTYPE_float64_t)
514 {
515 float64_t *a = (float64_t *)self->data;
516 float64_t *b = (float64_t *)other->data;
517 size_t max = self->size > other->size ? self->size : other->size;
518 double sum = 0;
519
520 if (self->size == other->size)
521 {
522 size_t i;
523
524 for (i = 0; i < max; i ++)
525 {
526 float32_t d = a[i] - b[i];
527 sum += d * d;
528 }
529 }
530
531 return (double)sqrt((double)sum);
532 }
533
534 return 0;
535 }
536
537 // hash
538
UArray_changed(UArray * self)539 void UArray_changed(UArray *self)
540 {
541 self->evenHash = 0;
542 self->oddHash = 0;
543 }
544
545 #include "Hash_fnv.h"
546 #include "Hash_superfast.h"
547 #include "Hash_murmur.h"
548
UArray_superfastHash(UArray * self)549 uintptr_t UArray_superfastHash(UArray *self)
550 {
551 return SuperFastHash((char *)(self->data), (int)UArray_sizeInBytes(self));
552 }
553
UArray_fnvHash(UArray * self)554 uintptr_t UArray_fnvHash(UArray *self)
555 {
556 return (uintptr_t)fnv_32_buf((void *)(self->data), UArray_sizeInBytes(self), FNV1_32_INIT) << 1; // ensures odd result
557 }
558
UArray_murmurHash(UArray * self)559 uintptr_t UArray_murmurHash(UArray *self)
560 {
561 return (uintptr_t)MurmurHash2((const void *)(self->data), (int)UArray_sizeInBytes(self), 0);
562 }
563
564 // even/odd hashes for cuckoo hashtables
565
UArray_calcOddHash(UArray * self)566 uintptr_t UArray_calcOddHash(UArray *self)
567 {
568 return UArray_superfastHash(self) | 0x1; // ensures odd result
569 }
570
UArray_calcEvenHash(UArray * self)571 uintptr_t UArray_calcEvenHash(UArray *self)
572 {
573 return UArray_fnvHash(self) << 1; // ensures odd result
574 }
575
576 // Caching even/odd hashes for cuckoo hashtables
577
UArray_oddHash(UArray * self)578 uintptr_t UArray_oddHash(UArray *self)
579 {
580 if (!self->oddHash)
581 {
582 self->oddHash = UArray_calcOddHash(self);
583 }
584
585 return self->oddHash;
586 }
587
UArray_evenHash(UArray * self)588 uintptr_t UArray_evenHash(UArray *self)
589 {
590 if (!self->evenHash)
591 {
592 self->evenHash = UArray_calcEvenHash(self);
593 }
594
595 return self->evenHash;
596 }
597
UArray_equalsWithHashCheck_(UArray * self,UArray * other)598 int UArray_equalsWithHashCheck_(UArray *self, UArray *other)
599 {
600 if (self == other)
601 {
602 return 1;
603 }
604 else
605 {
606 if (UArray_evenHash(self) != UArray_evenHash(other))
607 {
608 return 0;
609 }
610
611 if (UArray_oddHash(self) != UArray_oddHash(other))
612 {
613 return 0;
614 }
615 /*
616 if(strcmp(self->data, other->data) != 0)
617 {
618 printf("[%s] %i == %i [%s]\n", self->data, h1, h2, other->data);
619 }
620 */
621 }
622
623 return UArray_equals_(self, other);
624 }
625
626 // indexes
627
UArray_duplicateIndexes(UArray * self)628 BASEKIT_API void UArray_duplicateIndexes(UArray *self)
629 {
630 size_t size = self->size;
631 int itemSize = self->itemSize;
632
633 if (size)
634 {
635 size_t si = size - 1;
636 size_t di = (size * 2) - 1;
637 uint8_t *b;
638
639 UArray_setSize_(self, self->size * 2);
640
641 b = self->data;
642
643 for (;;)
644 {
645 uint8_t *src = b + si * itemSize;
646 uint8_t *dest = b + di * itemSize;
647
648 memcpy(dest, src, itemSize);
649 memcpy(dest - itemSize, src, itemSize);
650
651 if (si == 0) break;
652 di = di - 2;
653 si --;
654 }
655 }
656 }
657
UArray_removeOddIndexes(UArray * self)658 void UArray_removeOddIndexes(UArray *self)
659 {
660 size_t itemSize = self->itemSize;
661 size_t di = 1;
662 size_t si = 2;
663 size_t max = self->size;
664 uint8_t *b = self->data;
665
666 if (max == 0)
667 {
668 return;
669 }
670
671 while (si < max)
672 {
673 uint8_t *src = b + (si * itemSize);
674 uint8_t *dest = b + (di * itemSize);
675 memcpy(dest, src, itemSize);
676 si = si + 2;
677 di = di + 1;
678 }
679
680 UArray_setSize_(self, di);
681 }
682
UArray_removeEvenIndexes(UArray * self)683 void UArray_removeEvenIndexes(UArray *self)
684 {
685 size_t itemSize = self->itemSize;
686 size_t di = 0;
687 size_t si = 1;
688 size_t max = self->size;
689 uint8_t *b = self->data;
690
691 while (si < max)
692 {
693 uint8_t *src = b + (si * itemSize);
694 uint8_t *dest = b + (di * itemSize);
695 memcpy(dest, src, itemSize);
696 si = si + 2;
697 di = di + 1;
698 }
699
700 UArray_setSize_(self, di);
701 }
702
UArray_reverseItemByteOrders(UArray * self)703 void UArray_reverseItemByteOrders(UArray *self)
704 {
705 size_t itemSize = self->itemSize;
706
707 if (itemSize > 1)
708 {
709 size_t i, max = self->size;
710 uint8_t *d = self->data;
711
712 for(i = 0; i < max; i ++)
713 {
714 size_t j;
715
716 for(j = 0; j < itemSize; j ++)
717 {
718 size_t i1 = i + j;
719 size_t i2 = i + itemSize - j;
720 uint8_t v = d[i1];
721 d[i1] = d[i2];
722 d[i2] = v;
723 }
724 }
725
726 UArray_changed(self);
727 }
728 }
729
730 //
UArray_addEqualsOffsetXScaleYScale(UArray * self,UArray * other,float offset,float xscale,float yscale)731 void UArray_addEqualsOffsetXScaleYScale(UArray *self, UArray *other, float offset, float xscale, float yscale)
732 {
733 if (self->itemType == CTYPE_float32_t && other->itemType == CTYPE_float32_t)
734 {
735 float32_t *d1 = (float32_t *)self->data;
736 float32_t *d2 = (float32_t *)other->data;
737
738 long i = offset;
739 long j = 0;
740
741 while (i < (long)self->size)
742 {
743 size_t jj = j/xscale;
744
745 //printf("self->size: %i i: %i jj: %i\n", self->size, i, jj);
746 if (jj > other->size - 1) break;
747
748 if (i >= 0) //&& jj < other->size - 1)
749 {
750 d1[i] += d2[jj] * yscale;
751 }
752
753 j ++;
754 i ++;
755 }
756
757 UArray_changed(self);
758 }
759 else
760 {
761 printf("UArray_addEqualsOffsetXScaleYScale called on non float array\n");
762 exit(-1);
763 }
764 }
765
766