Skip to content

Commit

Permalink
Added a new algo for sin() function, and a small error analysis to sh…
Browse files Browse the repository at this point in the history
…ow the precision differences
  • Loading branch information
Toufinet committed Jun 8, 2011
1 parent 297e94e commit 3b63453
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 1 deletion.
Binary file added images/error_analysis.ods
Binary file not shown.
8 changes: 7 additions & 1 deletion libfixmath/fix16.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ extern "C"

typedef int32_t fix16_t;

static const fix16_t FOUR_DIV_PI = 0x145F3; /*!< Fix16 value of 4/PI */
static const fix16_t _FOUR_DIV_PI2 = 0xFFFF9840; /*!< Fix16 value of -4/PI² */
static const fix16_t X4_CORRECTION_COMPONENT = 0x399A; /*!< Fix16 value of 0.225 */

static const fix16_t fix16_max = 0x7FFFFFFF; /*!< the maximum value of fix16_t */
static const fix16_t fix16_min = 0x80000000; /*!< the minimum value of fix16_t */

Expand Down Expand Up @@ -80,7 +84,9 @@ extern fix16_t fix16_lerp16(fix16_t inArg0, fix16_t inArg1, uint16_t inFract);
extern fix16_t fix16_lerp32(fix16_t inArg0, fix16_t inArg1, uint32_t inFract);
#endif


/*! Returns the sine of the given fix16_t.
*/
extern fix16_t fix16_sin_parabola(fix16_t inAngle);

/*! Returns the sine of the given fix16_t.
*/
Expand Down
30 changes: 30 additions & 0 deletions libfixmath/fix16_trig.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <limits.h>
#include "fix16.h"

#if defined(FIXMATH_SIN_LUT)
Expand All @@ -13,6 +14,35 @@ static fix16_t _fix16_atan_cache_value[4096] = { 0 };
#endif


fix16_t fix16_sin_parabola(fix16_t inAngle)
{
fix16_t abs_inAngle, abs_retval, retval;
fix16_t mask;

/* Absolute function */
mask = (inAngle >> (sizeof(fix16_t)*CHAR_BIT-1));
abs_inAngle = (inAngle + mask) ^ mask;

/* On 0->PI, sin looks like x² that is :
- centered on PI/2,
- equals 1 on PI/2,
- equals 0 on 0 and PI
that means : 4/PI * x - 4/PI² * x²
Use abs(x) to handle (-PI) -> 0 zone.
*/
retval = fix16_mul(FOUR_DIV_PI, inAngle) + fix16_mul( fix16_mul(_FOUR_DIV_PI2, inAngle), abs_inAngle );
/* At this point, retval equals sin(inAngle) on important points ( -PI, -PI/2, 0, PI/2, PI),
but is not very precise between these points
*/
#ifndef FIXMATH_FAST_SIN
/* Absolute value of retval */
mask = (retval >> (sizeof(fix16_t)*CHAR_BIT-1));
abs_retval = (retval + mask) ^ mask;
/* So improve its precision by adding some x^4 component to retval */
retval += fix16_mul(X4_CORRECTION_COMPONENT, fix16_mul(retval, abs_retval) - retval );
#endif
return retval;
}

fix16_t fix16_sin(fix16_t inAngle) {
fix16_t tempAngle = inAngle % (fix16_pi << 1);
Expand Down

0 comments on commit 3b63453

Please sign in to comment.