Serious-Engine/Sources/Engine/Math/FixInt.h
2016-03-11 15:57:17 +02:00

86 lines
4.4 KiB
C++

/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */
#ifndef SE_INCL_FIXINT_H
#define SE_INCL_FIXINT_H
#ifdef PRAGMA_ONCE
#pragma once
#endif
/*
* iInt - number of bits in integer part
* iFrac - number of bits in fractional part
* NOTE: Since 32 bit integer holds this fix int, iInt+iFrac must be 32.
*/
/*
* Template class for fixed integer with arbitrary sizes of integer and fractional parts
*/
template<int iInt, int iFrac>
class FixInt {
//implementation:
public:
SLONG slHolder; // the representation is stored here
//interface:
public:
/* Default constructor. */
inline FixInt<iInt, iFrac>(void) {};
/* Copy constructor. */
inline FixInt<iInt, iFrac>(const FixInt<iInt, iFrac> &x) { slHolder = x.slHolder; };
/* Constructor from integer. */
inline FixInt<iInt, iFrac>(SLONG sl) : slHolder(sl<<iFrac) {};
inline FixInt<iInt, iFrac>(ULONG ul) : slHolder((SLONG)(ul<<iFrac)) {};
inline FixInt<iInt, iFrac>(SWORD sw) : slHolder((SLONG)(sw<<iFrac)) {};
inline FixInt<iInt, iFrac>(UWORD uw) : slHolder((SLONG)(uw<<iFrac)) {};
inline FixInt<iInt, iFrac>(SBYTE sb) : slHolder((SLONG)(sb<<iFrac)) {};
inline FixInt<iInt, iFrac>(UBYTE ub) : slHolder((SLONG)(ub<<iFrac)) {};
inline FixInt<iInt, iFrac>(signed int si) : slHolder((SLONG)(si<<iFrac)) {};
inline FixInt<iInt, iFrac>(unsigned int ui) : slHolder((SLONG)(ui<<iFrac)) {};
/* Constructor from float. */
inline FixInt<iInt, iFrac>(float f) : slHolder((SLONG)(f*(1L<<iFrac))) {};
inline FixInt<iInt, iFrac>(double f) : slHolder((SLONG)(f*(1L<<iFrac))) {};
/* Set holder constructor. */
inline FixInt<iInt, iFrac>(SLONG slNewHolder, int iDummy) : slHolder(slNewHolder) {};
/* Conversion to integer (truncatenation). */
inline operator SLONG(void) const { return slHolder>>iFrac; };
/* Conversion to float (exact). */
inline operator float(void) const { return slHolder/(float) (1L<<iFrac); };
inline operator double(void) const { return slHolder/(double)(1L<<iFrac); };
/* Negation. */
inline FixInt<iInt, iFrac> operator-(void) const { return FixInt<iInt, iFrac>(-slHolder, 1); };
/* Addition. */
inline FixInt<iInt, iFrac> &operator+=(FixInt<iInt, iFrac> x) { slHolder += x.slHolder; return *this; };
inline FixInt<iInt, iFrac> operator+(FixInt<iInt, iFrac> x) const { return FixInt<iInt, iFrac>(slHolder+x.slHolder, 1); };
/* Substraction. */
inline FixInt<iInt, iFrac> &operator-=(FixInt<iInt, iFrac> x) { slHolder -= x.slHolder; return *this;};
inline FixInt<iInt, iFrac> operator-(FixInt<iInt, iFrac> x) const { return FixInt<iInt, iFrac>(slHolder-x.slHolder, 1); };
/* Multiplication. */
inline FixInt<iInt, iFrac> operator*(FixInt<iInt, iFrac> x) const { return FixInt<iInt, iFrac>( (SLONG)((__int64(slHolder)*x.slHolder) >>iFrac), 1); };
inline FixInt<iInt, iFrac> operator*(SLONG sl) const { return FixInt<iInt, iFrac>(slHolder*sl, 1); };
friend inline FixInt<iInt, iFrac> operator*(SLONG sl, FixInt<iInt, iFrac> x){ return FixInt<iInt, iFrac>(x.slHolder*sl, 1); };
inline FixInt<iInt, iFrac> &operator*=(FixInt<iInt, iFrac> x) { return *this = *this*x; };
/* Division. */
inline FixInt<iInt, iFrac> operator/(FixInt<iInt, iFrac> x) const { return FixInt<iInt, iFrac>( (SLONG) ( (__int64(slHolder)<<iFrac) / x.slHolder ) , 1); };
inline FixInt<iInt, iFrac> &operator/=(FixInt<iInt, iFrac> x) { return *this = *this/x; };
/* Relational operators. */
inline BOOL operator< (FixInt<iInt, iFrac> x) const { return slHolder< x.slHolder; };
inline BOOL operator<=(FixInt<iInt, iFrac> x) const { return slHolder<=x.slHolder; };
inline BOOL operator> (FixInt<iInt, iFrac> x) const { return slHolder> x.slHolder; };
inline BOOL operator>=(FixInt<iInt, iFrac> x) const { return slHolder>=x.slHolder; };
inline BOOL operator==(FixInt<iInt, iFrac> x) const { return slHolder==x.slHolder; };
inline BOOL operator!=(FixInt<iInt, iFrac> x) const { return slHolder!=x.slHolder; };
/* Rounding and truncatenation functions. */
friend inline SLONG Floor(FixInt<iInt, iFrac> x) { return (x.slHolder)>>iFrac; };
friend inline SLONG Ceil(FixInt<iInt, iFrac> x) { return (x.slHolder+(0xFFFFFFFFL>>iInt))>>iFrac; };
/* Truncatenate to fixed number of decimal bits. */
friend inline FixInt<iInt, iFrac> Trunc(FixInt<iInt, iFrac> x, int iDecimalPart) {
return FixInt<iInt, iFrac>(x.slHolder& (0xFFFFFFFF*((1<<iFrac)/iDecimalPart)), 1);};
};
#endif /* include-once check. */