/* This software is licensed by the MIT License, see LICENSE file */ /* Copyright © 2022 Gregory Lirent */ #include "__internal/assert.h" #include "__internal/include.h" /*#####################################################################################################################*/ static ldbl_t normalize_value(const void* v, vtype t) { if (t == VTYPE_BOOLEAN || t == VTYPE_UINT8) { return *(u8_t*)v; } else if (t == VTYPE_UINT16) { return *(u16_t*)v; } else if (t == VTYPE_UINT32 || (sizeof(void*) == 4 && t == VTYPE_POINTER)) { return *(u32_t*)v; } else if (t == VTYPE_UINT64 || (sizeof(void*) == 8 && t == VTYPE_POINTER)) { return *(u64_t*)v; } else if (t == VTYPE_INT8) { return *(s8_t*)v; } else if (t == VTYPE_INT16) { return *(s16_t*)v; } else if (t == VTYPE_INT32) { return *(s32_t*)v; } else if (t == VTYPE_INT64) { return *(s64_t*)v; } else if (t == VTYPE_FLOAT) { return abs(*(fl_t*)v) <= FLT_EPSILON ? 0 : *(fl_t*)v; } else if (t == VTYPE_DOUBLE) { return abs(*(dbl_t*)v) <= DBL_EPSILON ? 0 : *(dbl_t*)v; } else return abs(*(ldbl_t*)v) <= LDBL_EPSILON ? 0 : *(ldbl_t*)v; } int libcdsb_vtype_compare_values(const void* s0, vtype t0, const void* s1, vtype t1) { if (t0 == t1) return libcdsb_vtype_compare_values_eq(s0, s1, t0); if (t0 <= VTYPE_LDOUBLE && t1 <= VTYPE_LDOUBLE) { ldbl_t d0, d1; d0 = normalize_value(s0, t0); d1 = normalize_value(s1, t1); return (abs(d0 - d1) <= LDBL_EPSILON) ? 0 : (d0 < d1 ? -1 : 1); } return t0 - t1; } /*#####################################################################################################################*/ int libcdsb_vtype_compare_values_eq(const void* s0, const void* s1, vtype t) { #define compare(T, s0, s1) *(T*)s0 == *(T*)s1 ? 0 : (*(T*)s0 < *(T*)s1 ? -1 : 1) if (s0 == s1) return 0; switch (t) { default: abort(); case VTYPE_INT8: return compare( s8_t, s0, s1); case VTYPE_INT16: return compare(s16_t, s0, s1); case VTYPE_INT32: return compare(s32_t, s0, s1); case VTYPE_INT64: return compare(s64_t, s0, s1); case VTYPE_BOOLEAN: case VTYPE_UINT8: return compare( u8_t, s0, s1); case VTYPE_UINT16: return compare(u16_t, s0, s1); case VTYPE_UINT32: u32_: return compare(u32_t, s0, s1); case VTYPE_POINTER: if (sizeof(void*) != 8) goto u32_; case VTYPE_UINT64: return compare(u64_t, s0, s1); case VTYPE_LDOUBLE: return (abs(*(ldbl_t*)s0 - *(ldbl_t*)s1) <= LDBL_EPSILON) ? 0 : (*(ldbl_t*)s0 < *(ldbl_t*)s1 ? -1 : 1); case VTYPE_DOUBLE: return (abs(*( dbl_t*)s0 - *( dbl_t*)s1) <= DBL_EPSILON) ? 0 : (*( dbl_t*)s0 < *( dbl_t*)s1 ? -1 : 1); case VTYPE_FLOAT: return (abs(*( fl_t*)s0 - *( fl_t*)s1) <= FLT_EPSILON) ? 0 : (*( fl_t*)s0 < *( fl_t*)s1 ? -1 : 1); case VTYPE_STRING: return string_compare(s0, s1); case VTYPE_ARRAY: return array_compare(s0, s1); case VTYPE_LIST: return list_compare(s0, s1); case VTYPE_MAP: return map_compare(s0, s1); case VTYPE_SET: return vset_compare(s0, s1); } #undef compare }