Initial commit. Since its use in fgl and the Dingoo SDK the functions have been separated into more descriptive files/modules.

This commit is contained in:
Flatmush 2011-02-14 20:59:41 +00:00
commit 3420855dc0
17 changed files with 579 additions and 0 deletions

48
libfixmath/Makefile Normal file
View File

@ -0,0 +1,48 @@
#Project settings
PROJECT = libfixmath
LIB =
SRC = .
INC =
#Compiler settings
CPP = gcc
CC = gcc
AS = gcc
LD = gcc
AR = ar
CPP_FLAGS = -O2 $(INC) -Wall -Wextra -c
CC_FLAGS = -O2 $(INC) -Wall -Wextra -c
AS_FLAGS = $(CC_FLAGS) -D_ASSEMBLER_
LD_FLAGS = -Wall
# Find all source files
SRC_CPP = $(foreach dir, $(SRC), $(wildcard $(dir)/*.cpp))
SRC_C = $(foreach dir, $(SRC), $(wildcard $(dir)/*.c))
SRC_S = $(foreach dir, $(SRC), $(wildcard $(dir)/*.S))
OBJ_CPP = $(patsubst %.cpp, %.o, $(SRC_CPP))
OBJ_C = $(patsubst %.c, %.o, $(SRC_C))
OBJ_S = $(patsubst %.S, %.o, $(SRC_S))
OBJ = $(OBJ_CPP) $(OBJ_C) $(OBJ_S)
# Compile rules.
.PHONY : all
all: $(PROJECT).a
$(PROJECT).a: $(OBJ)
$(AR) rcs $(PROJECT).a $(OBJ)
$(OBJ_CPP) : %.o : %.cpp
$(CPP) $(CPP_FLAGS) -o $@ $<
$(OBJ_C) : %.o : %.c
$(CC) $(CC_FLAGS) -o $@ $<
$(OBJ_S) : %.o : %.S
$(AS) $(AS_FLAGS) -o $@ $<
# Clean rules
.PHONY : clean
clean:
rm -f $(PROJECT).a $(OBJ)

99
libfixmath/fix16.c Normal file
View File

@ -0,0 +1,99 @@
#include "fix16.h"
const fix16_t fix16_pi = 205887;
const fix16_t fix16_e = 178145;
const fix16_t fix16_one = 0x00010000;
double fix16_to_dbl(const fix16_t inVal) {
return ((double)inVal / 65536.0);
}
fix16_t fix16_from_dbl(const double inVal) {
return (fix16_t)(inVal * 65536.0);
}
float fix16_to_float(const fix16_t inVal) {
return ((float)inVal / 65536.0f);
}
fix16_t fix16_from_float(const float inVal) {
return (fix16_t)(inVal * 65536.0f);
}
int32_t fix16_to_int(const fix16_t inVal) {
return ((inVal + 0x00008000) >> 16);
}
fix16_t fix16_from_int(const int32_t inVal) {
return (inVal << 16);
}
fix16_t fix16_sadd(fix16_t inArg0, fix16_t inArg1) {
fix16_t tempResult = (inArg0 + inArg1);
if((tempResult > 0) && (inArg0 < 0) && (inArg1 < 0))
return 0x80000000;
if((tempResult < 0) && (inArg0 > 0) && (inArg1 > 0))
return 0x7FFFFFFF;
return tempResult;
}
fix16_t fix16_mul(fix16_t inArg0, fix16_t inArg1) {
int64_t tempResult = ((int64_t)inArg0 * (int64_t)inArg1) + 0x00008000;
tempResult >>= 16;
return tempResult;
}
fix16_t fix16_smul(fix16_t inArg0, fix16_t inArg1) {
int64_t tempResult = ((int64_t)inArg0 * (int64_t)inArg1) + 0x00008000;
tempResult >>= 16;
if(tempResult < fix16_MIN)
return fix16_MIN;
if(tempResult > fix16_MAX)
return fix16_MAX;
return tempResult;
}
fix16_t fix16_div(fix16_t inArg0, fix16_t inArg1) {
int64_t tempResult = inArg0;
tempResult <<= 16;
tempResult += (inArg1 >> 1);
tempResult /= inArg1;
return tempResult;
}
fix16_t fix16_sdiv(fix16_t inArg0, fix16_t inArg1) {
if(inArg1 == 0) {
if(inArg0 < 0)
return fix16_MIN;
return fix16_MAX;
}
int64_t tempResult = inArg0;
tempResult <<= 16;
tempResult += (inArg1 >> 1);
tempResult /= inArg1;
if(tempResult < fix16_MIN)
return fix16_MIN;
if(tempResult > fix16_MAX)
return fix16_MAX;
return tempResult;
}
fix16_t fix16_lerp16(fix16_t inArg0, fix16_t inArg1, uint16_t inFract) {
int64_t tempOut;
tempOut = ((int64_t)inArg0 * (fix16_one - inFract));
tempOut += ((int64_t)inArg1 * inFract);
tempOut >>= 16;
return (fix16_t)tempOut;
}

118
libfixmath/fix16.h Normal file
View File

@ -0,0 +1,118 @@
#ifndef __libfixmath_fix16_h__
#define __libfixmath_fix16_h__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#define fix16_MAX (fix16_t)0x7FFFFFFF /*!< the maximum value of fix16_t */
#define fix16_MIN (fix16_t)0x80000000 /*!< the minimum value of fix16_t */
typedef int32_t fix16_t;
extern const fix16_t fix16_pi; /*!< fix16_t value of pi */
extern const fix16_t fix16_e; /*!< fix16_t value of e */
extern const fix16_t fix16_one; /*!< fix16_t value of 1 */
/*! Coverts a fix16_t to a double and returns the result.
*/
extern double fix16_to_dbl(const fix16_t inVal);
/*! Converts a double to a fix16_t and returns the result.
*/
extern fix16_t fix16_from_dbl(const double inVal);
/*! Converts a fix16_t to a float and returns the result.
*/
extern float fix16_to_float(const fix16_t inVal);
/*! Converts a float to a fix16_t and returns the result.
*/
extern fix16_t fix16_from_float(const float inVal);
/*! Converts a fix16_t to a signed integer and returns the result.
*/
extern int32_t fix16_to_int(const fix16_t inVal);
/*! Converts a signed integer to a fix16_t and returns the result.
*/
extern fix16_t fix16_from_int(const int32_t inVal);
/*! Performs a saturated addition (overflow-protected) of the two given fix16_t's and returns the result.
*/
extern fix16_t fix16_sadd(fix16_t inArg0, fix16_t inArg1);
/*! Multiplies the two given fix16_t's and returns the result.
*/
extern fix16_t fix16_mul(fix16_t inArg0, fix16_t inArg1);
/*! Performs a saturated multiplication (overflow-protected) of the two given fix16_t's and returns the result.
*/
extern fix16_t fix16_smul(fix16_t inArg0, fix16_t inArg1);
/*! Divides the first given fix16_t by the second and returns the result.
*/
extern fix16_t fix16_div(fix16_t inArg0, fix16_t inArg1);
/*! Performs a saturated division (overflow-protected) of the first fix16_t by the second and returns the result.
*/
extern fix16_t fix16_sdiv(fix16_t inArg0, fix16_t inArg1);
/*! Returns the linear interpolation: (inArg0 * (1 - inFract)) + (inArg1 * inFract)
*/
extern fix16_t fix16_lerp16(fix16_t inArg0, fix16_t inArg1, uint16_t inFract);
/*! Returns the sine of the given fix16_t.
*/
extern fix16_t fix16_sin(fix16_t inAngle);
/*! Returns the cosine of the given fix16_t.
*/
extern fix16_t fix16_cos(fix16_t inAngle);
/*! Returns the tangent of the given fix16_t.
*/
extern fix16_t fix16_tan(fix16_t inAngle);
/*! Returns the arcsine of the given fix16_t.
*/
extern fix16_t fix16_asin(fix16_t inValue);
/*! Returns the arccosine of the given fix16_t.
*/
extern fix16_t fix16_acos(fix16_t inValue);
/*! Returns the arctangent of the given fix16_t.
*/
extern fix16_t fix16_atan(fix16_t inValue);
/*! Returns the arctangent of inY/inX.
*/
extern fix16_t fix16_atan2(fix16_t inY, fix16_t inX);
/*! Returns the square root of the given fix16_t.
*/
extern fix16_t fix16_sqrt(fix16_t inValue);
#ifdef __cplusplus
}
#endif
#endif

35
libfixmath/fix16_sqrt.c Normal file
View File

@ -0,0 +1,35 @@
#include "fix16.h"
fix16_t _fix16_sqrt_cache_index[4096] = { 0 };
fix16_t _fix16_sqrt_cache_value[4096] = { 0 };
fix16_t fix16_sqrt(fix16_t inValue) {
fix16_t tempIndex = (((inValue >> 16) ^ (inValue >> 4)) & 0x00000FFF);
if(_fix16_sqrt_cache_index[tempIndex] == inValue)
return _fix16_sqrt_cache_value[tempIndex];
int64_t tempOp = inValue; tempOp <<= 16;
int64_t tempOut = 0;
int64_t tempOne = 0x4000000000000000ULL;
while(tempOne > tempOp)
tempOne >>= 2;
while(tempOne != 0) {
if (tempOp >= tempOut + tempOne) {
tempOp -= tempOut + tempOne;
tempOut += tempOne << 1;
}
tempOut >>= 1;
tempOne >>= 2;
}
_fix16_sqrt_cache_index[tempIndex] = inValue;
_fix16_sqrt_cache_value[tempIndex] = tempOut;
return tempOut;
}

115
libfixmath/fix16_trig.c Normal file
View File

@ -0,0 +1,115 @@
#include "fix16.h"
fix16_t _fix16_sin_cache_index[4096] = { 0 };
fix16_t _fix16_sin_cache_value[4096] = { 0 };
fix16_t _fix16_atan_cache_index[4096] = { 0 };
fix16_t _fix16_atan_cache_value[4096] = { 0 };
fix16_t fix16_sin(fix16_t inAngle) {
fix16_t tempAngle = inAngle % (fix16_pi << 1);
if(tempAngle > fix16_pi)
tempAngle -= (fix16_pi << 1);
else if(tempAngle < -fix16_pi)
tempAngle += (fix16_pi << 1);
fix16_t tempIndex = ((inAngle >> 5) & 0x00000FFF);
if(_fix16_sin_cache_index[tempIndex] == inAngle)
return _fix16_sin_cache_value[tempIndex];
fix16_t tempAngleSq = fix16_mul(tempAngle, tempAngle);
fix16_t tempOut = tempAngle;
tempAngle = fix16_mul(tempAngle, tempAngleSq);
tempOut -= (tempAngle / 6);
tempAngle = fix16_mul(tempAngle, tempAngleSq);
tempOut += (tempAngle / 120);
tempAngle = fix16_mul(tempAngle, tempAngleSq);
tempOut -= (tempAngle / 5040);
tempAngle = fix16_mul(tempAngle, tempAngleSq);
tempOut += (tempAngle / 362880);
tempAngle = fix16_mul(tempAngle, tempAngleSq);
tempOut -= (tempAngle / 39916800);
_fix16_sin_cache_index[tempIndex] = inAngle;
_fix16_sin_cache_value[tempIndex] = tempOut;
return tempOut;
}
fix16_t fix16_cos(fix16_t inAngle) {
return fix16_sin(inAngle + (fix16_pi >> 1));
}
fix16_t fix16_tan(fix16_t inAngle) {
return fix16_div(fix16_sin(inAngle), fix16_cos(inAngle));
}
fix16_t fix16_asin(fix16_t inValue) {
if((inValue > 1) || (inValue < -1))
return 0;
fix16_t tempOut;
tempOut = (1 - fix16_mul(inValue, inValue));
tempOut = (inValue / fix16_sqrt(tempOut));
tempOut = fix16_atan(tempOut);
return tempOut;
}
fix16_t fix16_acos(fix16_t inValue) {
return ((fix16_pi >> 1) - fix16_asin(inValue));
}
fix16_t _fix16_atan(fix16_t inValue) {
fix16_t tempOut;
if(inValue > 29736) {
tempOut = (1 + fix16_mul(inValue, inValue));
tempOut = (1 + fix16_sqrt(tempOut));
tempOut = (inValue / tempOut);
tempOut = _fix16_atan(tempOut);
return (tempOut << 1);
}
fix16_t tempValue = inValue;
fix16_t tempValSq = fix16_mul(inValue, inValue);
tempOut = inValue;
tempValue = fix16_mul(tempValue, tempValSq);
tempOut += (tempValue / 3);
tempValue = fix16_mul(tempValue, tempValSq);
tempOut += (tempValue / 5);
tempValue = fix16_mul(tempValue, tempValSq);
tempOut += (tempValue / 7);
tempValue = fix16_mul(tempValue, tempValSq);
tempOut += (tempValue / 9);
tempValue = fix16_mul(tempValue, tempValSq);
tempOut += (tempValue / 11);
return tempOut;
}
fix16_t fix16_atan(fix16_t inValue) {
fix16_t tempIndex = (((inValue >> 16) ^ (inValue >> 4)) & 0x00000FFF);
if(_fix16_atan_cache_index[tempIndex] == inValue)
return _fix16_atan_cache_value[tempIndex];
fix16_t tempOut = _fix16_atan(inValue);
_fix16_atan_cache_index[tempIndex] = inValue;
_fix16_atan_cache_value[tempIndex] = tempOut;
return tempOut;
}
fix16_t fix16_atan2(fix16_t inY, fix16_t inX) {
if(inX == 0) {
if(inY == 0)
return 0;
if(inY > 0)
return (fix16_pi >> 1);
return -(fix16_pi >> 1);
}
if(inY > 0)
return fix16_atan(fix16_div(inY, inX));
if(inY >= 0)
return (fix16_pi + fix16_atan(fix16_div(inY, inX)));
return (-fix16_pi + fix16_atan(fix16_div(inY, inX)));
}

22
libfixmath/fixmath.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef __libfixmath_fixmath_h__
#define __libfixmath_fixmath_h__
#ifdef __cplusplus
extern "C"
{
#endif
/*!
\file fixmath.h
\brief Functions to perform fast accurate fixed-point math operations.
*/
#include "uint32.h"
#include "fract32.h"
#include "fix16.h"
#ifdef __cplusplus
}
#endif
#endif

25
libfixmath/fract32.c Normal file
View File

@ -0,0 +1,25 @@
#include "fract32.h"
fract32_t fract32_create(uint32_t inNumerator, uint32_t inDenominator) {
if(inDenominator <= inNumerator)
return 0xFFFFFFFF;
uint32_t tempMod = (inNumerator % inDenominator);
uint32_t tempDiv = (0xFFFFFFFF / (inDenominator - 1));
return (tempMod * tempDiv);
}
fract32_t fract32_invert(fract32_t inFract) {
return (0xFFFFFFFF - inFract);
}
uint32_t fract32_usmul(uint32_t inVal, fract32_t inFract) {
return (uint32_t)(((uint64_t)inVal * (uint64_t)inFract) >> 32);
}
int32_t fract32_smul(int32_t inVal, fract32_t inFract) {
if(inVal < 0)
return -fract32_usmul(-inVal, inFract);
return fract32_usmul(inVal, inFract);
}

36
libfixmath/fract32.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef __libfixmath_fract32_h__
#define __libfixmath_fract32_h__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
typedef uint32_t fract32_t;
/*! Creates a fraction using unsigned integers.
\param inNumerator the unsigned integer numerator
\param inDenominator the unsigned integer denominator
\return a fraction using the given numerator and denominator
*/
extern fract32_t fract32_create(uint32_t inNumerator, uint32_t inDenominator);
/*! Inverts the given fraction, swapping the numerator and the denominator.
*/
extern fract32_t fract32_invert(fract32_t inFract);
/*! Performs unsigned saturated (overflow-protected) multiplication with the two given fractions and returns the result as an unsigned integer.
*/
extern uint32_t fract32_usmul(uint32_t inVal, fract32_t inFract);
/*! Performs saturated (overflow-protected) multiplication with the two given fractions and returns the result as a signed integer.
*/
extern int32_t fract32_smul(int32_t inVal, fract32_t inFract);
#ifdef __cplusplus
}
#endif
#endif

