From db1c4890475609550a002f9f665a409b70d54594 Mon Sep 17 00:00:00 2001 From: danij Date: Fri, 18 Feb 2011 07:37:05 +0000 Subject: [PATCH] Implemented M_RatioReduce - using Euclid's Algorithm reduce the given numerator and denominator by their greatest common divisor. --- doomsday/engine/api/doomsday.def | 3 +- doomsday/engine/api/doomsday.h | 3 +- doomsday/engine/portable/include/m_misc.h | 10 +++++++ doomsday/engine/portable/src/m_misc.c | 34 +++++++++++++++++++++++ 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/doomsday/engine/api/doomsday.def b/doomsday/engine/api/doomsday.def index dcb894511d..5bcad7acb0 100644 --- a/doomsday/engine/api/doomsday.def +++ b/doomsday/engine/api/doomsday.def @@ -1,6 +1,6 @@ ; Doomsday Engine API (Routines exported from Doomsday.exe). ; -; Highest ordinal is currently: --> 498 <-- +; Highest ordinal is currently: --> 499 <-- ; Other free ordinals: 30 NAME "DOOMSDAY" @@ -538,6 +538,7 @@ EXPORTS M_RunTrigger @341 NONAME M_CeilPow2 @422 NONAME M_NumDigits @143 NONAME + M_RatioReduce @499 NONAME ; Math. ; Binary angles. diff --git a/doomsday/engine/api/doomsday.h b/doomsday/engine/api/doomsday.h index 648107cc15..22ba03b6d0 100644 --- a/doomsday/engine/api/doomsday.h +++ b/doomsday/engine/api/doomsday.h @@ -107,7 +107,7 @@ gameid_t DD_AddGame(const char* identityKey, const char* dataPath, const char* d * @param rflags @see resourceFlags * @param names One or more known potential names, seperated by semicolon e.g., "name1;name2". * Names may include valid absolute, or relative file paths. These paths include - * valid symbolbolic escape tokens, predefined symbols into the virtual file system. + * valid symbolbolic escape tokens, predefined symbols into the virtual file system. */ void DD_AddGameResource(gameid_t game, resourceclass_t rclass, int rflags, const char* names, void* params); @@ -531,6 +531,7 @@ void Con_SetString(const char* name, char* text); int M_ScreenShot(const char* filename, int bits); int M_CeilPow2(int num); int M_NumDigits(int value); + int M_RatioReduce(int* numerator, int* denominator); // MiscellaneousL: Time utilities. boolean M_RunTrigger(trigger_t* trigger, timespan_t advanceTime); diff --git a/doomsday/engine/portable/include/m_misc.h b/doomsday/engine/portable/include/m_misc.h index a317a638a4..795259bf68 100644 --- a/doomsday/engine/portable/include/m_misc.h +++ b/doomsday/engine/portable/include/m_misc.h @@ -135,6 +135,16 @@ int M_FloorPow2(int num); int M_RoundPow2(int num); int M_WeightPow2(int num, float weight); float M_CycleIntoRange(float value, float length); + +/** + * Using Euclid's Algorithm reduce the given numerator and denominator by + * their greatest common integer divisor. + * @param numerator Input and output numerator. + * @param denominator Input and output denominator. + * @return Greatest common divisor. + */ +int M_RatioReduce(int* numerator, int* denominator); + double M_SlopeToAngle(double dx, double dy); double M_Length(double x, double y); int M_NumDigits(int num); diff --git a/doomsday/engine/portable/src/m_misc.c b/doomsday/engine/portable/src/m_misc.c index c2ee714a5d..661a86c578 100644 --- a/doomsday/engine/portable/src/m_misc.c +++ b/doomsday/engine/portable/src/m_misc.c @@ -341,6 +341,40 @@ void RNG_Reset(void) rngIndex = 0, rngIndex2 = 0; } +int M_RatioReduce(int* numerator, int* denominator) +{ + assert(numerator && denominator); + { + int n, d, temp; + + if(*numerator == *denominator) + return 1; // 1:1 + + n = abs(*numerator); + d = abs(*denominator); + // Ensure numerator is larger. + if(n < d) + { + temp = n; + n = d; + d = temp; + } + + // Reduce to the common divisor. + while(d != 0) + { + temp = n; + n = d; + d = temp % d; + } + + // Apply divisor. + *numerator /= n; + *denominator /= n; + return n; + } +} + /** * Finds the power of 2 that is equal to or greater than the specified * number.