Sample: cleaning up Inheritance
[io/quag.git] / libs / basekit / source / UArray_math.c
blob8a0737bb7e1de92df37037fb955bb659b7824c03
1 /*
2 copyright: Steve Dekorte, 2006. All rights reserved.
3 license: See _BSDLicense.txt.
4 */
6 #include "UArray.h"
7 #include <math.h>
8 #include <float.h>
10 #ifdef IO_USE_SIMD
11 #include "simd_cp.h"
12 #else
13 #define __UNK__EMU__
14 #include "simd_cp_emu.h"
15 #endif
17 #define VEC_SIZE 4
19 #define LLVEC_DUALARG_OP(VNAME, COP, TYPE) \
20 void v ## TYPE ## _ ## VNAME(TYPE ##_t *aa, TYPE ##_t *bb, size_t size)\
22 size_t i = 0;\
23 simd_m128 *a = (simd_m128 *)aa;\
24 simd_m128 *b = (simd_m128 *)bb;\
25 size_t max = (size / VEC_SIZE);\
26 for(i = 0; i < max; i ++) { simd_4f_ ## VNAME (a[i], b[i], a[i]); }\
27 i = i * VEC_SIZE;\
28 while (i < size) { aa[i] COP bb[i]; i ++; }\
31 LLVEC_DUALARG_OP(add, +=, float32);
32 LLVEC_DUALARG_OP(sub, -=, float32);
33 LLVEC_DUALARG_OP(mult, *=, float32);
34 LLVEC_DUALARG_OP(div, /=, float32);
36 // set
38 void UArray_clear(UArray *self)
40 UARRAY_FOREACHASSIGN(self, i, v, 0);
43 void UArray_setItemsToLong_(UArray *self, long x)
45 UARRAY_FOREACHASSIGN(self, i, v, x);
48 void UArray_setItemsToDouble_(UArray *self, double x)
50 UARRAY_FOREACHASSIGN(self, i, v, x);
53 void UArray_rangeFill(UArray *self)
55 UARRAY_FOREACHASSIGN(self, i, v, i);
58 void UArray_negate(const UArray *self)
60 if(UArray_isSignedType(self))
62 UARRAY_FOREACHASSIGN(self, i, v, -v);
64 else
66 UArray_error_(self, "UArray_negate not supported on this type");
70 // basic vector math
72 void UArray_add_(UArray *self, const UArray *other)
74 if (self->itemType == CTYPE_float32_t && other->itemType == CTYPE_float32_t)
76 vfloat32_add((float32_t *)self->data, (float32_t *)other->data, UArray_minSizeWith_(self, other));
77 return;
80 DUARRAY_OP(UARRAY_BASICOP_TYPES, +=, self, other);
83 void UArray_subtract_(UArray *self, const UArray *other)
85 if (self->itemType == CTYPE_float32_t && other->itemType == CTYPE_float32_t)
87 vfloat32_sub((float32_t *)self->data, (float32_t *)other->data, UArray_minSizeWith_(self, other));
88 return;
91 DUARRAY_OP(UARRAY_BASICOP_TYPES, -=, self, other);
94 void UArray_multiply_(UArray *self, const UArray *other)
96 if (self->itemType == CTYPE_float32_t && other->itemType == CTYPE_float32_t)
98 vfloat32_mult((float32_t *)self->data, (float32_t *)other->data, UArray_minSizeWith_(self, other));
99 return;
102 DUARRAY_OP(UARRAY_BASICOP_TYPES, *=, self, other);
105 void UArray_divide_(UArray *self, const UArray *other)
107 if (self->itemType == CTYPE_float32_t && other->itemType == CTYPE_float32_t)
109 vfloat32_div((float32_t *)self->data, (float32_t *)other->data, UArray_minSizeWith_(self, other));
110 return;
113 DUARRAY_OP(UARRAY_BASICOP_TYPES, /=, self, other);
116 #define UARRAY_DOT(OP2, TYPE1, self, TYPE2, other)\
118 double p = 0;\
119 size_t i, minSize = self->size < other->size ? self->size : other->size;\
120 for(i = 0; i < minSize; i ++)\
121 { p += ((TYPE1 *)self->data)[i] * ((TYPE2 *)other->data)[i]; }\
122 return p; \
126 double UArray_dotProduct_(const UArray *self, const UArray *other)
128 DUARRAY_OP(UARRAY_DOT, NULL, self, other);
131 // basic scalar math
133 void UArray_addScalarDouble_(UArray *self, double value)
135 UARRAY_FOREACHASSIGN(self, i, v, v + value);
138 void UArray_subtractScalarDouble_(UArray *self, double value)
140 UARRAY_FOREACHASSIGN(self, i, v, v - value);
143 void UArray_multiplyScalarDouble_(UArray *self, double value)
145 UARRAY_FOREACHASSIGN(self, i, v, v * value);
148 void UArray_divideScalarDouble_(UArray *self, double value)
150 UARRAY_FOREACHASSIGN(self, i, v, v / value);
153 // bitwise
155 void UArray_bitwiseOr_(UArray *self, const UArray *other)
157 size_t i, max = UArray_minSizeInBytesWith_(self, other);
158 uint8_t *d1 = self->data;
159 uint8_t *d2 = other->data;
160 for (i = 0; i < max; i ++) { d1[i] |= d2[i]; }
163 void UArray_bitwiseAnd_(UArray *self, const UArray *other)
165 size_t i, max = UArray_minSizeInBytesWith_(self, other);
166 uint8_t *d1 = self->data;
167 uint8_t *d2 = other->data;
168 for (i = 0; i < max; i ++) { d1[i] &= d2[i]; }
171 void UArray_bitwiseXor_(UArray *self, const UArray *other)
173 size_t i, max = UArray_minSizeInBytesWith_(self, other);
174 uint8_t *d1 = self->data;
175 uint8_t *d2 = other->data;
176 for (i = 0; i < max; i ++) { d1[i] ^= d2[i]; }
179 void UArray_bitwiseNot(UArray *self)
181 size_t i, max = UArray_sizeInBytes(self);
182 uint8_t *data = self->data;
183 for (i = 0; i < max; i ++) { data[i] = ~(data[i]); }
186 // bitwise ops
188 void UArray_setAllBitsTo_(UArray *self, uint8_t aBool)
190 size_t i, max = UArray_sizeInBytes(self);
191 uint8_t *data = self->data;
192 uint8_t bits = aBool ? ~0 : 0;
193 for (i = 0; i < max; i ++) { data[i] = bits; }
196 // adjust for endianess?
198 int UArray_bitAt_(UArray *self, size_t i)
200 size_t bytePos = i / 8;
201 size_t bitPos = i - bytePos;
202 if (bytePos >= UArray_sizeInBytes(self)) return 0;
203 return self->data[bytePos] = (self->data[bytePos] >> bitPos) & 0x1;
206 uint8_t UArray_byteAt_(UArray *self, size_t i)
208 if (i < self->size) return self->data[i];
209 return 0;
212 void UArray_setBit_at_(UArray *self, int aBool, size_t i)
214 size_t bytePos = i / 8;
215 size_t bitPos = i - bytePos;
216 uint8_t n = 0x1 << bitPos;
217 uint8_t b;
218 if (bytePos >= UArray_sizeInBytes(self)) return;
219 b = self->data[bytePos];
220 b ^= n;
221 if (aBool) b |= (0x1 << bitPos);
222 self->data[bytePos] = b;
225 UArray *UArray_asBits(const UArray *self)
227 UArray *out = UArray_new();
228 size_t i, max = UArray_sizeInBytes(self);
229 uint8_t *data = self->data;
231 for (i = 0; i < max; i ++)
233 uint8_t b = data[i];
234 int j;
236 for (j = 0; j < 8; j ++)
238 int v = (b >> j) & 0x1;
239 UArray_appendCString_(out, v ? "1" : "0");
243 return out;
246 size_t UArray_bitCount(UArray *self)
248 const unsigned char map[] =
250 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
251 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
252 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
253 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
254 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
255 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
256 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
257 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
258 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
259 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
260 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
261 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
262 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
263 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
264 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
265 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
268 size_t i, max = UArray_sizeInBytes(self);
269 uint8_t *data = self->data;
270 size_t total = 0;
272 for (i = 0; i < max; i ++) { total += map[data[i]]; }
274 return total;
277 // logic
279 #define UARRAY_LOGICOP_TYPES(OP2, TYPE1, self, TYPE2, other)\
281 size_t i, minSize = self->size < other->size ? self->size : other->size;\
282 for(i = 0; i < minSize; i ++)\
284 ((TYPE1 *)self->data)[i] = ((TYPE1 *)self->data)[i] OP2 ((TYPE2 *)other->data)[i];\
288 void UArray_logicalOr_(UArray *self, const UArray *other)
290 DUARRAY_INTOP(UARRAY_LOGICOP_TYPES, ||, self, other);
293 void UArray_logicalAnd_(UArray *self, const UArray *other)
295 DUARRAY_INTOP(UARRAY_LOGICOP_TYPES, &&, self, other);
298 // trigonometry
300 #define UARRAY_DOP(OP) \
301 void UArray_ ## OP (UArray *self) { UARRAY_FOREACHASSIGN(self, i, v, OP((double)v)); }
303 UARRAY_DOP(sin);
304 UARRAY_DOP(cos);
305 UARRAY_DOP(tan);
306 UARRAY_DOP(asin);
307 UARRAY_DOP(acos);
308 UARRAY_DOP(atan);
309 UARRAY_DOP(sinh);
310 UARRAY_DOP(cosh);
311 UARRAY_DOP(tanh);
312 UARRAY_DOP(exp);
313 UARRAY_DOP(log);
314 UARRAY_DOP(log10);
316 UARRAY_DOP(sqrt);
317 UARRAY_DOP(ceil);
318 UARRAY_DOP(floor);
319 UARRAY_DOP(fabs);
321 void UArray_abs(UArray *self)
323 UArray_fabs(self);
326 void UArray_square(UArray *self)
328 UArray_multiply_(self, self);
331 // extras
333 double UArray_sumAsDouble(const UArray *self)
335 double sum = 0;
336 UARRAY_FOREACH(self, i, v, sum += v);
337 return sum;
340 double UArray_productAsDouble(const UArray *self)
342 double p = 1;
343 UARRAY_FOREACH(self, i, v, p *= v);
344 return p;
347 double UArray_arithmeticMeanAsDouble(const UArray *self)
349 return UArray_sumAsDouble(self) / ((double)self->size);
352 double UArray_arithmeticMeanSquareAsDouble(const UArray *self)
354 double r;
355 UArray *s = UArray_clone(self);
356 UArray_square(s);
357 r = UArray_arithmeticMeanAsDouble(s);
358 UArray_free(s);
359 return r;
362 double UArray_maxAsDouble(const UArray *self)
364 if(self->size > 0)
366 double max = DBL_MIN;
367 UARRAY_FOREACH(self, i, v, if(v > max) { max = v; });
368 return max;
371 return 0;
374 double UArray_minAsDouble(const UArray *self)
376 if(self->size > 0)
378 double max = DBL_MAX;
379 UARRAY_FOREACH(self, i, v, if(v < max) { max = v; });
380 return max;
383 return 0;
386 BASEKIT_API void UArray_Max(UArray *self, const UArray *other)
388 size_t i, minSize = self->size < other->size ? self->size : other->size;
390 for(i = 0; i < minSize; i ++)
392 double v1 = UArray_rawDoubleAt_(self, i);
393 double v2 = UArray_rawDoubleAt_(other, i);
394 double m = v1 > v2 ? v1 : v2;
395 UArray_at_putDouble_(self, i, m);
399 BASEKIT_API void UArray_Min(UArray *self, const UArray *other)
401 size_t i, minSize = self->size < other->size ? self->size : other->size;
403 for(i = 0; i < minSize; i ++)
405 double v1 = UArray_rawDoubleAt_(self, i);
406 double v2 = UArray_rawDoubleAt_(other, i);
407 double m = v1 < v2 ? v1 : v2;
408 UArray_at_putDouble_(self, i, m);
413 void UArray_normalize(UArray *self)
415 double a;
416 UArray *s = UArray_clone(self);
417 UArray_square(s);
418 a = UArray_sumAsDouble(s);
419 UArray_free(s);
420 a = sqrt(a);
421 UArray_divideScalarDouble_(self, a);
424 void UArray_crossProduct_(UArray *self, const UArray *other)
426 if (self->itemType == CTYPE_float32_t &&
427 other->itemType == CTYPE_float32_t &&
428 self->size > 2 && other->size > 2)
430 float32_t *a = (float32_t *)self->data;
431 float32_t *b = (float32_t *)other->data;
433 float32_t i = (a[1]*b[2]) - (a[2]*b[1]);
434 float32_t j = (a[2]*b[0]) - (a[0]*b[2]);
435 float32_t k = (a[0]*b[1]) - (a[1]*b[0]);
437 a[0] = i;
438 a[1] = j;
439 a[2] = k;
441 UArray_changed(self);
443 return;
447 double UArray_distanceTo_(const UArray *self, const UArray *other)
449 if (self->itemType == CTYPE_float32_t &&
450 other->itemType == CTYPE_float32_t)
452 float32_t *a = (float32_t *)self->data;
453 float32_t *b = (float32_t *)other->data;
454 size_t max = self->size > other->size ? self->size : other->size;
455 double sum = 0;
457 if (self->size == other->size)
459 size_t i;
461 for (i = 0; i < max; i ++)
463 float32_t d = a[i] - b[i];
464 sum += d * d;
468 return (double)sqrt((double)sum);
470 else if (self->itemType == CTYPE_float64_t &&
471 other->itemType == CTYPE_float64_t)
473 float64_t *a = (float64_t *)self->data;
474 float64_t *b = (float64_t *)other->data;
475 size_t max = self->size > other->size ? self->size : other->size;
476 double sum = 0;
478 if (self->size == other->size)
480 size_t i;
482 for (i = 0; i < max; i ++)
484 float32_t d = a[i] - b[i];
485 sum += d * d;
489 return (double)sqrt((double)sum);
492 return 0;
495 // hash
497 void UArray_changed(UArray *self)
499 self->hash = 0;
502 uintptr_t UArray_calcHash(UArray *self)
504 uintptr_t h = 5381;
506 int i, max = UArray_sizeInBytes(self);
507 uint8_t *data = self->data;
509 for(i = 0; i < max; i ++)
511 h += (h << 5);
512 h ^= data[i];
515 //printf("UArray_%p %i %s\n", self, h, (char *)self->data);
518 // I *think* this should hash to the same value for ASCII, UTF16 and UTF32 types, but not UTF8
520 UARRAY_FOREACH(self, i, v,
521 h += (h << 5);
522 h ^= (uintptr_t)v;
526 return h;
529 uintptr_t UArray_hash(UArray *self)
531 if (!self->hash)
533 self->hash = UArray_calcHash(self);
534 if(self->hash == 0x0) self->hash = 0x1;
537 return self->hash;
540 int UArray_equalsWithHashCheck_(UArray *self, UArray *other)
542 if (self == other)
544 return 1;
546 else
548 uintptr_t h1 = UArray_hash(self);
549 uintptr_t h2 = UArray_hash(other);
551 if (h1 != h2)
553 return 0;
557 if(strcmp(self->data, other->data) != 0)
559 printf("[%s] %i == %i [%s]\n", self->data, h1, h2, other->data);
564 return UArray_equals_(self, other);
567 // indexes
569 BASEKIT_API void UArray_duplicateIndexes(UArray *self)
571 size_t size = self->size;
572 int itemSize = self->itemSize;
574 if (size)
576 size_t si = size - 1;
577 size_t di = (size * 2) - 1;
578 uint8_t *b;
580 UArray_setSize_(self, self->size * 2);
582 b = self->data;
584 for (;;)
586 uint8_t *src = b + si * itemSize;
587 uint8_t *dest = b + di * itemSize;
589 memcpy(dest, src, itemSize);
590 memcpy(dest - itemSize, src, itemSize);
592 if (si == 0) break;
593 di = di - 2;
594 si --;
599 void UArray_removeOddIndexes(UArray *self)
601 size_t itemSize = self->itemSize;
602 size_t di = 1;
603 size_t si = 2;
604 size_t max = self->size;
605 uint8_t *b = self->data;
607 if (max == 0)
609 return;
612 while (si < max)
614 uint8_t *src = b + (si * itemSize);
615 uint8_t *dest = b + (di * itemSize);
616 memcpy(dest, src, itemSize);
617 si = si + 2;
618 di = di + 1;
621 UArray_setSize_(self, di);
624 void UArray_removeEvenIndexes(UArray *self)
626 size_t itemSize = self->itemSize;
627 size_t di = 0;
628 size_t si = 1;
629 size_t max = self->size;
630 uint8_t *b = self->data;
632 while (si < max)
634 uint8_t *src = b + (si * itemSize);
635 uint8_t *dest = b + (di * itemSize);
636 memcpy(dest, src, itemSize);
637 si = si + 2;
638 di = di + 1;
641 UArray_setSize_(self, di);
644 void UArray_reverseItemByteOrders(UArray *self)
646 size_t itemSize = self->itemSize;
648 if (itemSize > 1)
650 size_t i, max = self->size;
651 uint8_t *d = self->data;
653 for(i = 0; i < max; i ++)
655 size_t j;
657 for(j = 0; j < itemSize; j ++)
659 size_t i1 = i + j;
660 size_t i2 = i + itemSize - j;
661 uint8_t v = d[i1];
662 d[i1] = d[i2];
663 d[i2] = v;
667 UArray_changed(self);