#ifndef Common_Fixed_H
#define Common_Fixed_H

struct Fixed {
  typedef long bits_t;

  Fixed();
  Fixed( int new_val);
  Fixed( bits_t new_val);
  Fixed( double new_val);

  const Fixed & operator=( const Fixed &rhs);
  const Fixed & operator=( double rhs);
  const Fixed & operator=( int rhs);

  operator double() const;
  operator int() const;

  bits_t  m_bits;
};


inline
Fixed::Fixed()
: m_bits( 0)
{
}


inline
Fixed::Fixed( int new_val)
: m_bits( new_val << 16)
{
}


inline
Fixed::Fixed( bits_t new_val)
: m_bits( new_val)
{
}


inline
Fixed::Fixed( double new_val)
: m_bits( (bits_t) (new_val * 65536))
{
}


inline const Fixed &
Fixed::operator=( const Fixed &rhs)
{
  m_bits = rhs.m_bits;
  return *this;
}


inline const Fixed &
Fixed::operator=( double rhs)
{
  m_bits = (Fixed::bits_t)(rhs * 65536);
  return *this;
}


inline const Fixed &
Fixed::operator=( int rhs)
{
  m_bits = (Fixed::bits_t)(rhs << 16);
  return *this;
}


inline
Fixed::operator double() const
{
  return m_bits / 65536.0;
}


inline
Fixed::operator int() const
{
  return m_bits >> 16;
}


inline Fixed
operator+( const Fixed &lhs, const Fixed &rhs)
{
  return Fixed( lhs.m_bits + rhs.m_bits);
}


inline Fixed
operator-( const Fixed &lhs, const Fixed &rhs)
{
  return Fixed( lhs.m_bits - rhs.m_bits);
}


inline Fixed
operator*( const Fixed &lhs, double rhs)
{
  return Fixed( (Fixed::bits_t)(lhs.m_bits * rhs));
}


inline Fixed
operator*( double lhs, const Fixed &rhs)
{
  return rhs * lhs;
}


inline Fixed
operator*( const Fixed &lhs, const Fixed &rhs)
{
  return lhs * (rhs.m_bits / 65536.0);
}


inline Fixed
operator/( const Fixed &lhs, double rhs)
{
  return Fixed( (Fixed::bits_t)(lhs.m_bits / rhs));
}


inline Fixed
operator/( double lhs, const Fixed &rhs)
{
  return Fixed( (Fixed::bits_t)(lhs / (rhs.m_bits / 65536.0)));
}


inline Fixed
operator/( const Fixed &lhs, const Fixed &rhs)
{
  return lhs / (rhs.m_bits / 65536.0);
}


inline const Fixed &
operator+=( Fixed &lhs, const Fixed &rhs)
{
  lhs.m_bits += rhs.m_bits;
  return lhs;
}


inline const Fixed &
operator+=( Fixed &lhs, int rhs)
{
  lhs.m_bits += rhs << 16;
  return lhs;
}


inline const Fixed &
operator+=( Fixed &lhs, double rhs)
{
  lhs.m_bits += (Fixed::bits_t)( rhs * 65536);
  return lhs;
}


inline const Fixed &
operator-=( Fixed &lhs, const Fixed &rhs)
{
  lhs.m_bits -= rhs.m_bits;
  return lhs;
}


inline const Fixed &
operator-=( Fixed &lhs, int rhs)
{
  lhs.m_bits -= rhs << 16;
  return lhs;
}


inline const Fixed &
operator-=( Fixed &lhs, double rhs)
{
  lhs.m_bits -= (Fixed::bits_t)( rhs * 65536);
  return lhs;
}


inline bool
operator<( const Fixed &lhs, const Fixed &rhs)
{
  return (lhs.m_bits < rhs.m_bits);
}

inline bool
operator<=( const Fixed &lhs, const Fixed &rhs)
{
  return (lhs.m_bits <= rhs.m_bits);
}


inline bool
operator>=( const Fixed &lhs, const Fixed &rhs)
{
  return (lhs.m_bits >= rhs.m_bits);
}


inline bool
operator>( const Fixed &lhs, const Fixed &rhs)
{
  return (lhs.m_bits > rhs.m_bits);
}


inline bool
operator==( const Fixed &lhs, const Fixed &rhs)
{
  return (lhs.m_bits == rhs.m_bits);
}


inline bool
operator!=( const Fixed &lhs, const Fixed &rhs)
{
  return (lhs.m_bits != rhs.m_bits);
}


#endif//Common_Fixed_H
