Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

rational.cpp

/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-1-2-0/common/rational.cpp $
 * $Id: rational.cpp 52675 2010-09-11 10:03:31Z drmccoy $
 */

#include "common/debug.h"
#include "common/rational.h"
#include "common/util.h"
#include "common/algorithm.h"

namespace Common {

Rational::Rational() {
      _num   = 1;
      _denom = 1;
}

Rational::Rational(int num) {
      _num   = num;
      _denom = 1;
}

Rational::Rational(int num, int denom) {
      assert(denom != 0);

      if (denom > 0) {
            _num   = num;
            _denom = denom;
      } else {
            _num   = -num;
            _denom = -denom;
      }

      cancel();
}

void Rational::cancel() {
      // Cancel the fraction by dividing both the num and the denom
      // by their greatest common divisor.

      int gcd = Common::gcd(_num, _denom);

      _num   /= gcd;
      _denom /= gcd;
}

Rational &Rational::operator=(const Rational &right) {
      _num   = right._num;
      _denom = right._denom;

      return *this;
}

Rational &Rational::operator=(int right) {
      _num   = right;
      _denom = 1;

      return *this;
}

Rational &Rational::operator+=(const Rational &right) {
      _num   = _num * right._denom + right._num * _denom;
      _denom = _denom * right._denom;

      cancel();

      return *this;
}

Rational &Rational::operator-=(const Rational &right) {
      _num   = _num * right._denom - right._num * _denom;
      _denom = _denom * right._denom;

      cancel();

      return *this;
}

Rational &Rational::operator*=(const Rational &right) {
      // Cross-cancel to avoid unnecessary overflow;
      // the result then is automatically normalized
      int gcd1 = Common::gcd(_num, right._denom);
      int gcd2 = Common::gcd(right._num, _denom);

      _num   = (_num    / gcd1) * (right._num    / gcd2);
      _denom = (_denom  / gcd2) * (right._denom  / gcd1);

      return *this;
}

Rational &Rational::operator/=(const Rational &right) {
      return *this *= right.getInverse();
}

Rational &Rational::operator+=(int right) {
      return *this += Rational(right);
}

Rational &Rational::operator-=(int right) {
      return *this -= Rational(right);
}

Rational &Rational::operator*=(int right) {
      return *this *= Rational(right);
}

Rational &Rational::operator/=(int right) {
      return *this /= Rational(right);
}

const Rational Rational::operator-() const {
      return Rational(-_num, _denom);
}

const Rational Rational::operator+(const Rational &right) const {
      Rational tmp = *this;
      tmp += right;
      return tmp;
}

const Rational Rational::operator-(const Rational &right) const {
      Rational tmp = *this;
      tmp -= right;
      return tmp;
}

const Rational Rational::operator*(const Rational &right) const {
      Rational tmp = *this;
      tmp *= right;
      return tmp;
}

const Rational Rational::operator/(const Rational &right) const {
      Rational tmp = *this;
      tmp /= right;
      return tmp;
}

const Rational Rational::operator+(int right) const {
      Rational tmp = *this;
      tmp += right;
      return tmp;
}

const Rational Rational::operator-(int right) const {
      Rational tmp = *this;
      tmp -= right;
      return tmp;
}

const Rational Rational::operator*(int right) const {
      Rational tmp = *this;
      tmp *= right;
      return tmp;
}

const Rational Rational::operator/(int right) const {
      Rational tmp = *this;
      tmp /= right;
      return tmp;
}

bool Rational::operator==(const Rational &right) const {
      return (_num == right._num) && (_denom == right._denom);
}

bool Rational::operator!=(const Rational &right) const {
      return (_num != right._num) || (_denom != right._denom);
}

bool Rational::operator>(const Rational &right) const {
      return (_num * right._denom) > (right._num * _denom);
}

bool Rational::operator<(const Rational &right) const {
      return (_num * right._denom) < (right._num * _denom);
}

bool Rational::operator>=(const Rational &right) const {
      return (_num * right._denom) >= (right._num * _denom);
}

bool Rational::operator<=(const Rational &right) const {
      return (_num * right._denom) <= (right._num * _denom);
}

bool Rational::operator==(int right) const {
      return (_denom == 1) && (_num == right);
}

bool Rational::operator!=(int right) const {
      return (_denom != 1) || (_num != right);
}

bool Rational::operator>(int right) const {
      return *this > Rational(right, 1);
}

bool Rational::operator<(int right) const {
      return *this < Rational(right, 1);
}

bool Rational::operator>=(int right) const {
      return *this >= Rational(right, 1);
}

bool Rational::operator<=(int right) const {
      return *this <= Rational(right, 1);
}

void Rational::invert() {
      assert(_num != 0);

      SWAP(_num, _denom);

      if (_denom < 0) {
            _denom = -_denom;
            _num = -_num;
      }
}

Rational Rational::getInverse() const {
      Rational inverse = *this;

      inverse.invert();

      return inverse;
}

int Rational::toInt() const {
      return _num / _denom;
}

double Rational::toDouble() const {
      return ((double)_num) / ((double)_denom);
}

frac_t Rational::toFrac() const {
      return (_num * FRAC_ONE) / _denom;
}

const Rational operator+(int left, const Rational &right) {
      Rational tmp(left);
      tmp += right;
      return tmp;
}

const Rational operator-(int left, const Rational &right) {
      Rational tmp(left);
      tmp -= right;
      return tmp;
}

const Rational operator*(int left, const Rational &right) {
      Rational tmp(left);
      tmp *= right;
      return tmp;
}

const Rational operator/(int left, const Rational &right) {
      Rational tmp(left);
      tmp /= right;
      return tmp;
}

void Rational::debugPrint(int debuglevel, const char *caption) const {
      debug(debuglevel, "%s %d/%d", caption, _num, _denom);
}

bool operator==(int left, const Rational &right) {
      return right == left;
}

bool operator!=(int left, const Rational &right) {
      return right != left;
}

bool operator>(int left, const Rational &right) {
      return right < left;
}

bool operator<(int left, const Rational &right) {
      return right > left;
}

bool operator>=(int left, const Rational &right) {
      return right <= left;
}

bool operator<=(int left, const Rational &right) {
      return right >= left;
}

} // End of namespace Common

Generated by  Doxygen 1.6.0   Back to index