Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added ability for fixed point number to be bigger than 4 byte. #5

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 23 additions & 21 deletions include/EAStdC/EAFixedPoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,12 @@ namespace StdC
///////////////////////////////////////////////////////////////////////////////
// class FPTemplate
//
#define FPTemplateDeclaration template<class T, int upShiftInt, int downShiftInt, int upMulInt, int downDivInt>
#define FPTemplateDeclaration template<class T, T upShiftInt, T downShiftInt, T upMulInt, T downDivInt>
#define FPTemplateType FPTemplate<T, upShiftInt, downShiftInt, upMulInt, downDivInt>

template <class T, //'T' must be a signed or unsigned integer type (e.g. long, unsigned long, etc.)
int upShiftInt, int downShiftInt,
int upMulInt, int downDivInt>
T upShiftInt, T downShiftInt,
T upMulInt, T downDivInt>

struct FPTemplate
{
Expand All @@ -152,12 +152,12 @@ struct FPTemplate
//Functions
FPTemplate() {}
FPTemplate(const FPTemplate& newValue) { value = newValue.value; }
FPTemplate(const int& newValue) { value = newValue << upShiftInt; }
FPTemplate(const unsigned int& newValue) { value = newValue << upShiftInt; }
FPTemplate(const long& newValue) { value = newValue << upShiftInt; }
FPTemplate(const unsigned long& newValue) { value = newValue << upShiftInt; }
FPTemplate(const float& newValue) { value = (int)(newValue * (float)upMulInt); }
FPTemplate(const double& newValue) { value = (int)(newValue * (double)upMulInt); }
FPTemplate(const int& newValue) { value = (T)(newValue) << upShiftInt; }
FPTemplate(const unsigned int& newValue) { value = (T)(newValue) << upShiftInt; }
FPTemplate(const long& newValue) { value = (T)(newValue) << upShiftInt; }
FPTemplate(const unsigned long& newValue) { value = (T)(newValue) << upShiftInt; }
FPTemplate(const float& newValue) { value = (T)(newValue * (float)upMulInt); }
FPTemplate(const double& newValue) { value = (T)(newValue * (double)upMulInt); }
void FromFixed(const int& newValue) { value = newValue; } // Accepts an int that is in fixed point format (i.e. shifted) already.
T AsFixed () { return value; } // Allows you to get the fixed point value itself and mess with it as you want.

Expand Down Expand Up @@ -245,15 +245,15 @@ struct FPTemplate
FPTemplate& operator+=(const unsigned int& argValue) { value += (T)(argValue<<upShiftInt); return *this; }
FPTemplate& operator+=(const long & argValue) { value += (T)(argValue<<upShiftInt); return *this; }
FPTemplate& operator+=(const unsigned long& argValue) { value += (T)(argValue<<upShiftInt); return *this; }
FPTemplate& operator+=(const float& argValue) { value += int(argValue*(float)upMulInt); return *this; }
FPTemplate& operator+=(const double& argValue) { value += int(argValue*(double)upMulInt); return *this; }
FPTemplate& operator+=(const float& argValue) { value += (T)(argValue*(float)upMulInt); return *this; }
FPTemplate& operator+=(const double& argValue) { value += (T)(argValue*(double)upMulInt); return *this; }
FPTemplate& operator-=(const FPTemplate& argValue) { value -= argValue.value; return *this; }
FPTemplate& operator-=(const int& argValue) { value -= (T)(argValue<<upShiftInt); return *this; }
FPTemplate& operator-=(const unsigned int& argValue) { value -= (T)(argValue<<upShiftInt); return *this; }
FPTemplate& operator-=(const long& argValue) { value -= (T)(argValue<<upShiftInt); return *this; }
FPTemplate& operator-=(const unsigned long& argValue) { value -= (T)(argValue<<upShiftInt); return *this; }
FPTemplate& operator-=(const float& argValue) { value -= int(argValue*(float)upMulInt); return *this; }
FPTemplate& operator-=(const double& argValue) { value -= int(argValue*(double)upMulInt); return *this; }
FPTemplate& operator-=(const float& argValue) { value -= (T)(argValue*(float)upMulInt); return *this; }
FPTemplate& operator-=(const double& argValue) { value -= (T)(argValue*(double)upMulInt); return *this; }
FPTemplate& operator*=(const FPTemplate& argValue) { value = FixedMul(value, argValue.value); return *this; }
FPTemplate& operator*=(const int& argValue) { value = FixedMul(value, argValue<<upShiftInt); return *this; }
FPTemplate& operator*=(const unsigned int& argValue) { value = FixedMul(value, argValue<<upShiftInt); return *this; }
Expand Down Expand Up @@ -289,10 +289,10 @@ struct FPTemplate
FPTemplate& operator<<=(int numBits) { value <<= numBits; return *this;}
FPTemplate& operator>>=(int numBits) { value >>= numBits; return *this;}

FPTemplate& operator++() { value += 1<<upShiftInt; return *this; }
FPTemplate& operator--() { value -= 1<<upShiftInt; return *this; }
FPTemplate operator++(int) { FPTemplate temp(*this); value += 1<<upShiftInt; return temp; }
FPTemplate operator--(int) { FPTemplate temp(*this); value -= 1<<upShiftInt; return temp; }
FPTemplate& operator++() { value += (T)(1)<<upShiftInt; return *this; }
FPTemplate& operator--() { value -= (T)(1)<<upShiftInt; return *this; }
FPTemplate operator++(int) { FPTemplate temp(*this); value += (T)(1)<<upShiftInt; return temp; }
FPTemplate operator--(int) { FPTemplate temp(*this); value -= (T)(1)<<upShiftInt; return temp; }

FPTemplate Abs() { if(value<0) return -value; return value; }
FPTemplate DivSafe(const FPTemplate& denominator) { FPTemplate temp; temp.FromFixed(FixedDivSafe(value, denominator.value)); return temp; }
Expand Down Expand Up @@ -516,14 +516,14 @@ inline FPTemplateType operator*(const FPTemplateType& t1, const FPTemplateType&
FPTemplateDeclaration
inline FPTemplateType operator*(const FPTemplateType& t1, const int& t2){
FPTemplateType temp;
temp.value = FPTemplateType::FixedMul(t1.value, t2<<upShiftInt);
temp.value = FPTemplateType::FixedMul(t1.value, (T)(t2)<<upShiftInt);
return temp;
}

FPTemplateDeclaration
inline FPTemplateType operator*(const int& t2, const FPTemplateType& t1){
FPTemplateType temp;
temp.value = FPTemplateType::FixedMul(t2<<upShiftInt, t1.value);
temp.value = FPTemplateType::FixedMul((T)(t2)<<upShiftInt, t1.value);
return temp;
}

Expand Down Expand Up @@ -705,14 +705,14 @@ inline FPTemplateType operator%(const FPTemplateType& t1, const FPTemplateType&
FPTemplateDeclaration
inline FPTemplateType operator%(const FPTemplateType& t1, const int& t2){
FPTemplateType temp;
temp.value = FPTemplateType::FixedMod(t1.value, t2<<upShiftInt);
temp.value = FPTemplateType::FixedMod(t1.value, (T)(t2)<<upShiftInt);
return temp;
}

FPTemplateDeclaration
inline FPTemplateType operator%(const int& t2, const FPTemplateType& t1){
FPTemplateType temp;
temp.value = FPTemplateType::FixedMod(t2<<upShiftInt, t1.value);
temp.value = FPTemplateType::FixedMod((T)(t2)<<upShiftInt, t1.value);
return temp;
}

Expand Down Expand Up @@ -992,6 +992,8 @@ typedef FPTemplate<uint32_t, 10, 22, 4194304, 1024> UFixed10;
typedef FPTemplate<int32_t, 24, 8, 16777216, 256> SFixed8; // 8:24 fixed point (24 bits of fraction)
typedef FPTemplate<uint32_t, 24, 8, 16777216, 256> UFixed8;

typedef FPTemplate<int64_t, 32, 32, 4294967296LL, 4294967296LL> SFixed32; // 32:32 fixed point (32 bits of fraction)

///////////////////////////////////////////////////////////////////////////////

#define FPDeclareTemplateSpecializations(TypeDef) \
Expand Down
114 changes: 114 additions & 0 deletions test/source/TestFixedPoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <EAStdC/EAFixedPoint.h>
#include <EAStdCTest/EAStdCTest.h>
#include <EATest/EATest.h>
#include <EAStdC/Int128_t.h>



Expand Down Expand Up @@ -57,8 +58,43 @@ static bool CompareValues(EA::StdC::SFixed16 a, double b)
const volatile uint64_t c = ((uint64_t)a) << 8;
return (int32_t)(uint32_t)(c % b);
}

static bool CompareValues(SFixed32 a, double b) {
#define Fixed32ToDouble(a) (((double)a) / (65536.0 * 65536.0))

const double c = Fixed32ToDouble(a.AsFixed());
return (fabs(c - b) < 0.01);
}
template <>
EASTDC_API int64_t FP_PASCAL SFixed32::FixedMul(const int64_t lhs,
const int64_t rhs) {
int128_t lhs128(lhs);
lhs128 *= rhs;
lhs128 >>= 32;

return lhs128.AsInt64();
}

template <>
EASTDC_API int64_t FP_PASCAL SFixed32::FixedDiv(const int64_t lhs,
const int64_t rhs) {
int128_t lhs128(lhs);
lhs128 <<= 32;
lhs128 /= rhs;

return lhs128.AsInt64();
}

template <>
EASTDC_API int64_t FP_PASCAL SFixed32::FixedMod(const int64_t lhs,
const int64_t rhs) {
int128_t c(lhs);
c <<= 32;
return (c % rhs).AsInt64();
}
}
}

