Ticket #9141: 01-rational.patch

File 01-rational.patch, 14.2 KB (added by DrMcCoy, 14 years ago)

Fixed Rational class

  • common/algorithm.h

    commit 9da1967937e6fd7424f857165b2a2965ec2059eb
    Author: Sven Hesse <drmccoy@users.sourceforge.net>
    Date:   Thu May 13 20:20:36 2010 +0200
    
        Adding a simple Rational class that holds fractions
    
    diff --git a/common/algorithm.h b/common/algorithm.h
    index 3a66efe..06f2a27 100644
    a b void sort(T first, T last) {  
    222222        sort(first, last, Common::Less<typename T::ValueType>());
    223223}
    224224
     225/**
     226 * Euclid's algorithm to compute the greatest common divisor.
     227 */
     228template<class T>
     229T gcd(T a, T b) {
     230        while (a > 0) {
     231                T tmp = a;
     232                a = b % a;
     233                b = tmp;
     234        }
     235        return b;
     236}
     237
    225238} // End of namespace Common
    226239#endif
    227240
  • common/module.mk

    diff --git a/common/module.mk b/common/module.mk
    index 2bbb1ed..83d30f0 100644
    a b MODULE_OBJS := \  
    1616        md5.o \
    1717        mutex.o \
    1818        random.o \
     19        rational.o \
    1920        str.o \
    2021        stream.o \
    2122        system.o \
  • new file common/rational.cpp

    diff --git a/common/rational.cpp b/common/rational.cpp
    new file mode 100644
    index 0000000..e27e880
    - +  
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11 *
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 */
     24
     25#include "common/rational.h"
     26#include "common/util.h"
     27#include "common/algorithm.h"
     28
     29namespace Common {
     30
     31Rational::Rational() {
     32        _num   = 1;
     33        _denom = 1;
     34}
     35
     36Rational::Rational(int num) {
     37        _num   = num;
     38        _denom = 1;
     39}
     40
     41Rational::Rational(int num, int denom) {
     42        assert(denom != 0);
     43
     44        _num   = num;
     45        _denom = denom;
     46
     47        normalize();
     48}
     49
     50void Rational::cancel() {
     51        // Cancel the fraction by dividing both the num and the denom
     52        // by their greatest common denom.
     53
     54        int gcd = Common::gcd(_num, _denom);
     55
     56        _num   /= gcd;
     57        _denom /= gcd;
     58}
     59
     60void Rational::normalize() {
     61        // Is the fraction negative?
     62        bool negative = !((!(_num < 0)) == (!(_denom < 0)));
     63
     64        // Make both integers positive
     65        _num   = ABS(_num);
     66        _denom = ABS(_denom);
     67
     68        // Cancel the fraction
     69        cancel();
     70
     71        // If the fraction is supposed to be negative, make the num negative
     72        if (negative)
     73                _num = -_num;
     74}
     75
     76Rational &Rational::operator=(const Rational &right) {
     77        _num   = right._num;
     78        _denom = right._denom;
     79
     80        return *this;
     81}
     82
     83Rational &Rational::operator=(int right) {
     84        _num   = right;
     85        _denom = 1;
     86
     87        return *this;
     88}
     89
     90Rational &Rational::operator+=(const Rational &right) {
     91        _num   = _num * right._denom + right._num * _denom;
     92        _denom = _denom * right._denom;
     93
     94        normalize();
     95
     96        return *this;
     97}
     98
     99Rational &Rational::operator-=(const Rational &right) {
     100        _num   = _num * right._denom - right._num * _denom;
     101        _denom = _denom * right._denom;
     102
     103        normalize();
     104
     105        return *this;
     106}
     107
     108Rational &Rational::operator*=(const Rational &right) {
     109        // Try to cross-cancel first, to avoid unnecessary overflow
     110        int gcd1 = Common::gcd(_num, right._denom);
     111        int gcd2 = Common::gcd(right._num, _denom);
     112
     113        _num   = (_num    / gcd1) * (right._num    / gcd2);
     114        _denom = (_denom  / gcd2) * (right._denom  / gcd1);
     115
     116        normalize();
     117
     118        return *this;
     119}
     120
     121Rational &Rational::operator/=(const Rational &right) {
     122        return *this *= Rational(right._denom, right._num);
     123}
     124
     125Rational &Rational::operator+=(int right) {
     126        return *this += Rational(right);
     127}
     128
     129Rational &Rational::operator-=(int right) {
     130        return *this -= Rational(right);
     131}
     132
     133Rational &Rational::operator*=(int right) {
     134        return *this *= Rational(right);
     135}
     136
     137Rational &Rational::operator/=(int right) {
     138        return *this /= Rational(right);
     139}
     140
     141const Rational Rational::operator-() const {
     142        return Rational(-_num, _denom);
     143}
     144
     145const Rational Rational::operator+(const Rational &right) const {
     146        Rational tmp = *this;
     147
     148        tmp += right;
     149
     150        return tmp;
     151}
     152
     153const Rational Rational::operator-(const Rational &right) const {
     154        Rational tmp = *this;
     155
     156        tmp -= right;
     157
     158        return tmp;
     159}
     160
     161const Rational Rational::operator*(const Rational &right) const {
     162        Rational tmp = *this;
     163
     164        tmp *= right;
     165
     166        return tmp;
     167}
     168
     169const Rational Rational::operator/(const Rational &right) const {
     170        Rational tmp = *this;
     171
     172        tmp /= right;
     173
     174        return tmp;
     175}
     176
     177const Rational Rational::operator+(int right) const {
     178        Rational tmp = *this;
     179
     180        tmp += right;
     181
     182        return tmp;
     183}
     184
     185const Rational Rational::operator-(int right) const {
     186        Rational tmp = *this;
     187
     188        tmp -= right;
     189
     190        return tmp;
     191}
     192
     193const Rational Rational::operator*(int right) const {
     194        Rational tmp = *this;
     195
     196        tmp *= right;
     197
     198        return tmp;
     199}
     200
     201const Rational Rational::operator/(int right) const {
     202        Rational tmp = *this;
     203
     204        tmp /= right;
     205
     206        return tmp;
     207}
     208
     209bool Rational::operator==(const Rational &right) const {
     210        return (_num == right._num) && (_denom == right._denom);
     211}
     212
     213bool Rational::operator!=(const Rational &right) const {
     214        return (_num != right._num) || (_denom != right._denom);
     215}
     216
     217bool Rational::operator>(const Rational &right) const {
     218        return (_num * right._denom) > (right._num * _denom);
     219}
     220
     221bool Rational::operator<(const Rational &right) const {
     222        return (_num * right._denom) < (right._num * _denom);
     223}
     224
     225bool Rational::operator>=(const Rational &right) const {
     226        return (_num * right._denom) >= (right._num * _denom);
     227}
     228
     229bool Rational::operator<=(const Rational &right) const {
     230        return (_num * right._denom) <= (right._num * _denom);
     231}
     232
     233bool Rational::operator==(int right) const {
     234        return (_denom == 1) && (_num == right);
     235}
     236
     237bool Rational::operator!=(int right) const {
     238        return (_denom == 1) && (_num != right);
     239}
     240
     241bool Rational::operator>(int right) const {
     242        return *this > Rational(right, 1);
     243}
     244
     245bool Rational::operator<(int right) const {
     246        return *this < Rational(right, 1);
     247}
     248
     249bool Rational::operator>=(int right) const {
     250        return *this >= Rational(right, 1);
     251}
     252
     253bool Rational::operator<=(int right) const {
     254        return *this <= Rational(right, 1);
     255}
     256
     257void Rational::invert() {
     258        assert(_num != 0);
     259
     260        SWAP(_num, _denom);
     261
     262        normalize();
     263}
     264
     265Rational Rational::getInverse() const {
     266        Rational inverse = *this;
     267
     268        inverse.invert();
     269
     270        return inverse;
     271}
     272
     273int Rational::toInt() const {
     274        assert(_denom != 0);
     275
     276        return _num / _denom;
     277}
     278
     279double Rational::toDouble() const {
     280        assert(_denom != 0);
     281
     282        return ((double) _num) / ((double) _denom);
     283}
     284
     285frac_t Rational::toFrac() const {
     286        return (_num * FRAC_ONE) / _denom;
     287}
     288
     289Rational::operator int() const {
     290        return toInt();
     291}
     292
     293Rational::operator double() const {
     294        return toDouble();
     295}
     296
     297const Rational operator+(int left, const Rational &right) {
     298        Rational tmp = right;
     299
     300        tmp += left;
     301
     302        return tmp;
     303}
     304
     305const Rational operator-(int left, const Rational &right) {
     306        Rational tmp = right;
     307
     308        tmp -= left;
     309
     310        return tmp;
     311}
     312
     313const Rational operator*(int left, const Rational &right) {
     314        Rational tmp = right;
     315
     316        tmp *= left;
     317
     318        return tmp;
     319}
     320
     321const Rational operator/(int left, const Rational &right) {
     322        Rational tmp = right;
     323
     324        tmp /= left;
     325
     326        return tmp;
     327}
     328
     329bool operator==(int left, const Rational &right) {
     330        return right == left;
     331}
     332
     333bool operator!=(int left, const Rational &right) {
     334        return right != left;
     335}
     336
     337bool operator>(int left, const Rational &right) {
     338        return right < left;
     339}
     340
     341bool operator<(int left, const Rational &right) {
     342        return right > left;
     343}
     344
     345bool operator>=(int left, const Rational &right) {
     346        return right <= left;
     347}
     348
     349bool operator<=(int left, const Rational &right) {
     350        return right >= left;
     351}
     352
     353} // End of namespace Common
  • new file common/rational.h

    diff --git a/common/rational.h b/common/rational.h
    new file mode 100644
    index 0000000..1ad33de
    - +  
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11 *
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 */
     24
     25#ifndef COMMON_RATIONAL_H
     26#define COMMON_RATIONAL_H
     27
     28#include "common/scummsys.h"
     29#include "common/frac.h"
     30
     31namespace Common {
     32
     33/** A simple rational class that holds fractions. */
     34class Rational {
     35public:
     36        Rational();
     37        Rational(int num);
     38        Rational(int num, int denom);
     39
     40        Rational &operator=(const Rational &right);
     41        Rational &operator=(int right);
     42
     43        Rational &operator+=(const Rational &right);
     44        Rational &operator-=(const Rational &right);
     45        Rational &operator*=(const Rational &right);
     46        Rational &operator/=(const Rational &right);
     47
     48        Rational &operator+=(int right);
     49        Rational &operator-=(int right);
     50        Rational &operator*=(int right);
     51        Rational &operator/=(int right);
     52
     53        const Rational operator-() const;
     54
     55        const Rational operator+(const Rational &right) const;
     56        const Rational operator-(const Rational &right) const;
     57        const Rational operator*(const Rational &right) const;
     58        const Rational operator/(const Rational &right) const;
     59
     60        const Rational operator+(int right) const;
     61        const Rational operator-(int right) const;
     62        const Rational operator*(int right) const;
     63        const Rational operator/(int right) const;
     64
     65        bool operator==(const Rational &right) const;
     66        bool operator!=(const Rational &right) const;
     67        bool operator>(const Rational &right) const;
     68        bool operator<(const Rational &right) const;
     69        bool operator>=(const Rational &right) const;
     70        bool operator<=(const Rational &right) const;
     71
     72        bool operator==(int right) const;
     73        bool operator!=(int right) const;
     74        bool operator>(int right) const;
     75        bool operator<(int right) const;
     76        bool operator>=(int right) const;
     77        bool operator<=(int right) const;
     78
     79        operator int() const;
     80        operator double() const;
     81
     82        void invert();
     83        Rational getInverse() const;
     84
     85        int toInt() const;
     86        double toDouble() const;
     87        frac_t toFrac() const;
     88
     89private:
     90        int _num;
     91        int _denom;
     92
     93        void cancel();
     94        void normalize();
     95};
     96
     97const Rational operator+(int left, const Rational &right);
     98const Rational operator-(int left, const Rational &right);
     99const Rational operator*(int left, const Rational &right);
     100const Rational operator/(int left, const Rational &right);
     101
     102bool operator==(int left, const Rational &right);
     103bool operator!=(int left, const Rational &right);
     104bool operator>(int left, const Rational &right);
     105bool operator<(int left, const Rational &right);
     106bool operator>=(int left, const Rational &right);
     107bool operator<=(int left, const Rational &right);
     108
     109} // End of namespace Common
     110
     111#endif
  • sound/timestamp.cpp

    diff --git a/sound/timestamp.cpp b/sound/timestamp.cpp
    index f705ff4..1eb5483 100644
    a b  
    2424 */
    2525
    2626#include "sound/timestamp.h"
     27#include "common/algorithm.h"
    2728
    2829namespace Audio {
    2930
    30 static uint gcd(uint a, uint b) {
    31         while (a > 0) {
    32                 int tmp = a;
    33                 a = b % a;
    34                 b = tmp;
    35         }
    36         return b;
    37 }
    38 
    3931Timestamp::Timestamp(uint ms, uint fr) {
    4032        assert(fr > 0);
    4133
    4234        _secs = ms / 1000;
    43         _framerateFactor = 1000 / gcd(1000, fr);
     35        _framerateFactor = 1000 / Common::gcd<uint>(1000, fr);
    4436        _framerate = fr * _framerateFactor;
    4537
    4638        // Note that _framerate is always divisible by 1000.
    Timestamp::Timestamp(uint s, uint frames, uint fr) {  
    5143        assert(fr > 0);
    5244
    5345        _secs = s;
    54         _framerateFactor = 1000 / gcd(1000, fr);
     46        _framerateFactor = 1000 / Common::gcd<uint>(1000, fr);
    5547        _framerate = fr * _framerateFactor;
    5648        _numFrames = frames * _framerateFactor;
    5749
    Timestamp Timestamp::convertToFramerate(uint newFramerate) const {  
    6254        Timestamp ts(*this);
    6355
    6456        if (ts.framerate() != newFramerate) {
    65                 ts._framerateFactor = 1000 / gcd(1000, newFramerate);
     57                ts._framerateFactor = 1000 / Common::gcd<uint>(1000, newFramerate);
    6658                ts._framerate = newFramerate * ts._framerateFactor;
    6759
    68                 const uint g = gcd(_framerate, ts._framerate);
     60                const uint g = Common::gcd(_framerate, ts._framerate);
    6961                const uint p = _framerate / g;
    7062                const uint q = ts._framerate / g;
    7163
    bool Timestamp::operator>=(const Timestamp &ts) const {  
    122114int Timestamp::cmp(const Timestamp &ts) const {
    123115        int delta = _secs - ts._secs;
    124116        if (!delta) {
    125                 const uint g = gcd(_framerate, ts._framerate);
     117                const uint g = Common::gcd(_framerate, ts._framerate);
    126118                const uint p = _framerate / g;
    127119                const uint q = ts._framerate / g;
    128120
    void Timestamp::addIntern(const Timestamp &ts) {  
    164156                // We need to multiply by the quotient of the two framerates.
    165157                // We cancel the GCD in this fraction to reduce the risk of
    166158                // overflows.
    167                 const uint g = gcd(_framerate, ts._framerate);
     159                const uint g = Common::gcd(_framerate, ts._framerate);
    168160                const uint p = _framerate / g;
    169161                const uint q = ts._framerate / g;
    170162
    int Timestamp::frameDiff(const Timestamp &ts) const {  
    227219                // We need to multiply by the quotient of the two framerates.
    228220                // We cancel the GCD in this fraction to reduce the risk of
    229221                // overflows.
    230                 const uint g = gcd(_framerate, ts._framerate);
     222                const uint g = Common::gcd(_framerate, ts._framerate);
    231223                const uint p = _framerate / g;
    232224                const uint q = ts._framerate / g;
    233225