fixed point
От: WinterMute Россия http://yarrr.ru
Дата: 22.04.05 12:31
Оценка: 28 (5)
Собственно шаблон класса для предсталения чисел с фиксированной точкой. Определены все основные арифметические операции, преобразование к типам double / float. Доступны методы: integer(), fractional(), float(), ceil(), round(). Интерестно узнать ваше мнение.



template< typename Type, uint t_shift >
class fixed_T
{
public:
    typedef Type value_type;

    static const value_type shift = t_shift;    // количество бит для хранения дробной части
    static const value_type scale = 1 << shift; // множитель для получения дробной части
    static const value_type f_max = scale - 1;  // максимальное значение дробной части
    static const value_type mask = scale - 1;   // маска для получения дробной части

private:
    value_type m_data;

    inline static int l_div( value_type a, value_type b )
    {
        return (a * scale) / b;
    }

    // Раскладывает число "v" на целую и дробные части
    static void analize( double v, value_type& integer, value_type& fractional )
    {
        integer = value_type(v);
        fractional = value_type( ( v - double(integer) ) * scale );
    }

    // Раскладывает число "v" на целую и дробные части
    static void analize( float v, value_type& integer, value_type& fractional )
    {
        integer = value_type(v);
        fractional = value_type( ( v - double(integer) ) * scale );
    }

public:
    fixed_T(){}

    explicit fixed_T(value_type v) : m_data( v * scale )
    {
    }

    explicit fixed_T(value_type integer, value_type fractional) : m_data(integer*scale + fractional)
    {
    }

    explicit fixed_T(double v)
    {
        value_type integer;
        value_type fractional;

        analize( v, integer, fractional );

        m_data = integer * scale + fractional;
    }

    explicit fixed_T(float v)
    {
        value_type integer;
        value_type fractional;

        analize( v, integer, fractional );

        m_data = integer * scale + fractional;
    }


    value_type value() const { return m_data; }
    value_type integer() const { return m_data/scale; }
    value_type fractional() const { return m_data%scale; }

    value_type sign() const { return value() > 0 ? 1 : -1; }
    bool isNegative() const { return value() < 0; }

    value_type round() const
    {
        return isNegative() ? (value() - scale/2) / scale 
                            : (value() + scale/2) / scale;
    }
    
    value_type ceil() const
    {
        return isNegative() ? value() / scale : ( value() + f_max ) / scale;
    }

    value_type floor() const
    {
        return isNegative() ? ( value() - f_max ) / scale : value() / scale;
    }

    //////////////////////////////////////////////////////////////////////////
    // Операторы
    //////////////////////////////////////////////////////////////////////////
    
    /// (+ и -) Сложение / вычитание

    fixed_T operator+(value_type a) const { return fixed_T( a, m_data ); }
    fixed_T operator-(value_type a) const { return fixed_T( 0, m_data - a*scale ); }
    fixed_T operator+(fixed_T f) const { return fixed_T( 0, m_data + f.m_data ); }
    fixed_T operator-(fixed_T f) const { return fixed_T( 0, m_data - f.m_data ); }
    fixed_T operator+(double a) const
    {
        value_type v_i, v_f;
        analize( a, v_i, v_f );
        return fixed_T( 0, m_data + v_i*scale + v_f );
    }
    fixed_T operator-(double a) const
    {
        value_type v_i, v_f;
        analize( a, v_i, v_f );
        return fixed_T( 0, m_data - v_i*scale - v_f );
    }
    fixed_T operator+(float a) const
    {
        value_type v_i, v_f;
        analize( a, v_i, v_f );
        return fixed_T( 0, m_data + v_i*scale + v_f );
    }
    fixed_T operator-(float a) const
    {
        value_type v_i, v_f;
        analize( a, v_i, v_f );
        return fixed_T( 0, m_data - v_i*scale - v_f );
    }

    /// (*) Умножение

    fixed_T operator*(value_type a) const { return fixed_T( 0, m_data*a ); }
    fixed_T operator*(fixed_T f) const
    {
        return fixed_T( 0, m_data*f.integer() + (m_data*f.fractional())/scale );
    }

    fixed_T operator*(double a) const
    {
        value_type v_i, v_f;
        analize( a, v_i, v_f );
        return fixed_T( 0, m_data*v_i + (m_data*v_f)/scale );
    }
    fixed_T operator*(float a) const
    {
        value_type v_i, v_f;
        analize( a, v_i, v_f );
        return fixed_T( 0, m_data*v_i + (m_data*v_f)/scale );
    }

    /// (/) Деление

    fixed_T operator/(value_type a) const { return fixed_T( 0, m_data/a ); }
    fixed_T operator/(fixed_T f) const { return fixed_T( 0, q_div( m_data, f.m_data ) ); }
    fixed_T operator/(double v) const { return fixed_T( 0, q_div( m_data, fixed_T(v).m_data ) ); }
    fixed_T operator/(float v) const { return fixed_T( 0, q_div( m_data, fixed_T(v).m_data ) ); }

    /// (+= и -=)

    fixed_T& operator+=(value_type a) { m_data += a*scale; return *this; }
    fixed_T& operator-=(value_type a) { m_data -= a*scale; return *this; }

    fixed_T& operator+=(fixed_T f) { m_data += f.m_data; return *this; }
    fixed_T& operator-=(fixed_T f) { m_data -= f.m_data; return *this; }

