diff options
author | Calvin Morrison <calvin@pobox.com> | 2023-04-05 14:13:39 -0400 |
---|---|---|
committer | Calvin Morrison <calvin@pobox.com> | 2023-04-05 14:13:39 -0400 |
commit | 835e373b3eeaabcd0621ed6798ab500f37982fae (patch) | |
tree | dfa16b0e2e1b4956b38f693220eac4e607802133 /goo/FixedPoint.h |
Diffstat (limited to 'goo/FixedPoint.h')
-rw-r--r-- | goo/FixedPoint.h | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/goo/FixedPoint.h b/goo/FixedPoint.h new file mode 100644 index 0000000..9f0c324 --- /dev/null +++ b/goo/FixedPoint.h @@ -0,0 +1,180 @@ +//======================================================================== +// +// FixedPoint.h +// +// Fixed point type, with C++ operators. +// +// Copyright 2004 Glyph & Cog, LLC +// +//======================================================================== + +#ifndef FIXEDPOINT_H +#define FIXEDPOINT_H + +#include <aconf.h> + +#if USE_FIXEDPOINT + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "gtypes.h" + +#define fixptShift 16 +#define fixptMaskL ((1 << fixptShift) - 1) +#define fixptMaskH (~fixptMaskL) + +typedef long long FixPtInt64; + +class FixedPoint { +public: + + FixedPoint() { val = 0; } + FixedPoint(const FixedPoint &x) { val = x.val; } + FixedPoint(double x) { val = (int)(x * (1 << fixptShift) + 0.5); } + FixedPoint(int x) { val = x << fixptShift; } + FixedPoint(Guint x) { val = x << fixptShift; } + FixedPoint(long x) { val = (int)x << fixptShift; } + + operator float() + { return (float) val * ((float)1 / (float)(1 << fixptShift)); } + operator double() + { return (double) val * (1.0 / (double)(1 << fixptShift)); } + operator int() + { return val >> fixptShift; } + + int get16Dot16() { return val; } + + FixedPoint operator =(FixedPoint x) { val = x.val; return *this; } + + bool operator ==(FixedPoint x) const { return val == x.val; } + bool operator ==(double x) const { return *this == (FixedPoint)x; } + bool operator ==(int x) const { return *this == (FixedPoint)x; } + bool operator ==(Guint x) const { return *this == (FixedPoint)x; } + bool operator ==(long x) const { return *this == (FixedPoint)x; } + + bool operator !=(FixedPoint x) const { return val != x.val; } + bool operator !=(double x) const { return *this != (FixedPoint)x; } + bool operator !=(int x) const { return *this != (FixedPoint)x; } + bool operator !=(Guint x) const { return *this != (FixedPoint)x; } + bool operator !=(long x) const { return *this != (FixedPoint)x; } + + bool operator <(FixedPoint x) const { return val < x.val; } + bool operator <(double x) const { return *this < (FixedPoint)x; } + bool operator <(int x) const { return *this < (FixedPoint)x; } + bool operator <(Guint x) const { return *this < (FixedPoint)x; } + bool operator <(long x) const { return *this < (FixedPoint)x; } + + bool operator <=(FixedPoint x) const { return val <= x.val; } + bool operator <=(double x) const { return *this <= (FixedPoint)x; } + bool operator <=(int x) const { return *this <= (FixedPoint)x; } + bool operator <=(Guint x) const { return *this <= (FixedPoint)x; } + bool operator <=(long x) const { return *this <= (FixedPoint)x; } + + bool operator >(FixedPoint x) const { return val > x.val; } + bool operator >(double x) const { return *this > (FixedPoint)x; } + bool operator >(int x) const { return *this > (FixedPoint)x; } + bool operator >(Guint x) const { return *this > (FixedPoint)x; } + bool operator >(long x) const { return *this > (FixedPoint)x; } + + bool operator >=(FixedPoint x) const { return val >= x.val; } + bool operator >=(double x) const { return *this >= (FixedPoint)x; } + bool operator >=(int x) const { return *this >= (FixedPoint)x; } + bool operator >=(Guint x) const { return *this >= (FixedPoint)x; } + bool operator >=(long x) const { return *this >= (FixedPoint)x; } + + FixedPoint operator -() { return make(-val); } + + FixedPoint operator +(FixedPoint x) { return make(val + x.val); } + FixedPoint operator +(double x) { return *this + (FixedPoint)x; } + FixedPoint operator +(int x) { return *this + (FixedPoint)x; } + FixedPoint operator +(Guint x) { return *this + (FixedPoint)x; } + FixedPoint operator +(long x) { return *this + (FixedPoint)x; } + + FixedPoint operator +=(FixedPoint x) { val = val + x.val; return *this; } + FixedPoint operator +=(double x) { return *this += (FixedPoint)x; } + FixedPoint operator +=(int x) { return *this += (FixedPoint)x; } + FixedPoint operator +=(Guint x) { return *this += (FixedPoint)x; } + FixedPoint operator +=(long x) { return *this += (FixedPoint)x; } + + FixedPoint operator -(FixedPoint x) { return make(val - x.val); } + FixedPoint operator -(double x) { return *this - (FixedPoint)x; } + FixedPoint operator -(int x) { return *this - (FixedPoint)x; } + FixedPoint operator -(Guint x) { return *this - (FixedPoint)x; } + FixedPoint operator -(long x) { return *this - (FixedPoint)x; } + + FixedPoint operator -=(FixedPoint x) { val = val - x.val; return *this; } + FixedPoint operator -=(double x) { return *this -= (FixedPoint)x; } + FixedPoint operator -=(int x) { return *this -= (FixedPoint)x; } + FixedPoint operator -=(Guint x) { return *this -= (FixedPoint)x; } + FixedPoint operator -=(long x) { return *this -= (FixedPoint)x; } + + FixedPoint operator *(FixedPoint x) { return make(mul(val, x.val)); } + FixedPoint operator *(double x) { return *this * (FixedPoint)x; } + FixedPoint operator *(int x) { return *this * (FixedPoint)x; } + FixedPoint operator *(Guint x) { return *this * (FixedPoint)x; } + FixedPoint operator *(long x) { return *this * (FixedPoint)x; } + + FixedPoint operator *=(FixedPoint x) { val = mul(val, x.val); return *this; } + FixedPoint operator *=(double x) { return *this *= (FixedPoint)x; } + FixedPoint operator *=(int x) { return *this *= (FixedPoint)x; } + FixedPoint operator *=(Guint x) { return *this *= (FixedPoint)x; } + FixedPoint operator *=(long x) { return *this *= (FixedPoint)x; } + + FixedPoint operator /(FixedPoint x) { return make(div(val, x.val)); } + FixedPoint operator /(double x) { return *this / (FixedPoint)x; } + FixedPoint operator /(int x) { return *this / (FixedPoint)x; } + FixedPoint operator /(Guint x) { return *this / (FixedPoint)x; } + FixedPoint operator /(long x) { return *this / (FixedPoint)x; } + + FixedPoint operator /=(FixedPoint x) { val = div(val, x.val); return *this; } + FixedPoint operator /=(double x) { return *this /= (FixedPoint)x; } + FixedPoint operator /=(int x) { return *this /= (FixedPoint)x; } + FixedPoint operator /=(Guint x) { return *this /= (FixedPoint)x; } + FixedPoint operator /=(long x) { return *this /= (FixedPoint)x; } + + static FixedPoint abs(FixedPoint x) { return make(::abs(x.val)); } + + static int floor(FixedPoint x) { return x.val >> fixptShift; } + + static int ceil(FixedPoint x) + { return (x.val & fixptMaskL) ? ((x.val >> fixptShift) + 1) + : (x.val >> fixptShift); } + + static int round(FixedPoint x) + { return (x.val + (1 << (fixptShift - 1))) >> fixptShift; } + + // Computes (x+y)/2 avoiding overflow and LSbit accuracy issues. + static FixedPoint avg(FixedPoint x, FixedPoint y) + { return make((x.val >> 1) + (y.val >> 1) + ((x.val | y.val) & 1)); } + + static FixedPoint sqrt(FixedPoint x); + + static FixedPoint pow(FixedPoint x, FixedPoint y); + + // Compute *result = x/y; return false if there is an underflow or + // overflow. + static GBool divCheck(FixedPoint x, FixedPoint y, FixedPoint *result); + + // Compute abs(m11*m22 - m12*m21) >= epsilon, handling the case + // where the multiplications overflow. + static GBool checkDet(FixedPoint m11, FixedPoint m12, + FixedPoint m21, FixedPoint m22, + FixedPoint epsilon); + +private: + + static FixedPoint make(int valA) { FixedPoint x; x.val = valA; return x; } + + static int mul(int x, int y); + static int div(int x, int y); + + int val; // fixed point: (n-fixptShift).(fixptShift) +}; + +#endif // USE_FIXEDPOINT + +#endif |