Here Boost implements it. Code commented out.
template <typename IntType> bool rational<IntType>::operator< (const rational<IntType>& r) const { // Avoid repeated construction int_type const zero( 0 ); // This should really be a class-wide invariant. The reason for these // checks is that for 2 complement systems, INT_MIN has no corresponding // positive, so negating it during normalization keeps it INT_MIN, which // is bad for later calculations that assume a positive denominator. BOOST_ASSERT( this->den > zero ); BOOST_ASSERT( r.den > zero ); // Determine relative order by expanding each value to its simple continued // fraction representation using the Euclidian GCD algorithm. struct { int_type n, d, q, r; } ts = { this->num, this->den, this->num / this->den, this->num % this->den }, rs = { r.num, r.den, r.num / r.den, r.num % r.den }; unsigned reverse = 0u; // Normalize negative moduli by repeatedly adding the (positive) denominator // and decrementing the quotient. Later cycles should have all positive // values, so this only has to be done for the first cycle. (The rules of // C++ require a nonnegative quotient & remainder for a nonnegative dividend // & positive divisor.) while ( ts.r < zero ) { ts.r += ts.d; --ts.q; } while ( rs.r < zero ) { rs.r += rs.d; --rs.q; } // Loop through and compare each variable continued-fraction components while ( true ) { // The quotients of the current cycle are the continued-fraction // components. Comparing two cf is comparing their sequences, // stopping at the first difference. if ( ts.q != rs.q ) { // Since reciprocation changes the relative order of two variables, // and cf use reciprocals, the less/greater-than test reverses // after each index. (Start w/ non-reversed @ whole-number place.) return reverse ? ts.q > rs.q : ts.q < rs.q; } // Prepare the next cycle reverse ^= 1u; if ( (ts.r == zero) || (rs.r == zero) ) { // At least one variable cf expansion has ended break; } ts.n = ts.d; ts.d = ts.r; ts.q = ts.n / ts.d; ts.r = ts.n % ts.d; rs.n = rs.d; rs.d = rs.r; rs.q = rs.n / rs.d; rs.r = rs.n % rs.d; } // Compare infinity-valued components for otherwise equal sequences if ( ts.r == rs.r ) { // Both remainders are zero, so the next (and subsequent) cf // components for both sequences are infinity. Therefore, the sequences // and their corresponding values are equal. return false; } else { // Exactly one of the remainders is zero, so all following cf // components of that variable are infinity, while the other variable // has a finite next cf component. So that other variable has the // lesser value (modulo the reversal flag!). return ( ts.r != zero ) != static_cast<bool>( reverse ); } }
source share