    fixed_T& operator+=(double a)
    {
        value_type v_i, v_f;
        analize( a, v_i, v_f );

        m_data += v_i*scale + v_f;
        return *this;
    }

    fixed_T& operator-=(double a)
    {
        value_type v_i, v_f;
        analize( a, v_i, v_f );

        m_data -= v_i*scale + v_f;
        return *this;
    }

    fixed_T& operator+=(float a)
    {
        value_type v_i, v_f;
        analize( a, v_i, v_f );

        m_data += v_i*scale + v_f;
        return *this;
    }

    fixed_T& operator-=(float a)
    {
        value_type v_i, v_f;
        analize( a, v_i, v_f );

        m_data -= v_i*scale + v_f;
        return *this;
    }

    // (/=)

    fixed_T& operator/=(value_type a) { m_data /= a; return *this; }
    
    fixed_T& operator/=(fixed_T f)
    {
        value_type quot = m_data / f.m_data;
        value_type rem = m_data % f.m_data;

        m_data = quot*scale + (rem*scale) / f.m_data;

        return *this;
    }

    fixed_T& operator/=(double a)
    {
        fixed f(a);
        
        value_type quot = m_data / f.m_data;
        value_type rem = m_data % f.m_data;

        m_data = quot*scale + (rem*scale) / f.m_data;
        
        return *this;
    }

    fixed_T& operator/=(float a)
    {
        fixed f(a);

        value_type quot = m_data / f.m_data;
        value_type rem = m_data % f.m_data;

        m_data = quot*scale + (rem*scale) / f.m_data;

        return *this;
    }

    // (*=)

    fixed_T& operator*=(value_type a) { m_data *= a; return *this; }

    fixed_T& operator*=(fixed_T f)
    {
        m_data = m_data*f.integer() + (m_data*f.fractional())/scale;
        return *this;
    }

    fixed_T& operator*=(double a)
    {
        value_type v_i, v_f;
        analize( a, v_i, v_f );

        m_data = m_data*v_i + (m_data*v_f)/scale;
        return *this;
    }

    fixed_T& operator*=(float a)
    {
        value_type v_i, v_f;
        analize( a, v_i, v_f );

        m_data = m_data*v_i + (m_data*v_f)/scale;
        return *this;
    }

    /// (++ и --)    
    
    fixed_T& operator++() { m_data += scale; return *this; }
    fixed_T& operator++(int) { m_data += scale; return *this; }
    fixed_T& operator--() { m_data -= scale; return *this; }
    fixed_T& operator--(int) { m_data -= scale; return *this; }
    
    /*
    friend fixed operator+(value_type a, fixed f) { return fixed( a, f.m_data ); }
    friend fixed operator-(value_type a, fixed f) { return fixed( 0, a*scale-f.m_data ); }
    friend fixed operator*(value_type a, fixed f) { return fixed( 0, f.m_data*a ); }
    friend fixed operator/(value_type a, fixed f)
    {
        value_type quot = m_data / f.m_data;
        value_type rem = m_data % f.m_data;

        return fixed( quot, (rem*scale) / f.m_data );
    }
    */

    /// Приведение к типу

    operator value_type() const { return (m_data+scale/2)/scale; }
    operator double() const { return double(m_data)/double(scale); }
    operator float() const { return float(m_data)/float(scale); }
    
    /// Присваивание

    fixed_T& operator = (value_type a) { m_data = a*scale; return *this; }
    fixed_T& operator = (fixed_T& f) { m_data = f.m_data; return *this; }
    fixed_T& operator = (double a) { m_data = fixed_T(a).m_data; return *this; }
    fixed_T& operator = (float a) { m_data = fixed_T(a).m_data; return *this; }

    /// Сравнение

    bool operator == (fixed_T& f) { return m_data == f.m_data; }
    bool operator != (fixed_T& f) { return m_data != f.m_data; }
    bool operator >= (fixed_T& f) { return m_data >= f.m_data; }
    bool operator <= (fixed_T& f) { return m_data <= f.m_data; }
    bool operator > (fixed_T& f) { return m_data > f.m_data; }
    bool operator < (fixed_T& f) { return m_data < f.m_data; }

    bool operator == (value_type a) { return m_data == a*scale; }
    bool operator != (value_type a) { return m_data != a*scale; }
    bool operator >= (value_type a) { return m_data >= a*scale; }
    bool operator <= (value_type a) { return m_data <= a*scale; }
    bool operator > (value_type a) { return m_data > a*scale; }
    bool operator < (value_type a) { return m_data < a*scale; }

    bool operator == (double a) { return double(*this) == a; }
    bool operator != (double a) { return double(*this) != a; }
    bool operator >= (double a) { return double(*this) >= a; }
    bool operator <= (double a) { return double(*this) <= a; }
    bool operator > (double a) { return double(*this) > a; }
    bool operator < (double a) { return double(*this) < a; }

    bool operator == (float a) { return float(*this) == a; }
    bool operator != (float a) { return float(*this) != a; }
    bool operator >= (float a) { return float(*this) >= a; }
    bool operator <= (float a) { return float(*this) <= a; }
    bool operator > (float a) { return float(*this) > a; }
    bool operator < (float a) { return float(*this) < a; }
};

typedef fixed_T<int, 8> fixed;
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.