synkro
0xdeadbeef
Any optimizations, comment and criticism are welcome!
Code:
#ifndef _FIXED_H_
#define _FIXED_H_
/*
** Fixed Point Class 16.16
**
** TODO
** - calculate limits for range check
**
** REV1
** - MULS and DIVS now with range check and intermediate long long
** - easier to use and read than macros
** - overloaded cast operators
** - only slooow math function (double conversion)
**
** Greets and shouts to the guys and gals @ gp32x.de
**
** ----------------------------------------------------------------------------
** "THE BEER-WARE LICENSE" (Revision 42):
** <synkro@gmx.net> wrote this file. As long as you retain this notice you
** can do whatever you want with this stuff. If we meet some day, and you think
** this stuff is worth it, you can buy me a beer in return SYNKRO
** ----------------------------------------------------------------------------
*/
#include <iostream>
#include <cmath>
using namespace std;
#define PI 3.1415926535
#define PRECISION 16
#define DOUBLE_FACTOR 65536.0
class Fixed
{
public:
Fixed(void) { fix = 0;}
Fixed(int n) { fix = n << PRECISION;}
Fixed(double f) { fix = (int) (f * DOUBLE_FACTOR);}
// cast operators
operator int() { return fix >> PRECISION; }
operator unsigned int() { return fix >> PRECISION; }
operator char() { return fix >> PRECISION; }
operator unsigned char() { return fix >> PRECISION; }
operator double() { return fix / DOUBLE_FACTOR; }
friend bool operator==(const Fixed a, const Fixed b) {return a.fix == b.fix;}
friend bool operator<(const Fixed a, const Fixed b) {return a.fix < b.fix;}
friend bool operator>(const Fixed a, const Fixed b) {return a.fix > b.fix;}
// math functions
int floor(void) { return (fix >> PRECISION); }
int ceil(void) { return (fix >> PRECISION)+1; }
Fixed sqrt(void) {Fixed t( std::sqrt(this->toDouble()) ); return t;}
Fixed sin(void) {Fixed t( std::sin(this->toDouble()) ); return t;}
Fixed cos(void) {Fixed t( std::cos(this->toDouble()) ); return t;}
Fixed tan(void) {Fixed t( std::tan(this->toDouble()) ); return t;}
Fixed abs(void) {Fixed t( std::abs(this->toDouble()) ); return t;}
// Addition
Fixed& operator+=(const Fixed a) { fix += a.fix; return *this; }
Fixed& operator+=(int n) { fix += (n << PRECISION); return *this; }
Fixed& operator+=(double d) { fix += (int) (d * DOUBLE_FACTOR); return *this; }
friend Fixed operator+(const Fixed a, const Fixed b) { Fixed t = a; return t += b; }
friend Fixed operator+(const int a, const Fixed b) { Fixed t = b; return t += a; }
friend Fixed operator+(const Fixed a, const int b) { Fixed t = a; return t += b; }
friend Fixed operator+(const double a, const Fixed b) { Fixed t = b; return t += a; }
friend Fixed operator+(const Fixed a, const double b) { Fixed t = a; return t += b; }
// Substraktion
Fixed& operator-=(Fixed a) { fix -= a.fix; return *this; }
Fixed& operator-=(int n) { fix -= (n << PRECISION); return *this; }
Fixed& operator-=(double d) { fix -= (int) (d * DOUBLE_FACTOR); return *this; }
friend Fixed operator-(const Fixed a, const Fixed b) { Fixed t = a; return t -= b; }
friend Fixed operator-(int a, Fixed b) { Fixed t(a); return t-=b; }
friend Fixed operator-(const Fixed a, const int b) { Fixed t = a; return t -= b; }
friend Fixed operator-(const double a, const Fixed b) { Fixed t(a); return t -= b; }
friend Fixed operator-(const Fixed a, const double b) { Fixed t = a; return t -= b; }
// Mult
inline Fixed& operator*=(Fixed a);
inline Fixed& operator*=(int n);
inline Fixed& operator*=(double d);
friend Fixed operator*(const Fixed a, const Fixed b) { Fixed t = a; return t *=b; }
friend Fixed operator*(const int a, const Fixed b) { Fixed t = b; return t *=a; }
friend Fixed operator*(const Fixed a, const int b) { Fixed t = a; return t *=b; }
friend Fixed operator*(const Fixed a, const double b) { Fixed t = a; return t *=b; }
friend Fixed operator*(const double a, const Fixed b) { Fixed t = b; return t *=a; }
// DIV
inline Fixed& operator/=(Fixed a);
inline Fixed& operator/=(int n);
inline Fixed& operator/=(double d);
friend Fixed operator/(const Fixed a, const Fixed b) { Fixed t = a; return t /=b; }
friend Fixed operator/(const int a, const Fixed b) { Fixed t(a); return t /=b; }
friend Fixed operator/(const Fixed a, const int b) { Fixed t = a; return t /=b; }
friend Fixed operator/(const double a, const Fixed b) { Fixed t(a); return t /=b; }
friend Fixed operator/(const Fixed a, const double b) { Fixed t = a; return t /=b; }
// stream output
friend ostream& operator<<(ostream &os, Fixed &obj);
private:
int fix;
int toInt(void) { return (fix >> PRECISION);}
float toDouble(void) { return fix/DOUBLE_FACTOR; }
};
/*
** FIXMUL with range check
** TODO: calculate range for variable precisions
*/
inline Fixed& Fixed::operator*=(Fixed a)
{
const long long a_long = a.fix;
const long long b_long = fix;
const long long result = b_long * a_long;
// check range
if(result > 0x7FFFFFFF0000LL)
{
fix = 0x7FFFFFFFL;
}
else if(result < -0x7FFFFFFF0000LL)
{
fix = 0x80000000L;
}
else
{
fix = result >> PRECISION;
}
return *this;
}
inline Fixed& Fixed::operator*=(int n)
{
Fixed a(n);
const long long a_long = a.fix;
const long long b_long = fix;
const long long result = b_long * a_long;
// check range
if(result > 0x7FFFFFFF0000LL)
{
fix = 0x7FFFFFFFL;
}
else if(result < -0x7FFFFFFF0000LL)
{
fix = 0x80000000L;
}
else
{
fix = result >> PRECISION;
}
return *this;
}
inline Fixed& Fixed::operator*=(double d)
{
Fixed a(d);
const long long a_long = a.fix;
const long long b_long = fix;
const long long result = b_long * a_long;
// check range
if(result > 0x7FFFFFFF0000LL)
{
fix = 0x7FFFFFFFL;
}
else if(result < -0x7FFFFFFFL)
{
fix = 0x80000000;
}
else
{
fix = result >> PRECISION;
}
return *this;
}
/*
** FIXDIV with simple checks
*/
inline Fixed& Fixed::operator/=(Fixed a)
{
// division by zero!
if(a.fix == 0)
{
if(fix < 0) fix = 0x80000000L;
if(fix > 0) fix = 0x7FFFFFFFL;
return *this;
}
const long long a_long = a.fix;
const long long b_long = fix;
const long long result = (b_long << PRECISION) / a_long;
// check range
if(result > 0x7FFFFFFF0000LL)
{
fix = 0x7FFFFFFFL;
}
else if(result < -0x7FFFFFFF0000LL)
{
fix = 0x80000000L;
}
else
{
fix = result;
}
return *this;
}
inline Fixed& Fixed::operator/=(int n)
{
Fixed a(n);
// division by zero!
if(a.fix == 0)
{
if(fix < 0) fix = 0x80000000L;
if(fix > 0) fix = 0x7FFFFFFFL;
return *this;
}
const long long a_long = a.fix;
const long long b_long = fix;
const long long result = (b_long << PRECISION) / a_long;
// check range
if(result > 0x7FFFFFFF0000LL)
{
fix = 0x7FFFFFFFL;
}
else if(result < -0x7FFFFFFF0000LL)
{
fix = 0x80000000L;
}
else
{
fix = result;
}
return *this;
}
inline Fixed& Fixed::operator/=(double d)
{
Fixed a(d);
// division by zero!
if(a.fix == 0)
{
if(fix < 0) fix = 0x80000000L;
if(fix > 0) fix = 0x7FFFFFFFL;
return *this;
}
const long long a_long = a.fix;
const long long b_long = fix;
const long long result = (b_long << PRECISION) / a_long;
// check range
if(result > 0x7FFFFFFF0000LL)
{
fix = 0x7FFFFFFFL;
}
else if(result < -0x7FFFFFFF0000LL)
{
fix = 0x80000000L;
}
else
{
fix = result;
}
return *this;
}
/*
** output stream fixed
** TODO: input stream
*/
inline ostream& operator<<(ostream &os, Fixed &obj)
{
double f = obj.toDouble();
os << f << "fix";
return os;
}
#endif
Last edited by a moderator: