* eina: Improve precision of f32p32 sinus/cosinus.
authorCedric BAIL <cedric.bail@free.fr>
Wed, 9 Dec 2009 13:03:23 +0000 (13:03 +0000)
committerCedric BAIL <cedric.bail@free.fr>
Wed, 9 Dec 2009 13:03:23 +0000 (13:03 +0000)
SVN revision: 44322

legacy/eina/src/include/eina_fp.h
legacy/eina/src/include/eina_inline_f32p32.x
legacy/eina/src/lib/eina_fp.c

index 8a324af..e362940 100644 (file)
@@ -20,6 +20,8 @@
 #ifndef EINA_FP_H_
 # define EINA_FP_H_
 
+#include "eina_types.h"
+
 #ifdef _MSC_VER
 typedef unsigned __int64 uint64_t;
 typedef signed __int64 int64_t;
@@ -47,6 +49,9 @@ static inline Eina_F32p32 eina_f32p32_div(Eina_F32p32 a, Eina_F32p32 b);
 static inline Eina_F32p32 eina_f32p32_sqrt(Eina_F32p32 a);
 static inline unsigned int eina_f32p32_fracc_get(Eina_F32p32 v);
 
+// dont use llabs - issues if not on 64bit
+#define eina_fp32p32_llabs(a) ((a < 0) ? -(a) : (a))
+
 EAPI Eina_F32p32 eina_f32p32_cos(Eina_F32p32 a);
 EAPI Eina_F32p32 eina_f32p32_sin(Eina_F32p32 a);
 
index 06a6339..7eaaec3 100644 (file)
@@ -21,9 +21,6 @@
 
 #include <stdlib.h>
 
-// dont use llabs - issues if not on 64bit
-#define _eina_fp32p32_llabs(a) ((a < 0) ? -(a) : (a))
-
 static inline Eina_F32p32
 eina_f32p32_add(Eina_F32p32 a, Eina_F32p32 b)
 {
@@ -48,8 +45,8 @@ eina_f32p32_mul(Eina_F32p32 a, Eina_F32p32 b)
    Eina_F32p32 sign;
 
    sign = a ^ b;
-   as = _eina_fp32p32_llabs(a);
-   bs = _eina_fp32p32_llabs(b);
+   as = eina_fp32p32_llabs(a);
+   bs = eina_fp32p32_llabs(b);
 
    up = (as >> 16) * (bs >> 16);
    down = (as & 0xFFFF) * (bs & 0xFFFF);
@@ -76,7 +73,7 @@ eina_f32p32_div(Eina_F32p32 a, Eina_F32p32 b)
    if (b == 0)
      return sign < 0 ? (Eina_F32p32) 0x8000000000000000ll : (Eina_F32p32) 0x7FFFFFFFFFFFFFFFll;
 
-   result = (eina_f32p32_mul(_eina_fp32p32_llabs(a),  (((uint64_t) 1 << 62) / ((uint64_t)(_eina_fp32p32_llabs(b)) >> 2))));
+   result = (eina_f32p32_mul(eina_fp32p32_llabs(a),  (((uint64_t) 1 << 62) / ((uint64_t)(eina_fp32p32_llabs(b)) >> 2))));
 
    return sign < 0 ? - result : result;
 }
index 98a8c63..d9ec9ba 100644 (file)
@@ -124,27 +124,38 @@ eina_f32p32_cos(Eina_F32p32 a)
    Eina_F32p32 F32P32_3PI2;
    Eina_F32p32 remainder_2PI;
    Eina_F32p32 remainder_PI;
+   Eina_F32p32 interpol;
    Eina_F32p32 result;
    int index;
+   int index2;
 
    F32P32_2PI = EINA_F32P32_PI << 1;
    F32P32_PI2 = EINA_F32P32_PI >> 1;
    F32P32_3PI2 = EINA_F32P32_PI + F32P32_PI2;
 
+   /* Take advantage of cosinus symetrie. */
+   a = eina_fp32p32_llabs(a);
+
    /* Find table entry in 0 to PI / 2 */
    remainder_PI = a - (a / EINA_F32P32_PI) * EINA_F32P32_PI;
 
    /* Find which case from 0 to 2 * PI */
    remainder_2PI = a - (a / F32P32_2PI) * F32P32_2PI;
 
-   index = eina_f32p32_int_to(eina_f32p32_div(eina_f32p32_scale(remainder_PI, MAX_PREC * 2),
-                                             EINA_F32P32_PI));
-
-
+   interpol = eina_f32p32_div(eina_f32p32_scale(remainder_PI, MAX_PREC * 2),
+                             EINA_F32P32_PI);
+   index = eina_f32p32_int_to(interpol);
    if (index >= MAX_PREC)
      index = 2 * MAX_PREC - (index - 1);
 
-   result = eina_trigo[index];
+   index2 = index + 1;
+   if (index2 == MAX_PREC)
+     index2 = index - 1;
+
+   result = eina_f32p32_add(eina_trigo[index],
+                           eina_f32p32_mul(eina_f32p32_sub(eina_trigo[index],
+                                                           eina_trigo[index2]),
+                                           (Eina_F32p32) eina_f32p32_fracc_get(interpol)));
 
    if (0 <= remainder_2PI && remainder_2PI < F32P32_PI2)
      return result;
@@ -164,8 +175,10 @@ eina_f32p32_sin(Eina_F32p32 a)
    Eina_F32p32 F32P32_3PI2;
    Eina_F32p32 remainder_2PI;
    Eina_F32p32 remainder_PI;
+   Eina_F32p32 interpol;
    Eina_F32p32 result;
    int index;
+   int index2;
 
    F32P32_2PI = EINA_F32P32_PI << 1;
    F32P32_PI2 = EINA_F32P32_PI >> 1;
@@ -174,18 +187,29 @@ eina_f32p32_sin(Eina_F32p32 a)
    /* We only have a table for cosinus, but sin(a) = cos(pi / 2 - a) */
    a = eina_f32p32_sub(F32P32_PI2, a);
 
+   /* Take advantage of cosinus symetrie. */
+   a = eina_fp32p32_llabs(a);
+
    /* Find table entry in 0 to PI / 2 */
    remainder_PI = a - (a / EINA_F32P32_PI) * EINA_F32P32_PI;
 
    /* Find which case from 0 to 2 * PI */
    remainder_2PI = a - (a / F32P32_2PI) * F32P32_2PI;
 
-   index = eina_f32p32_int_to(eina_f32p32_div(eina_f32p32_scale(remainder_PI, MAX_PREC * 2),
-                                             EINA_F32P32_PI));
+   interpol = eina_f32p32_div(eina_f32p32_scale(remainder_PI, MAX_PREC * 2),
+                             EINA_F32P32_PI);
+   index = eina_f32p32_int_to(interpol);
    if (index >= MAX_PREC)
      index = MAX_PREC - (index + 1);
 
-   result = eina_trigo[index];
+   index2 = index + 1;
+   if (index2 == MAX_PREC)
+     index2 = index - 1;
+
+   result = eina_f32p32_add(eina_trigo[index],
+                           eina_f32p32_mul(eina_f32p32_sub(eina_trigo[index],
+                                                           eina_trigo[index2]),
+                                           (Eina_F32p32) eina_f32p32_fracc_get(interpol)));
 
    if (0 <= remainder_2PI && remainder_2PI < F32P32_PI2)
      return result;