BIN
libfixmath/libfixmath.a Normal file

Binary file not shown.

47
libfixmath/libfixmath.cbp Normal file
View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="libfixmath" />
<Option pch_mode="2" />
<Option compiler="gcc" />
<Build>
<Target title="dbg">
<Option output="libfixmath" prefix_auto="1" extension_auto="1" />
<Option working_dir="" />
<Option object_output="obj\dbg\" />
<Option type="2" />
<Option compiler="gcc" />
<Option createDefFile="1" />
<Compiler>
<Add option="-Wall" />
<Add option="-g" />
</Compiler>
</Target>
<Target title="rel">
<Option output="libfixmath" prefix_auto="1" extension_auto="1" />
<Option working_dir="" />
<Option object_output="obj\rel\" />
<Option type="2" />
<Option compiler="gcc" />
<Option createDefFile="1" />
<Compiler>
<Add option="-Wall" />
<Add option="-O2" />
</Compiler>
<Linker>
<Add option="-s" />
</Linker>
</Target>
</Build>
<Unit filename="main.c">
<Option compilerVar="CC" />
</Unit>
<Extensions>
<code_completion />
<envvars />
<debugger />
<lib_finder disable_auto="1" />
</Extensions>
</Project>
</CodeBlocks_project_file>

BIN
libfixmath/obj/dbg/fix16.o Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
libfixmath/obj/dbg/uint32.o Normal file

Binary file not shown.

15
libfixmath/uint32.c Normal file
View File

@ -0,0 +1,15 @@
#include "uint32.h"
uint32_t uint32_log2(uint32_t inVal) {
if(inVal == 0)
return 0;
uint32_t tempOut = 0;
if(inVal >= (1 << 16)) { inVal >>= 16; tempOut += 16; }
if(inVal >= (1 << 8)) { inVal >>= 8; tempOut += 8; }
if(inVal >= (1 << 4)) { inVal >>= 4; tempOut += 4; }
if(inVal >= (1 << 2)) { inVal >>= 2; tempOut += 2; }
if(inVal >= (1 << 1)) { tempOut += 1; }
return tempOut;
}

19
libfixmath/uint32.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef __libfixmath_uint32_h__
#define __libfixmath_uint32_h__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
/*! Performs an unsigned log-base2 on the specified unsigned integer and returns the result.
*/
extern uint32_t uint32_log2(uint32_t inVal);
#ifdef __cplusplus
}
#endif
#endif