diff options
Diffstat (limited to 'src/util/fixed_point.h')
-rw-r--r-- | src/util/fixed_point.h | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/src/util/fixed_point.h b/src/util/fixed_point.h new file mode 100644 index 0000000..44174d0 --- /dev/null +++ b/src/util/fixed_point.h @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Util::FixedPoint - fixed point type + * + * Authors: + * Jasper van de Gronde <th.v.d.gronde@hccnet.net> + * + * Copyright (C) 2006 Jasper van de Gronde + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#ifndef SEEN_INKSCAPE_UTIL_FIXED_POINT_H +#define SEEN_INKSCAPE_UTIL_FIXED_POINT_H + +#include <cmath> +#include <algorithm> +#include <limits> + +namespace Inkscape { + +namespace Util { + +template <typename T, unsigned int precision> +class FixedPoint { +public: + FixedPoint() = default; + FixedPoint(const FixedPoint& value) : v(value.v) {} + FixedPoint(char value) : v(static_cast<T>(value)<<precision) {} + FixedPoint(unsigned char value) : v(static_cast<T>(value)<<precision) {} + FixedPoint(short value) : v(static_cast<T>(value)<<precision) {} + FixedPoint(unsigned short value) : v(static_cast<T>(value)<<precision) {} + FixedPoint(int value) : v(static_cast<T>(value)<<precision) {} + FixedPoint(unsigned int value) : v(static_cast<T>(value)<<precision) {} + FixedPoint(double value) : v(static_cast<T>(floor(value*(1<<precision)))) {} + + FixedPoint& operator+=(FixedPoint val) { v += val.v; return *this; } + FixedPoint& operator-=(FixedPoint val) { v -= val.v; return *this; } + FixedPoint& operator*=(FixedPoint val) { + const unsigned int half_size = 8*sizeof(T)/2; + const T al = v&((1<<half_size)-1), bl = val.v&((1<<half_size)-1); + const T ah = v>>half_size, bh = val.v>>half_size; + v = static_cast<unsigned int>(al*bl)>>precision; + if ( half_size >= precision ) { + v += ((al*bh)+(ah*bl)+((ah*bh)<<half_size))<<(half_size-precision); + } else { + v += ((al*bh)+(ah*bl))>>(precision-half_size); + v += (ah*bh)<<(2*half_size-precision); + } + return *this; + } + + FixedPoint& operator*=(char val) { v *= val; return *this; } + FixedPoint& operator*=(unsigned char val) { v *= val; return *this; } + FixedPoint& operator*=(short val) { v *= val; return *this; } + FixedPoint& operator*=(unsigned short val) { v *= val; return *this; } + FixedPoint& operator*=(int val) { v *= val; return *this; } + FixedPoint& operator*=(unsigned int val) { v *= val; return *this; } + + FixedPoint operator+(FixedPoint val) const { FixedPoint r(*this); return r+=val; } + FixedPoint operator-(FixedPoint val) const { FixedPoint r(*this); return r-=val; } + FixedPoint operator*(FixedPoint val) const { FixedPoint r(*this); return r*=val; } + + FixedPoint operator*(char val) const { FixedPoint r(*this); return r*=val; } + FixedPoint operator*(unsigned char val) const { FixedPoint r(*this); return r*=val; } + FixedPoint operator*(short val) const { FixedPoint r(*this); return r*=val; } + FixedPoint operator*(unsigned short val) const { FixedPoint r(*this); return r*=val; } + FixedPoint operator*(int val) const { FixedPoint r(*this); return r*=val; } + FixedPoint operator*(unsigned int val) const { FixedPoint r(*this); return r*=val; } + + float operator*(float val) const { return static_cast<float>(*this)*val; } + double operator*(double val) const { return static_cast<double>(*this)*val; } + + operator char() const { return v>>precision; } + operator unsigned char() const { return v>>precision; } + operator short() const { return v>>precision; } + operator unsigned short() const { return v>>precision; } + operator int() const { return v>>precision; } + operator unsigned int() const { return v>>precision; } + + operator float() const { return ldexpf(v,-precision); } + operator double() const { return ldexp(v,-precision); } +private: + T v; +}; + +template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(char a, FixedPoint<T,precision> b) { return b*=a; } +template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned char a, FixedPoint<T,precision> b) { return b*=a; } +template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(short a, FixedPoint<T,precision> b) { return b*=a; } +template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned short a, FixedPoint<T,precision> b) { return b*=a; } +template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(int a, FixedPoint<T,precision> b) { return b*=a; } +template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned int a, FixedPoint<T,precision> b) { return b*=a; } + +template<typename T, unsigned int precision> float operator *(float a, FixedPoint<T,precision> b) { return b*a; } +template<typename T, unsigned int precision> double operator *(double a, FixedPoint<T,precision> b) { return b*a; } + +} + +} + +#endif +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : |