2 copyright: Steve Dekorte, 2006. All rights reserved.
3 license: See _BSDLicense.txt.
14 #include "simd_cp_emu.h"
19 #define LLVEC_DUALARG_OP(VNAME, COP, TYPE) \
20 void v ## TYPE ## _ ## VNAME(TYPE ##_t *aa, TYPE ##_t *bb, size_t size)\
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]); }\
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
);
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
);
66 UArray_error_(self
, "UArray_negate not supported on this type");
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
));
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
));
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
));
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
));
113 DUARRAY_OP(UARRAY_BASICOP_TYPES
, /=, self
, other
);
116 #define UARRAY_DOT(OP2, TYPE1, self, TYPE2, other)\
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]; }\
126 double UArray_dotProduct_(const UArray
*self
, const UArray
*other
)
128 DUARRAY_OP(UARRAY_DOT
, NULL
, self
, other
);
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
);
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
]); }
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
];
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
;
218 if (bytePos
>= UArray_sizeInBytes(self
)) return;
219 b
= self
->data
[bytePos
];
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
++)
236 for (j
= 0; j
< 8; j
++)
238 int v
= (b
>> j
) & 0x1;
239 UArray_appendCString_(out
, v
? "1" : "0");
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
;
272 for (i
= 0; i
< max
; i
++) { total
+= map
[data
[i
]]; }
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
);
300 #define UARRAY_DOP(OP) \
301 void UArray_ ## OP (UArray *self) { UARRAY_FOREACHASSIGN(self, i, v, OP((double)v)); }
321 void UArray_abs(UArray
*self
)
326 void UArray_square(UArray
*self
)
328 UArray_multiply_(self
, self
);
333 double UArray_sumAsDouble(const UArray
*self
)
336 UARRAY_FOREACH(self
, i
, v
, sum
+= v
);
340 double UArray_productAsDouble(const UArray
*self
)
343 UARRAY_FOREACH(self
, i
, v
, p
*= v
);
347 double UArray_arithmeticMeanAsDouble(const UArray
*self
)
349 return UArray_sumAsDouble(self
) / ((double)self
->size
);
352 double UArray_arithmeticMeanSquareAsDouble(const UArray
*self
)
355 UArray
*s
= UArray_clone(self
);
357 r
= UArray_arithmeticMeanAsDouble(s
);
362 double UArray_maxAsDouble(const UArray
*self
)
366 double max
= DBL_MIN
;
367 UARRAY_FOREACH(self
, i
, v
, if(v
> max
) { max
= v
; });
374 double UArray_minAsDouble(const UArray
*self
)
378 double max
= DBL_MAX
;
379 UARRAY_FOREACH(self
, i
, v
, if(v
< max
) { max
= v
; });
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
)
416 UArray
*s
= UArray_clone(self
);
418 a
= UArray_sumAsDouble(s
);
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]);
441 UArray_changed(self
);
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
;
457 if (self
->size
== other
->size
)
461 for (i
= 0; i
< max
; i
++)
463 float32_t d
= a
[i
] - b
[i
];
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
;
478 if (self
->size
== other
->size
)
482 for (i
= 0; i
< max
; i
++)
484 float32_t d
= a
[i
] - b
[i
];
489 return (double)sqrt((double)sum
);
497 void UArray_changed(UArray
*self
)
502 uintptr_t UArray_calcHash(UArray
*self
)
506 int i
, max
= UArray_sizeInBytes(self
);
507 uint8_t *data
= self
->data
;
509 for(i
= 0; i
< max
; 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,
529 uintptr_t UArray_hash(UArray
*self
)
533 self
->hash
= UArray_calcHash(self
);
534 if(self
->hash
== 0x0) self
->hash
= 0x1;
540 int UArray_equalsWithHashCheck_(UArray
*self
, UArray
*other
)
548 uintptr_t h1
= UArray_hash(self
);
549 uintptr_t h2
= UArray_hash(other
);
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
);
569 BASEKIT_API
void UArray_duplicateIndexes(UArray
*self
)
571 size_t size
= self
->size
;
572 int itemSize
= self
->itemSize
;
576 size_t si
= size
- 1;
577 size_t di
= (size
* 2) - 1;
580 UArray_setSize_(self
, self
->size
* 2);
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
);
599 void UArray_removeOddIndexes(UArray
*self
)
601 size_t itemSize
= self
->itemSize
;
604 size_t max
= self
->size
;
605 uint8_t *b
= self
->data
;
614 uint8_t *src
= b
+ (si
* itemSize
);
615 uint8_t *dest
= b
+ (di
* itemSize
);
616 memcpy(dest
, src
, itemSize
);
621 UArray_setSize_(self
, di
);
624 void UArray_removeEvenIndexes(UArray
*self
)
626 size_t itemSize
= self
->itemSize
;
629 size_t max
= self
->size
;
630 uint8_t *b
= self
->data
;
634 uint8_t *src
= b
+ (si
* itemSize
);
635 uint8_t *dest
= b
+ (di
* itemSize
);
636 memcpy(dest
, src
, itemSize
);
641 UArray_setSize_(self
, di
);
644 void UArray_reverseItemByteOrders(UArray
*self
)
646 size_t itemSize
= self
->itemSize
;
650 size_t i
, max
= self
->size
;
651 uint8_t *d
= self
->data
;
653 for(i
= 0; i
< max
; i
++)
657 for(j
= 0; j
< itemSize
; j
++)
660 size_t i2
= i
+ itemSize
- j
;
667 UArray_changed(self
);