DriveHQ Start Menu
Cloud Drive Mapping
Folder Sync
Cloud Backup
True Drop Box
FTP/SFTP Hosting
Group Account
DriveHQ Start Menu
Online File Server
My Storage
|
Manage Shares
|
Publishes
|
Drop Boxes
|
Group Account
WebDAV Drive Mapping
Cloud Drive Home
|
WebDAV Guide
|
Drive Mapping Tool
|
Drive Mapping URL
Complete Data Backup
Backup Guide
|
Online Backup Tool
|
Cloud-to-Cloud Backup
FTP, Email & Web Service
FTP Home
|
FTP Hosting FAQ
|
Email Hosting
|
EmailManager
|
Web Hosting
Help & Resources
About
|
Enterprise Service
|
Partnership
|
Comparisons
|
Support
Quick Links
Security and Privacy
Download Software
Service Manual
Use Cases
Group Account
Online Help
Blog
Contact
Cloud Surveillance
Sign Up
Login
Features
Business Features
Online File Server
FTP Hosting
Cloud Drive Mapping
Cloud File Backup
Email Backup & Hosting
Cloud File Sharing
Folder Synchronization
Group Management
True Drop Box
Full-text Search
AD Integration/SSO
Mobile Access
IP Camera & DVR Solution
More...
Personal Features
Personal Cloud Drive
Backup All Devices
Mobile APPs
Personal Web Hosting
Sub-Account (for Kids)
Home/PC/Kids Monitoring
More...
Software
DriveHQ Drive Mapping Tool
DriveHQ FileManager
DriveHQ Online Backup
DriveHQ Mobile Apps
Pricing
Business Plans & Pricing
Personal Plans & Pricing
Price Comparison with Others
Feature Comparison with Others
Install Mobile App
Sign up
Creating account...
Invalid character in username! Only 0-9, a-z, A-Z, _, -, . allowed.
Username is required!
Invalid email address!
E-mail is required!
Password is required!
Password is invalid!
Password and confirmation do not match.
Confirm password is required!
I accept
Membership Agreement
Please read the Membership Agreement and check "I accept"!
Free Quick Sign-up
Sign-up Page
Log in
Signing in...
Username or e-mail address is required!
Password is required!
Keep me logged in
Quick Login
Forgot Password
Up
Upload
Download
Share
Publish
New Folder
New File
Copy
Cut
Delete
Paste
Rate
Upgrade
Rotate
Effect
Edit
Slide
History
// Boost rational.hpp header file ------------------------------------------// // (C) Copyright Paul Moore 1999. Permission to copy, use, modify, sell and // distribute this software is granted provided this copyright notice appears // in all copies. This software is provided "as is" without express or // implied warranty, and with no claim as to its suitability for any purpose. // See http://www.boost.org/libs/rational for documentation. // Credits: // Thanks to the boost mailing list in general for useful comments. // Particular contributions included: // Andrew D Jewell, for reminding me to take care to avoid overflow // Ed Brey, for many comments, including picking up on some dreadful typos // Stephen Silver contributed the test suite and comments on user-defined // IntType // Nickolay Mladenov, for the implementation of operator+= // Revision History // 05 Nov 06 Change rational_cast to not depend on division between different // types (Daryle Walker) // 04 Nov 06 Off-load GCD and LCM to Boost.Math; add some invariant checks; // add std::numeric_limits<> requirement to help GCD (Daryle Walker) // 31 Oct 06 Recoded both operator< to use round-to-negative-infinity // divisions; the rational-value version now uses continued fraction // expansion to avoid overflows, for bug #798357 (Daryle Walker) // 20 Oct 06 Fix operator bool_type for CW 8.3 (Joaqu�n M L�pez Mu�oz) // 18 Oct 06 Use EXPLICIT_TEMPLATE_TYPE helper macros from Boost.Config // (Joaqu�n M L�pez Mu�oz) // 27 Dec 05 Add Boolean conversion operator (Daryle Walker) // 28 Sep 02 Use _left versions of operators from operators.hpp // 05 Jul 01 Recode gcd(), avoiding std::swap (Helmut Zeisel) // 03 Mar 01 Workarounds for Intel C++ 5.0 (David Abrahams) // 05 Feb 01 Update operator>> to tighten up input syntax // 05 Feb 01 Final tidy up of gcd code prior to the new release // 27 Jan 01 Recode abs() without relying on abs(IntType) // 21 Jan 01 Include Nickolay Mladenov's operator+= algorithm, // tidy up a number of areas, use newer features of operators.hpp // (reduces space overhead to zero), add operator!, // introduce explicit mixed-mode arithmetic operations // 12 Jan 01 Include fixes to handle a user-defined IntType better // 19 Nov 00 Throw on divide by zero in operator /= (John (EBo) David) // 23 Jun 00 Incorporate changes from Mark Rodgers for Borland C++ // 22 Jun 00 Change _MSC_VER to BOOST_MSVC so other compilers are not // affected (Beman Dawes) // 6 Mar 00 Fix operator-= normalization, #include
(Jens Maurer) // 14 Dec 99 Modifications based on comments from the boost list // 09 Dec 99 Initial Version (Paul Moore) #ifndef BOOST_RATIONAL_HPP #define BOOST_RATIONAL_HPP #include
// for std::istream and std::ostream #include
// for std::noskipws #include
// for std::domain_error #include
// for std::string implicit constructor #include
// for boost::addable etc #include
// for std::abs #include
// for boost::call_traits #include
// for BOOST_NO_STDC_NAMESPACE, BOOST_MSVC #include
// for BOOST_WORKAROUND #include
// for BOOST_ASSERT #include
// for boost::math::gcd, lcm #include
// for std::numeric_limits #include
// for BOOST_STATIC_ASSERT // Control whether depreciated GCD and LCM functions are included (default: yes) #ifndef BOOST_CONTROL_RATIONAL_HAS_GCD #define BOOST_CONTROL_RATIONAL_HAS_GCD 1 #endif namespace boost { #if BOOST_CONTROL_RATIONAL_HAS_GCD template
IntType gcd(IntType n, IntType m) { // Defer to the version in Boost.Math return math::gcd( n, m ); } template
IntType lcm(IntType n, IntType m) { // Defer to the version in Boost.Math return math::lcm( n, m ); } #endif // BOOST_CONTROL_RATIONAL_HAS_GCD class bad_rational : public std::domain_error { public: explicit bad_rational() : std::domain_error("bad rational: zero denominator") {} }; template
class rational; template
rational
abs(const rational
& r); template
class rational : less_than_comparable < rational
, equality_comparable < rational
, less_than_comparable2 < rational
, IntType, equality_comparable2 < rational
, IntType, addable < rational
, subtractable < rational
, multipliable < rational
, dividable < rational
, addable2 < rational
, IntType, subtractable2 < rational
, IntType, subtractable2_left < rational
, IntType, multipliable2 < rational
, IntType, dividable2 < rational
, IntType, dividable2_left < rational
, IntType, incrementable < rational
, decrementable < rational
> > > > > > > > > > > > > > > > { // Class-wide pre-conditions BOOST_STATIC_ASSERT( ::std::numeric_limits
::is_specialized ); // Helper types typedef typename boost::call_traits
::param_type param_type; struct helper { IntType parts[2]; }; typedef IntType (helper::* bool_type)[2]; public: typedef IntType int_type; rational() : num(0), den(1) {} rational(param_type n) : num(n), den(1) {} rational(param_type n, param_type d) : num(n), den(d) { normalize(); } // Default copy constructor and assignment are fine // Add assignment from IntType rational& operator=(param_type n) { return assign(n, 1); } // Assign in place rational& assign(param_type n, param_type d); // Access to representation IntType numerator() const { return num; } IntType denominator() const { return den; } // Arithmetic assignment operators rational& operator+= (const rational& r); rational& operator-= (const rational& r); rational& operator*= (const rational& r); rational& operator/= (const rational& r); rational& operator+= (param_type i); rational& operator-= (param_type i); rational& operator*= (param_type i); rational& operator/= (param_type i); // Increment and decrement const rational& operator++(); const rational& operator--(); // Operator not bool operator!() const { return !num; } // Boolean conversion #if BOOST_WORKAROUND(__MWERKS__,<=0x3003) // The "ISO C++ Template Parser" option in CW 8.3 chokes on the // following, hence we selectively disable that option for the // offending memfun. #pragma parse_mfunc_templ off #endif operator bool_type() const { return operator !() ? 0 : &helper::parts; } #if BOOST_WORKAROUND(__MWERKS__,<=0x3003) #pragma parse_mfunc_templ reset #endif // Comparison operators bool operator< (const rational& r) const; bool operator== (const rational& r) const; bool operator< (param_type i) const; bool operator> (param_type i) const; bool operator== (param_type i) const; private: // Implementation - numerator and denominator (normalized). // Other possibilities - separate whole-part, or sign, fields? IntType num; IntType den; // Representation note: Fractions are kept in normalized form at all // times. normalized form is defined as gcd(num,den) == 1 and den > 0. // In particular, note that the implementation of abs() below relies // on den always being positive. bool test_invariant() const; void normalize(); }; // Assign in place template
inline rational
& rational
::assign(param_type n, param_type d) { num = n; den = d; normalize(); return *this; } // Unary plus and minus template
inline rational
operator+ (const rational
& r) { return r; } template
inline rational
operator- (const rational
& r) { return rational
(-r.numerator(), r.denominator()); } // Arithmetic assignment operators template
rational
& rational
::operator+= (const rational
& r) { // This calculation avoids overflow, and minimises the number of expensive // calculations. Thanks to Nickolay Mladenov for this algorithm. // // Proof: // We have to compute a/b + c/d, where gcd(a,b)=1 and gcd(b,c)=1. // Let g = gcd(b,d), and b = b1*g, d=d1*g. Then gcd(b1,d1)=1 // // The result is (a*d1 + c*b1) / (b1*d1*g). // Now we have to normalize this ratio. // Let's assume h | gcd((a*d1 + c*b1), (b1*d1*g)), and h > 1 // If h | b1 then gcd(h,d1)=1 and hence h|(a*d1+c*b1) => h|a. // But since gcd(a,b1)=1 we have h=1. // Similarly h|d1 leads to h=1. // So we have that h | gcd((a*d1 + c*b1) , (b1*d1*g)) => h|g // Finally we have gcd((a*d1 + c*b1), (b1*d1*g)) = gcd((a*d1 + c*b1), g) // Which proves that instead of normalizing the result, it is better to // divide num and den by gcd((a*d1 + c*b1), g) // Protect against self-modification IntType r_num = r.num; IntType r_den = r.den; IntType g = math::gcd(den, r_den); den /= g; // = b1 from the calculations above num = num * (r_den / g) + r_num * den; g = math::gcd(num, g); num /= g; den *= r_den/g; return *this; } template
rational
& rational
::operator-= (const rational
& r) { // Protect against self-modification IntType r_num = r.num; IntType r_den = r.den; // This calculation avoids overflow, and minimises the number of expensive // calculations. It corresponds exactly to the += case above IntType g = math::gcd(den, r_den); den /= g; num = num * (r_den / g) - r_num * den; g = math::gcd(num, g); num /= g; den *= r_den/g; return *this; } template
rational
& rational
::operator*= (const rational
& r) { // Protect against self-modification IntType r_num = r.num; IntType r_den = r.den; // Avoid overflow and preserve normalization IntType gcd1 = math::gcd(num, r_den); IntType gcd2 = math::gcd(r_num, den); num = (num/gcd1) * (r_num/gcd2); den = (den/gcd2) * (r_den/gcd1); return *this; } template
rational
& rational
::operator/= (const rational
& r) { // Protect against self-modification IntType r_num = r.num; IntType r_den = r.den; // Avoid repeated construction IntType zero(0); // Trap division by zero if (r_num == zero) throw bad_rational(); if (num == zero) return *this; // Avoid overflow and preserve normalization IntType gcd1 = math::gcd(num, r_num); IntType gcd2 = math::gcd(r_den, den); num = (num/gcd1) * (r_den/gcd2); den = (den/gcd2) * (r_num/gcd1); if (den < zero) { num = -num; den = -den; } return *this; } // Mixed-mode operators template
inline rational
& rational
::operator+= (param_type i) { return operator+= (rational
(i)); } template
inline rational
& rational
::operator-= (param_type i) { return operator-= (rational
(i)); } template
inline rational
& rational
::operator*= (param_type i) { return operator*= (rational
(i)); } template
inline rational
& rational
::operator/= (param_type i) { return operator/= (rational
(i)); } // Increment and decrement template
inline const rational
& rational
::operator++() { // This can never denormalise the fraction num += den; return *this; } template
inline const rational
& rational
::operator--() { // This can never denormalise the fraction num -= den; return *this; } // Comparison operators template
bool rational
::operator< (const rational
& 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's 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's continued-fraction components while ( true ) { // The quotients of the current cycle are the continued-fraction // components. Comparing two c.f. is comparing their sequences, // stopping at the first difference. if ( ts.q != rs.q ) { // Since reciprocation changes the relative order of two variables, // and c.f. 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's c.f. 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) c.f. // 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 c.f. // components of that variable are infinity, while the other variable // has a finite next c.f. component. So that other variable has the // lesser value (modulo the reversal flag!). return ( ts.r != zero ) != static_cast
( reverse ); } } template
bool rational
::operator< (param_type i) const { // Avoid repeated construction int_type const zero( 0 ); // Break value into mixed-fraction form, w/ always-nonnegative remainder BOOST_ASSERT( this->den > zero ); int_type q = this->num / this->den, r = this->num % this->den; while ( r < zero ) { r += this->den; --q; } // Compare with just the quotient, since the remainder always bumps the // value up. [Since q = floor(n/d), and if n/d < i then q < i, if n/d == i // then q == i, if n/d == i + r/d then q == i, and if n/d >= i + 1 then // q >= i + 1 > i; therefore n/d < i iff q < i.] return q < i; } template
bool rational
::operator> (param_type i) const { // Trap equality first if (num == i && den == IntType(1)) return false; // Otherwise, we can use operator< return !operator<(i); } template
inline bool rational
::operator== (const rational
& r) const { return ((num == r.num) && (den == r.den)); } template
inline bool rational
::operator== (param_type i) const { return ((den == IntType(1)) && (num == i)); } // Invariant check template
inline bool rational
::test_invariant() const { return ( this->den > int_type(0) ) && ( math::gcd(this->num, this->den) == int_type(1) ); } // Normalisation template
void rational
::normalize() { // Avoid repeated construction IntType zero(0); if (den == zero) throw bad_rational(); // Handle the case of zero separately, to avoid division by zero if (num == zero) { den = IntType(1); return; } IntType g = math::gcd(num, den); num /= g; den /= g; // Ensure that the denominator is positive if (den < zero) { num = -num; den = -den; } BOOST_ASSERT( this->test_invariant() ); } namespace detail { // A utility class to reset the format flags for an istream at end // of scope, even in case of exceptions struct resetter { resetter(std::istream& is) : is_(is), f_(is.flags()) {} ~resetter() { is_.flags(f_); } std::istream& is_; std::istream::fmtflags f_; // old GNU c++ lib has no ios_base }; } // Input and output template
std::istream& operator>> (std::istream& is, rational
& r) { IntType n = IntType(0), d = IntType(1); char c = 0; detail::resetter sentry(is); is >> n; c = is.get(); if (c != '/') is.clear(std::istream::badbit); // old GNU c++ lib has no ios_base #if !defined(__GNUC__) || (defined(__GNUC__) && (__GNUC__ >= 3)) || defined __SGI_STL_PORT is >> std::noskipws; #else is.unsetf(ios::skipws); // compiles, but seems to have no effect. #endif is >> d; if (is) r.assign(n, d); return is; } // Add manipulators for output format? template
std::ostream& operator<< (std::ostream& os, const rational
& r) { os << r.numerator() << '/' << r.denominator(); return os; } // Type conversion template
inline T rational_cast( const rational
& src BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) { return static_cast
(src.numerator())/static_cast
(src.denominator()); } // Do not use any abs() defined on IntType - it isn't worth it, given the // difficulties involved (Koenig lookup required, there may not *be* an abs() // defined, etc etc). template
inline rational
abs(const rational
& r) { if (r.numerator() >= IntType(0)) return r; return rational
(-r.numerator(), r.denominator()); } } // namespace boost #endif // BOOST_RATIONAL_HPP
rational.hpp
Page URL
File URL
Prev
80/113
Next
Download
( 19 KB )
Note: The DriveHQ service banners will NOT be displayed if the file owner is a paid member.
Comments
Total ratings:
0
Average rating:
Not Rated
Would you like to comment?
Join DriveHQ
for a free account, or
Logon
if you are already a member.