#endif


Expand Down Expand Up @@ -224,6 +260,84 @@ int TestFixedPoint()
if(!CompareValues(a, 0.77333))
nErrorCount++;
}

//Test SFixed32
{
SFixed32 a(1), b(2), c(3.f), d(1.0);
double e = 3.2;
float f = 4.5;
int g = 6;

if (a.AsInt() != 1) nErrorCount++;
if (c.AsUnsignedInt() != 3) nErrorCount++;
if (a.AsLong() != 1) nErrorCount++;
if (c.AsUnsignedLong() != 3) nErrorCount++;
if (!CompareValues((double)a.AsFloat(), 1.0)) nErrorCount++;
if (!CompareValues(c.AsDouble(), 3.0)) nErrorCount++;

a = b * f;
if (!CompareValues(a, 9.0)) nErrorCount++;

a = b / d;
if (!CompareValues(a, 2.0)) nErrorCount++;

a = b + d;
if (!CompareValues(a, 3.0)) nErrorCount++;

a = (c / e) + b + f;
if (!CompareValues(a, 7.4375)) nErrorCount++;

a = c / e * (b % g) + f / c;
if (!CompareValues(a, 3.375)) nErrorCount++;

if (!CompareValues(b, 2.0)) nErrorCount++;
a = g * -c / (b++);
if (!CompareValues(a, -9.0)) nErrorCount++;
if (!CompareValues(b, 3.0)) nErrorCount++;
--b; // Restore it to its original value.
if (!CompareValues(b, 2.0)) nErrorCount++;

a = sin(d) + pow(b, e) * sqrt(d);
if (!CompareValues(a, 10.031)) nErrorCount++;

a = log(e) / log(f);
if (!CompareValues(a, 0.77333))
nErrorCount++;
}

{
SFixed32 a(16);

auto expected = a.value << 1;

a = (a << 1);

if (!CompareValues(a.value, expected)) nErrorCount++;
}

// FPTemplate operator>>(int numBits) const
{
SFixed32 a(16);

auto expected = a.value >> 1;

a = (a >> 1);

if (!CompareValues(a.value, expected)) nErrorCount++;
}

// Reported regression - ensure operator<< and operator>> are
// implemented correctly.
{
SFixed32 a(16);

auto expected = a.value;

a = (a << 1);
a = (a >> 1);

if (!CompareValues(a.value, expected)) nErrorCount++;
}
#endif

// Test core multiplication/division functions
Expand Down