diff --git a/include/wx/math.h b/include/wx/math.h index 407c8e6936..a1478355fc 100644 --- a/include/wx/math.h +++ b/include/wx/math.h @@ -165,5 +165,7 @@ inline double wxRadToDeg(double rad) { return (rad * 180.0) / M_PI; } #endif #endif /* wxUSE_APPLE_IEEE */ +/* Compute the greatest common divisor of two positive integers */ +WXDLLIMPEXP_BASE unsigned int wxGCD(unsigned int u, unsigned int v); #endif /* _WX_MATH_H_ */ diff --git a/interface/wx/math.h b/interface/wx/math.h index 42114483d2..ca11a9fff2 100644 --- a/interface/wx/math.h +++ b/interface/wx/math.h @@ -16,6 +16,15 @@ */ int wxFinite(double x); +/** + Returns the greatest common divisor of the two given numbers. + + @since 3.1.0 + + @header{wx/math.h} +*/ +unsigned int wxGCD(unsigned int u, unsigned int v); + /** Returns a non-zero value if x is NaN (not a number), returns 0 otherwise. diff --git a/src/common/utilscmn.cpp b/src/common/utilscmn.cpp index b93666e318..4682611a60 100644 --- a/src/common/utilscmn.cpp +++ b/src/common/utilscmn.cpp @@ -52,6 +52,7 @@ #include "wx/mimetype.h" #include "wx/config.h" #include "wx/versioninfo.h" +#include "wx/math.h" #if defined(__WXWINCE__) && wxUSE_DATETIME #include "wx/datetime.h" @@ -967,10 +968,58 @@ void wxQsort(void* pbase, size_t total_elems, } } +// ---------------------------------------------------------------------------- +// wxGCD +// Compute the greatest common divisor of two positive integers +// using binary GCD algorithm. +// See: +// http://en.wikipedia.org/wiki/Binary_GCD_algorithm#Iterative_version_in_C +// ---------------------------------------------------------------------------- + +unsigned int wxGCD(unsigned int u, unsigned int v) +{ + // GCD(0,v) == v; GCD(u,0) == u, GCD(0,0) == 0 + if (u == 0) + return v; + if (v == 0) + return u; + + int shift; + + // Let shift := lg K, where K is the greatest power of 2 + // dividing both u and v. + for (shift = 0; ((u | v) & 1) == 0; ++shift) + { + u >>= 1; + v >>= 1; + } + + while ((u & 1) == 0) + u >>= 1; + + // From here on, u is always odd. + do + { + // remove all factors of 2 in v -- they are not common + // note: v is not zero, so while will terminate + while ((v & 1) == 0) + v >>= 1; + + // Now u and v are both odd. Swap if necessary so u <= v, + // then set v = v - u (which is even) + if (u > v) + { + wxSwap(u, v); + } + v -= u; // Here v >= u + } while (v != 0); + + // restore common factors of 2 + return u << shift; +} + #endif // wxUSE_BASE - - // ============================================================================ // GUI-only functions from now on // ============================================================================