// Copyright (C) 2000-2007, Luca Padovani . // // This file is part of GtkMathView, a flexible, high-quality rendering // engine for MathML documents. // // GtkMathView is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License as published // by the Free Software Foundation; either version 3 of the License, or // (at your option) any later version. // // GtkMathView is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with this program. If not, see . #ifndef __fixed_hh__ #define __fixed_hh__ #include #include "gmv_defines.h" #ifdef _MSC_VER #undef min #undef max #endif template::digits / 2> class GMV_MathView_EXPORT fixed { public: fixed(void) : value(0) { } fixed(T v, bool) : value(v) { } fixed(T v) : value(static_cast(v) << precision) { } fixed(float v) : value(static_cast(v * (static_cast(1) << precision))) { } fixed(double v) : value(static_cast(v * (static_cast(1) << precision))) { } static fixed zero(void) { return fixed(0, true); } static fixed half(void) { return fixed(static_cast(1) << (precision - 1), true); } static fixed one(void) { return fixed(static_cast(1) << precision, true); } static fixed min(void) { return fixed(std::numeric_limits::min(), true); } static fixed max(void) { return fixed(std::numeric_limits::max(), true); } template friend fixed abs(const fixed&); template friend fixed trunc(const fixed&); template friend fixed round(const fixed&); template friend fixed ceil(const fixed&); template friend fixed floor(const fixed&); template friend fixed operator+(const fixed&, const fixed&); template friend fixed operator-(const fixed&, const fixed&); template friend fixed operator-(const fixed&); template friend fixed operator*(const fixed&, const fixed&); template friend fixed operator*(const fixed&, int); template friend fixed operator*(const fixed&, float); template friend fixed operator*(const fixed&, double); template friend fixed operator*(int, const fixed&); template friend fixed operator*(float, const fixed&); template friend fixed operator*(double, const fixed&); template friend fixed operator/(const fixed&, int); template friend fixed operator/(const fixed&, float); template friend fixed operator/(const fixed&, double); template friend fixed& operator+=(fixed&, const fixed&); template friend fixed& operator-=(fixed&, const fixed&); template friend fixed& operator*=(fixed&, int); template friend fixed& operator*=(fixed&, float); template friend fixed& operator*=(fixed&, double); template friend fixed& operator/=(fixed&, int); template friend fixed& operator/=(fixed&, float); template friend fixed& operator/=(fixed&, double); template friend bool operator==(const fixed&, const fixed&); template friend bool operator!=(const fixed&, const fixed&); template friend bool operator<(const fixed&, const fixed&); template friend bool operator>(const fixed&, const fixed&); template friend bool operator<=(const fixed&, const fixed&); template friend bool operator>=(const fixed&, const fixed&); static int getPrecision(void) { return precision; } int toInt(void) const { return value >> precision; } float toFloat(void) const { return static_cast(value) / fixed::one().value; } double toDouble(void) const { return static_cast(value) / fixed::one().value; } T getValue(void) const { return value; } private: T value; }; template inline GMV_MathView_EXPORT fixed abs(const fixed& f) { return fixed((f.value > 0) ? f.value : -f.value, true); } template inline GMV_MathView_EXPORT fixed trunc(const fixed& f) { if (f.value > 0) return fixed(f.value & ~(fixed::one().value - 1), true); else return fixed(-(-f.value & ~(fixed::one().value - 1)), true); } template inline GMV_MathView_EXPORT fixed round(const fixed& f) { if (f.value > 0) return trunc(f + fixed::half()); else return trunc(f - fixed::half()); } template inline GMV_MathView_EXPORT fixed ceil(const fixed& f) { if (f.value > 0) return round(f + fixed::half()); else return trunc(f); } template inline GMV_MathView_EXPORT fixed floor(const fixed& f) { if (f.value > 0) return trunc(f); else return round(f - fixed::half()); } template inline GMV_MathView_EXPORT fixed operator+(const fixed& f1, const fixed& f2) { return fixed(f1.value + f2.value, true); } template inline GMV_MathView_EXPORT fixed operator-(const fixed& f1, const fixed& f2) { return fixed(f1.value - f2.value, true); } template inline GMV_MathView_EXPORT fixed operator-(const fixed& f) { return fixed(-f.value, true); } template inline GMV_MathView_EXPORT fixed operator*(const fixed& f1, const fixed& f2) { T a = f1.value >> (p / 2); T a1 = f1.value & ((1 << (p / 2)) - 1); T b = f2.value >> (p / 2); T b1 = f2.value & ((1 << (p / 2)) - 1); return fixed(static_cast(a * b + ((a1 * b) >> (p / 2)) + ((a * b1) >> (p / 2)) + ((a1 * b1) >> p)), true); } template inline GMV_MathView_EXPORT fixed operator*(const fixed& f, int v) { return fixed(f.value * v, true); } template inline GMV_MathView_EXPORT fixed operator*(const fixed& f, float v) { return fixed(static_cast(f.value * v), true); } template inline GMV_MathView_EXPORT fixed operator*(const fixed& f, double v) { return fixed(static_cast(f.value * v), true); } template inline GMV_MathView_EXPORT fixed operator/(const fixed& f, int v) { return fixed(f.value / v, true); } template inline GMV_MathView_EXPORT fixed operator/(const fixed& f, float v) { return fixed(static_cast(f.value / v), true); } template inline GMV_MathView_EXPORT fixed operator/(const fixed& f, double v) { return fixed(static_cast(f.value / v), true); } template inline GMV_MathView_EXPORT fixed operator*(int v, const fixed& f) { return fixed(f.value * v, true); } template inline GMV_MathView_EXPORT fixed operator*(float v, const fixed& f) { return fixed(static_cast(f.value * v), true); } template inline GMV_MathView_EXPORT fixed operator*(double v, const fixed& f) { return fixed(static_cast(f.value * v), true); } template inline GMV_MathView_EXPORT fixed& operator+=(fixed& f1, const fixed& f2) { f1.value += f2.value; return f1; } template inline GMV_MathView_EXPORT fixed& operator-=(fixed& f1, const fixed& f2) { f1.value -= f2.value; return f1; } template inline GMV_MathView_EXPORT fixed& operator*=(fixed& f, int v) { f.value *= v; return f; } template inline GMV_MathView_EXPORT fixed& operator*=(fixed& f, float v) { f.value = static_cast(f.value * v); return f; } template inline GMV_MathView_EXPORT fixed& operator*=(fixed& f, double v) { f.value = static_cast(f.value * v); return f; } template inline GMV_MathView_EXPORT fixed& operator/=(const fixed& f, int v) { f.value /= v; return f; } template inline GMV_MathView_EXPORT fixed& operator/=(const fixed& f, float v) { f.value = static_cast(f.value / v); return f; } template inline GMV_MathView_EXPORT fixed& operator/=(const fixed& f, double v) { f.value = static_cast(f.value / v); return f; } template inline GMV_MathView_EXPORT bool operator==(const fixed& f1, const fixed& f2) { return f1.value == f2.value; } template inline GMV_MathView_EXPORT bool operator!=(const fixed& f1, const fixed& f2) { return f1.value != f2.value; } template inline GMV_MathView_EXPORT bool operator<(const fixed& f1, const fixed& f2) { return f1.value < f2.value; } template inline GMV_MathView_EXPORT bool operator>(const fixed& f1, const fixed& f2) { return f1.value > f2.value; } template inline GMV_MathView_EXPORT bool operator<=(const fixed& f1, const fixed& f2) { return f1.value <= f2.value; } template inline GMV_MathView_EXPORT bool operator>=(const fixed& f1, const fixed& f2) { return f1.value >= f2.value; } #endif // __fixed_hh__