/**********************************************************************
** Copyright (C) 2000 Trolltech AS.  All rights reserved.
**
** This file is part of Qtopia Environment.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#ifndef MPEG3REAL_H
#define MPEG3REAL_H

#ifdef USE_FIXED_POINT

#include <limits.h>
#include <stdio.h>

#ifndef LONGLONG
#define LONGLONG long long
#endif

//#define SC (1<<16)
#define SC (1<<15)

class fixed {
    long v;
public:
    fixed() { } // Uninitialized, just like a float
    fixed(double d) { v=long(d*SC); }
    fixed(float f) { v=long(f*SC); }
    fixed(int i) { v=long(i*SC); }
    long fixedPoint() const { return v; }
    operator float() const { return ((float)v)/SC; }
    operator int() const { return (int)(v/SC); }
    fixed operator+() const;
    fixed operator-() const;
    fixed& operator= (const fixed&);
    fixed& operator+= (const fixed&);
    fixed& operator-= (const fixed&);
    fixed& operator*= (const fixed&);
    fixed& operator/= (const fixed&);
    friend fixed operator+ (const fixed&, const fixed&);
    friend fixed operator- (const fixed&, const fixed&);
    friend fixed operator* (const fixed&, const fixed&);
    friend fixed operator/ (const fixed&, const fixed&);
    friend fixed operator+ (const fixed&, const float&);
    friend fixed operator- (const fixed&, const float&);
    friend fixed operator* (const fixed&, const float&);
    friend fixed operator/ (const fixed&, const float&);
    friend fixed operator+ (const float&, const fixed&);
    friend fixed operator- (const float&, const fixed&);
    friend fixed operator* (const float&, const fixed&);
    friend fixed operator/ (const float&, const fixed&);
    friend fixed operator+ (const fixed&, const int&);
    friend fixed operator- (const fixed&, const int&);
    friend fixed operator* (const fixed&, const int&);
    friend fixed operator/ (const fixed&, const int&);
    friend fixed operator+ (const int&, const fixed&);
    friend fixed operator- (const int&, const fixed&);
    friend fixed operator* (const int&, const fixed&);
    friend fixed operator/ (const int&, const fixed&);
    friend bool operator< (const fixed&, const fixed&);
    friend bool operator<= (const fixed&, const fixed&);
    friend bool operator> (const fixed&, const fixed&);
    friend bool operator>= (const fixed&, const fixed&);
    friend bool operator== (const fixed&, const fixed&);
    friend bool operator!= (const fixed&, const fixed&);
};

inline fixed fixed::operator+() const
{
    return *this;
}

inline fixed fixed::operator-() const
{
    fixed r;
    r.v=-v;
    return r;
}

inline fixed& fixed::operator= (const fixed& o)
{
    v=o.v;
    return *this;
}

inline fixed& fixed::operator+= (const fixed& o)
{
    v += o.v;
    return *this;
}

inline fixed& fixed::operator-= (const fixed& o)
{
    v -= o.v;
    return *this;
}

inline fixed& fixed::operator*= (const fixed& o)
{
    *this = *this * o;
    return *this;
}

inline fixed& fixed::operator/= (const fixed& o)
{
    *this = *this / o; 
    return *this;
}


inline fixed operator+ (const fixed&a, const fixed&b)
{
    fixed r;
    r.v=a.v+b.v;
    return r;
}

inline fixed operator- (const fixed&a, const fixed&b)
{
    fixed r;
    r.v=a.v-b.v;
    return r;
}

inline fixed operator* (const fixed&a, const fixed&b)
{
    fixed r;
    r.v = (LONGLONG)a.v * b.v / SC;
    return r;
}

inline fixed operator/ (const fixed&a, const fixed&b)
{
    fixed r;
    r.v = (LONGLONG)a.v * SC / b.v;
    return r;
}

inline fixed operator+ (const fixed&a, const float&b)
{
    return a+fixed(b);
}

inline fixed operator- (const fixed&a, const float&b)
{
    return a-fixed(b);
}

inline fixed operator* (const fixed&a, const float&b)
{
    return a*fixed(b);
}

inline fixed operator/ (const fixed&a, const float&b)
{
    return a/fixed(b);
}


inline fixed operator+ (const float&a, const fixed&b)
{
    return fixed(a)+b;
}

inline fixed operator- (const float&a, const fixed&b)
{
    return fixed(a)-b;
}

inline fixed operator* (const float&a, const fixed&b)
{
    return fixed(a)*b;
}

inline fixed operator/ (const float&a, const fixed&b)
{
    return fixed(a)/b;
}


inline fixed operator+ (const fixed&a, const int&b)
{
    return a+fixed(b);
}

inline fixed operator- (const fixed&a, const int&b)
{
    return a-fixed(b);
}

inline fixed operator* (const fixed&a, const int&b)
{
    return a*fixed(b);
}

inline fixed operator/ (const fixed&a, const int&b)
{
    return a/fixed(b);
}


inline fixed operator+ (const int&a, const fixed&b)
{
    return fixed(a)+b;
}

inline fixed operator- (const int&a, const fixed&b)
{
    return fixed(a)-b;
}

inline fixed operator* (const int&a, const fixed&b)
{
    return fixed(a)*b;
}

inline fixed operator/ (const int&a, const fixed&b)
{
    return fixed(a)/b;
}

inline bool operator< (const fixed&a, const fixed&b)
{
    return a.v < b.v;
}

inline bool operator<= (const fixed&a, const fixed&b)
{
    return a.v <= b.v;
}

inline bool operator> (const fixed&a, const fixed&b)
{
    return a.v > b.v;
}

inline bool operator>= (const fixed&a, const fixed&b)
{
    return a.v >= b.v;
}

inline bool operator== (const fixed&a, const fixed&b)
{
    return a.v == b.v;
}

inline bool operator!= (const fixed&a, const fixed&b)
{
    return a.v != b.v;
}

#else
typedef float fixed;
#endif

#endif
