* eina: Add eina_fptoa.
authorCedric BAIL <cedric.bail@free.fr>
Wed, 23 Sep 2009 16:47:08 +0000 (16:47 +0000)
committerCedric BAIL <cedric.bail@free.fr>
Wed, 23 Sep 2009 16:47:08 +0000 (16:47 +0000)
This is a small piece of code, but a big one for an edje fixed point implementation.

SVN revision: 42646

legacy/eina/src/include/eina_convert.h
legacy/eina/src/lib/eina_convert.c
legacy/eina/src/tests/eina_test_convert.c

index 332e442..e82dda5 100644 (file)
@@ -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);
 
 /**
  * @}
index 4f095ec..a5464ea 100644 (file)
@@ -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);
+}
+
 /**
  * @}
  */
index 1f680dc..719d4e3 100644 (file)
@@ -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);
 }