diff --git a/legacy/eina/src/include/eina_convert.h b/legacy/eina/src/include/eina_convert.h index 332e442245..e82dda5243 100644 --- a/legacy/eina/src/include/eina_convert.h +++ b/legacy/eina/src/include/eina_convert.h @@ -56,6 +56,7 @@ EAPI int eina_convert_itoa(int n, char *s) EINA_ARG_NONNULL(2); EAPI int eina_convert_xtoa(unsigned int n, char *s) EINA_ARG_NONNULL(2); EAPI int eina_convert_dtoa(double d, char *des) EINA_ARG_NONNULL(2); EAPI Eina_Bool eina_convert_atod(const char *src, int length, long long *m, long *e) EINA_ARG_NONNULL(1,3,4); +EAPI int eina_convert_fptoa(Eina_F32p32 fp, char *des) EINA_ARG_NONNULL(2); /** * @} diff --git a/legacy/eina/src/lib/eina_convert.c b/legacy/eina/src/lib/eina_convert.c index 4f095ec1bc..a5464ea679 100644 --- a/legacy/eina/src/lib/eina_convert.c +++ b/legacy/eina/src/lib/eina_convert.c @@ -32,6 +32,7 @@ /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ #include "eina_safety_checks.h" #include "eina_convert.h" +#include "eina_f32p32.h" /*============================================================================* * Local * @@ -71,6 +72,28 @@ static inline void reverse(char s[], int length) } } +static inline Eina_F32p32 eina_f32p32_mul2(Eina_F32p32 fp) +{ + int64_t low; + int64_t high; + + low = (fp & 0x00000000ffffffffLL) << 1; + high = (fp >> 32) << 33; + + return low + high; +} + +static inline Eina_F32p32 eina_f32p32_mul16(Eina_F32p32 fp) +{ + int64_t low; + int64_t high; + + low = (fp & 0x00000000ffffffffLL) << 4; + high = (fp >> 32) << 36; + + return low + high; +} + /** * @endcond */ @@ -569,6 +592,94 @@ eina_convert_dtoa(double d, char *des) return length + eina_convert_itoa(p, des); } +EAPI int +eina_convert_fptoa(Eina_F32p32 fp, char *des) +{ + int length = 0; + int p = 0;; + int i; + + EINA_SAFETY_ON_NULL_RETURN_VAL(des, EINA_FALSE); + + if (fp == 0) + { + memcpy(des, "0x0p+0", 7); + return 7; + } + + if (fp < 0) + { + *(des++) = '-'; + fp = -fp; + length++; + } + + /* fp >= 1 */ + if (fp >= 0x0000000100000000LL) + { + while (fp >= 0x0000000100000000LL) + { + p++; + /* fp /= 2 */ + fp >>= 1; + } + } + /* fp < 0.5 */ + else if (fp < 0x80000000) + { + while (fp < 0x80000000) + { + p--; + /* fp *= 2 */ + fp <<= 1; + } + } + + if (p) + { + p--; + /* fp *= 2 */ + fp <<= 1; + } + + *(des++) = '0'; + *(des++) = 'x'; + *(des++) = look_up_table[fp >> 32]; + *(des++) = '.'; + length += 4; + + for (i = 0; i < 16; i++, length++) + { + fp &= 0x00000000ffffffffLL; + fp <<= 4; /* fp *= 16 */ + *(des++) = look_up_table[fp >> 32]; + } + + while (*(des - 1) == '0') + { + des--; + length--; + } + + if (*(des - 1) == '.') + { + des--; + length--; + } + + *(des++) = 'p'; + if (p < 0) + { + *(des++) = '-'; + p = -p; + } + else + *(des++) = '+'; + length += 2; + + return length + eina_convert_itoa(p, des); +} + /** * @} */ diff --git a/legacy/eina/src/tests/eina_test_convert.c b/legacy/eina/src/tests/eina_test_convert.c index 1f680dca18..719d4e3639 100644 --- a/legacy/eina/src/tests/eina_test_convert.c +++ b/legacy/eina/src/tests/eina_test_convert.c @@ -100,9 +100,43 @@ START_TEST(eina_convert_double) } END_TEST +static void +_eina_convert_fp_check(double d, Eina_F32p32 fp, int length) +{ + char tmp1[128]; + char tmp2[128]; + int l1; + int l2; + + l1 = eina_convert_dtoa(d, tmp1); + l2 = eina_convert_fptoa(fp, tmp2); + fail_if(l1 != l2); + fail_if(strcmp(tmp1, tmp2) != 0); + + d = -d; + fp = -fp; + + l1 = eina_convert_dtoa(d, tmp1); + l2 = eina_convert_fptoa(fp, tmp2); + fail_if(l1 != l2); + fail_if(strcmp(tmp1, tmp2) != 0); +} + +START_TEST(eina_convert_fp) +{ + _eina_convert_fp_check(1.0, 0x0000000100000000, 6); + _eina_convert_fp_check(0.5, 0x0000000080000000, 8); + _eina_convert_fp_check(0.625, 0x00000000a0000000, 8); + _eina_convert_fp_check(256.0, 0x0000010000000000, 6); + _eina_convert_fp_check(0.5, 0x0000000080000000, 9); + _eina_convert_fp_check(128.625, 0x00000080a0000000, 10); +} +END_TEST + void eina_test_convert(TCase *tc) { tcase_add_test(tc, eina_convert_simple); tcase_add_test(tc, eina_convert_double); + tcase_add_test(tc, eina_convert_fp); }