mirror of
https://github.com/boostorg/rational.git
synced 2026-01-19 04:42:09 +00:00
This commit was generated by cvs2svn to compensate for changes in r4,
which included commits to RCS files with non-trunk default branches. [SVN r7621]
This commit is contained in:
96
.gitattributes
vendored
Normal file
96
.gitattributes
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
* text=auto !eol svneol=native#text/plain
|
||||
*.gitattributes text svneol=native#text/plain
|
||||
|
||||
# Scriptish formats
|
||||
*.bat text svneol=native#text/plain
|
||||
*.bsh text svneol=native#text/x-beanshell
|
||||
*.cgi text svneol=native#text/plain
|
||||
*.cmd text svneol=native#text/plain
|
||||
*.js text svneol=native#text/javascript
|
||||
*.php text svneol=native#text/x-php
|
||||
*.pl text svneol=native#text/x-perl
|
||||
*.pm text svneol=native#text/x-perl
|
||||
*.py text svneol=native#text/x-python
|
||||
*.sh eol=lf svneol=LF#text/x-sh
|
||||
configure eol=lf svneol=LF#text/x-sh
|
||||
|
||||
# Image formats
|
||||
*.bmp binary svneol=unset#image/bmp
|
||||
*.gif binary svneol=unset#image/gif
|
||||
*.ico binary svneol=unset#image/ico
|
||||
*.jpeg binary svneol=unset#image/jpeg
|
||||
*.jpg binary svneol=unset#image/jpeg
|
||||
*.png binary svneol=unset#image/png
|
||||
*.tif binary svneol=unset#image/tiff
|
||||
*.tiff binary svneol=unset#image/tiff
|
||||
*.svg text svneol=native#image/svg%2Bxml
|
||||
|
||||
# Data formats
|
||||
*.pdf binary svneol=unset#application/pdf
|
||||
*.avi binary svneol=unset#video/avi
|
||||
*.doc binary svneol=unset#application/msword
|
||||
*.dsp text svneol=crlf#text/plain
|
||||
*.dsw text svneol=crlf#text/plain
|
||||
*.eps binary svneol=unset#application/postscript
|
||||
*.gz binary svneol=unset#application/gzip
|
||||
*.mov binary svneol=unset#video/quicktime
|
||||
*.mp3 binary svneol=unset#audio/mpeg
|
||||
*.ppt binary svneol=unset#application/vnd.ms-powerpoint
|
||||
*.ps binary svneol=unset#application/postscript
|
||||
*.psd binary svneol=unset#application/photoshop
|
||||
*.rdf binary svneol=unset#text/rdf
|
||||
*.rss text svneol=unset#text/xml
|
||||
*.rtf binary svneol=unset#text/rtf
|
||||
*.sln text svneol=native#text/plain
|
||||
*.swf binary svneol=unset#application/x-shockwave-flash
|
||||
*.tgz binary svneol=unset#application/gzip
|
||||
*.vcproj text svneol=native#text/xml
|
||||
*.vcxproj text svneol=native#text/xml
|
||||
*.vsprops text svneol=native#text/xml
|
||||
*.wav binary svneol=unset#audio/wav
|
||||
*.xls binary svneol=unset#application/vnd.ms-excel
|
||||
*.zip binary svneol=unset#application/zip
|
||||
|
||||
# Text formats
|
||||
.htaccess text svneol=native#text/plain
|
||||
*.bbk text svneol=native#text/xml
|
||||
*.cmake text svneol=native#text/plain
|
||||
*.css text svneol=native#text/css
|
||||
*.dtd text svneol=native#text/xml
|
||||
*.htm text svneol=native#text/html
|
||||
*.html text svneol=native#text/html
|
||||
*.ini text svneol=native#text/plain
|
||||
*.log text svneol=native#text/plain
|
||||
*.mak text svneol=native#text/plain
|
||||
*.qbk text svneol=native#text/plain
|
||||
*.rst text svneol=native#text/plain
|
||||
*.sql text svneol=native#text/x-sql
|
||||
*.txt text svneol=native#text/plain
|
||||
*.xhtml text svneol=native#text/xhtml%2Bxml
|
||||
*.xml text svneol=native#text/xml
|
||||
*.xsd text svneol=native#text/xml
|
||||
*.xsl text svneol=native#text/xml
|
||||
*.xslt text svneol=native#text/xml
|
||||
*.xul text svneol=native#text/xul
|
||||
*.yml text svneol=native#text/plain
|
||||
boost-no-inspect text svneol=native#text/plain
|
||||
CHANGES text svneol=native#text/plain
|
||||
COPYING text svneol=native#text/plain
|
||||
INSTALL text svneol=native#text/plain
|
||||
Jamfile text svneol=native#text/plain
|
||||
Jamroot text svneol=native#text/plain
|
||||
Jamfile.v2 text svneol=native#text/plain
|
||||
Jamrules text svneol=native#text/plain
|
||||
Makefile* text svneol=native#text/plain
|
||||
README text svneol=native#text/plain
|
||||
TODO text svneol=native#text/plain
|
||||
|
||||
# Code formats
|
||||
*.c text svneol=native#text/plain
|
||||
*.cpp text svneol=native#text/plain
|
||||
*.h text svneol=native#text/plain
|
||||
*.hpp text svneol=native#text/plain
|
||||
*.ipp text svneol=native#text/plain
|
||||
*.tpp text svneol=native#text/plain
|
||||
*.jam text svneol=native#text/plain
|
||||
*.java text svneol=native#text/plain
|
||||
321
include/boost/rational.hpp
Normal file
321
include/boost/rational.hpp
Normal file
@@ -0,0 +1,321 @@
|
||||
// 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 for most recent version including 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
|
||||
|
||||
// Revision History
|
||||
// 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 <string> (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 <iostream> // for std::istream and std::ostream
|
||||
#include <stdexcept> // for std::domain_error
|
||||
#include <string> // for std::string implicit constructor
|
||||
#include <boost/operators.hpp> // for boost::addable etc
|
||||
#include <cstdlib> // for std::abs
|
||||
#include <boost/config.hpp> // for BOOST_NO_STDC_NAMESPACE, BOOST_MSVC
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <typename IntType>
|
||||
IntType gcd(IntType n, IntType m)
|
||||
{
|
||||
while (m) {
|
||||
IntType r = n % m;
|
||||
if (r < 0)
|
||||
r += m;
|
||||
|
||||
n = m;
|
||||
m = r;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
template <typename IntType>
|
||||
IntType lcm(IntType n, IntType m)
|
||||
{
|
||||
n /= gcd(n, m);
|
||||
n *= m;
|
||||
return n;
|
||||
}
|
||||
|
||||
class bad_rational : public std::domain_error
|
||||
{
|
||||
public:
|
||||
explicit bad_rational() : std::domain_error("bad rational: zero denominator") {}
|
||||
};
|
||||
|
||||
// The following is an awful lot of code to implement a 1-line abs() function.
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
// This is a gross hack. MS Visual C++ has utterly broken namespace reslution
|
||||
// rules. Basically, the call to abs(int) in abs(rational) below will not find
|
||||
// ::abs(). So the only way we have of fixing this is to reimplement std::abs
|
||||
// in the boost:: namespace! In practice, this is a relatively minor bit of
|
||||
// pollution, so we should be OK.
|
||||
|
||||
inline int abs(int n) { return ::abs(n); }
|
||||
inline long abs(long n) { return ::labs(n); }
|
||||
|
||||
#endif
|
||||
|
||||
template <typename IntType>
|
||||
class rational;
|
||||
|
||||
template <typename IntType>
|
||||
rational<IntType> abs(const rational<IntType>& r);
|
||||
|
||||
template <typename IntType>
|
||||
class rational :
|
||||
less_than_comparable < rational<IntType> >,
|
||||
equality_comparable < rational<IntType> >,
|
||||
addable < rational<IntType> >,
|
||||
subtractable < rational<IntType> >,
|
||||
multipliable < rational<IntType> >,
|
||||
dividable < rational<IntType> >,
|
||||
incrementable < rational<IntType> >,
|
||||
decrementable < rational<IntType> >
|
||||
{
|
||||
typedef IntType int_type;
|
||||
|
||||
public:
|
||||
rational(IntType n = 0) : num(n), den(1) {}
|
||||
rational(IntType n, IntType d) : num(n), den(d) { normalize(); }
|
||||
|
||||
// Default copy constructor and assignment are fine
|
||||
|
||||
// Assign in place
|
||||
rational& assign(IntType n, IntType 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);
|
||||
|
||||
// Increment and decrement
|
||||
const rational& operator++();
|
||||
const rational& operator--();
|
||||
|
||||
// Comparison operators
|
||||
bool operator< (const rational& r) const;
|
||||
bool operator== (const rational& r) 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.
|
||||
void normalize();
|
||||
};
|
||||
|
||||
// Assign in place
|
||||
template <typename IntType>
|
||||
inline rational<IntType>& rational<IntType>::assign(IntType n, IntType d)
|
||||
{
|
||||
num = n;
|
||||
den = d;
|
||||
normalize();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Unary plus and minus
|
||||
template <typename IntType>
|
||||
inline rational<IntType> operator+ (const rational<IntType>& r)
|
||||
{
|
||||
return r;
|
||||
}
|
||||
|
||||
template <typename IntType>
|
||||
inline rational<IntType> operator- (const rational<IntType>& r)
|
||||
{
|
||||
return rational<IntType>(-r.numerator(), r.denominator());
|
||||
}
|
||||
|
||||
// Arithmetic assignment operators
|
||||
template <typename IntType>
|
||||
rational<IntType>& rational<IntType>::operator+= (const rational<IntType>& r)
|
||||
{
|
||||
// This calculation avoids overflow
|
||||
IntType new_den = lcm(den, r.den);
|
||||
num = num * (new_den / den) + r.num * (new_den / r.den);
|
||||
den = new_den;
|
||||
normalize(); // Example where this is needed: 1/2 + 1/2
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename IntType>
|
||||
rational<IntType>& rational<IntType>::operator-= (const rational<IntType>& r)
|
||||
{
|
||||
// This calculation avoids overflow
|
||||
IntType new_den = lcm(den, r.den);
|
||||
num = num * (new_den / den) - r.num * (new_den / r.den);
|
||||
den = new_den;
|
||||
normalize(); // Example where this is needed: 1/2 + 1/2
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename IntType>
|
||||
rational<IntType>& rational<IntType>::operator*= (const rational<IntType>& r)
|
||||
{
|
||||
// Avoid overflow and preserve normalization
|
||||
IntType gcd1 = gcd<IntType>(num, r.den);
|
||||
IntType gcd2 = gcd<IntType>(r.num, den);
|
||||
num = (num/gcd1) * (r.num/gcd2);
|
||||
den = (den/gcd2) * (r.den/gcd1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename IntType>
|
||||
rational<IntType>& rational<IntType>::operator/= (const rational<IntType>& r)
|
||||
{
|
||||
// Avoid overflow and preserve normalization
|
||||
IntType gcd1 = gcd<IntType>(num, r.num);
|
||||
IntType gcd2 = gcd<IntType>(r.den, den);
|
||||
num = (num/gcd1) * (r.den/gcd2);
|
||||
den = (den/gcd2) * (r.num/gcd1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Increment and decrement
|
||||
template <typename IntType>
|
||||
inline const rational<IntType>& rational<IntType>::operator++()
|
||||
{
|
||||
// This can never denormalise the fraction
|
||||
num += den;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename IntType>
|
||||
inline const rational<IntType>& rational<IntType>::operator--()
|
||||
{
|
||||
// This can never denormalise the fraction
|
||||
num -= den;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Comparison operators
|
||||
template <typename IntType>
|
||||
bool rational<IntType>::operator< (const rational<IntType>& r) const
|
||||
{
|
||||
// Avoid overflow
|
||||
IntType gcd1 = gcd<IntType>(num, r.num);
|
||||
IntType gcd2 = gcd<IntType>(r.den, den);
|
||||
return (num/gcd1) * (r.den/gcd2) < (den/gcd2) * (r.num/gcd1);
|
||||
}
|
||||
|
||||
template <typename IntType>
|
||||
inline bool rational<IntType>::operator== (const rational<IntType>& r) const
|
||||
{
|
||||
return ((num == r.num) && (den == r.den));
|
||||
}
|
||||
|
||||
// Normalisation
|
||||
template <typename IntType>
|
||||
void rational<IntType>::normalize()
|
||||
{
|
||||
if (den == 0)
|
||||
throw bad_rational();
|
||||
|
||||
IntType g = gcd<IntType>(num, den);
|
||||
|
||||
num /= g;
|
||||
den /= g;
|
||||
|
||||
if (den < 0) {
|
||||
num = -num;
|
||||
den = -den;
|
||||
}
|
||||
}
|
||||
|
||||
// Input and output
|
||||
template <typename IntType>
|
||||
std::istream& operator>> (std::istream& is, rational<IntType>& r)
|
||||
{
|
||||
IntType n = 0, d = 1;
|
||||
char c = 0;
|
||||
|
||||
is >> n;
|
||||
c = is.get();
|
||||
|
||||
if (c == '/')
|
||||
is >> d;
|
||||
else
|
||||
is.putback(c);
|
||||
|
||||
if (is)
|
||||
r.assign(n, d);
|
||||
|
||||
return is;
|
||||
}
|
||||
|
||||
// Add manipulators for output format?
|
||||
template <typename IntType>
|
||||
std::ostream& operator<< (std::ostream& os, const rational<IntType>& r)
|
||||
{
|
||||
os << r.numerator() << '/' << r.denominator();
|
||||
return os;
|
||||
}
|
||||
|
||||
// Type conversion
|
||||
template <typename T, typename IntType>
|
||||
inline T rational_cast(const rational<IntType>& src)
|
||||
{
|
||||
return static_cast<T>(src.numerator())/src.denominator();
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
// Workaround for a bug in gcc 2.95.2 - using statements at function scope are
|
||||
// silently ignored - to get around this, we need to include std::abs at
|
||||
// namespace scope.
|
||||
|
||||
using std::abs;
|
||||
#endif
|
||||
|
||||
template <typename IntType>
|
||||
inline rational<IntType> abs(const rational<IntType>& r)
|
||||
{
|
||||
#ifndef BOOST_NO_STDC_NAMESPACE
|
||||
// We want to use abs() unadorned below, so that if IntType is a
|
||||
// user-defined type, the name lookup rules will work to find an
|
||||
// appropriate abs() defined for IntType.
|
||||
//
|
||||
// We protect this with BOOST_NO_STDC_NAMESPACE, as some compilers
|
||||
// don't put abs into std:: (notably MS Visual C++) and so we can't
|
||||
// "use" it from there.
|
||||
using std::abs;
|
||||
#endif
|
||||
// Note that with normalized fractions, the denominator is always positive.
|
||||
return rational<IntType>(abs(r.numerator()), r.denominator());
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_RATIONAL_HPP
|
||||
|
||||
103
rational_example.cpp
Normal file
103
rational_example.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
// smart pointer test program ----------------------------------------------//
|
||||
|
||||
// (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.
|
||||
|
||||
// Revision History
|
||||
// 14 Dec 99 Initial version
|
||||
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#ifndef __MINGW32__
|
||||
#include <limits>
|
||||
#else
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#include <exception>
|
||||
#include <boost/rational.hpp>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using boost::rational;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// This is a nasty hack, required because MSVC does not implement "Koenig
|
||||
// Lookup". Basically, if I call abs(r), the C++ standard says that the
|
||||
// compiler should look for a definition of abs in the namespace which
|
||||
// contains r's class (in this case boost) - among other places.
|
||||
|
||||
// Koenig Lookup is a relatively recent feature, and other compilers may not
|
||||
// implement it yet. If so, try including this line.
|
||||
|
||||
using boost::abs;
|
||||
#endif
|
||||
|
||||
int main ()
|
||||
{
|
||||
rational<int> half(1,2);
|
||||
rational<int> one(1);
|
||||
rational<int> two(2);
|
||||
|
||||
// Some basic checks
|
||||
assert(half.numerator() == 1);
|
||||
assert(half.denominator() == 2);
|
||||
assert(boost::rational_cast<double>(half) == 0.5);
|
||||
|
||||
// Arithmetic
|
||||
assert(half + half == one);
|
||||
assert(one - half == half);
|
||||
assert(two * half == one);
|
||||
assert(one / half == two);
|
||||
|
||||
// With conversions to integer
|
||||
assert(half+half == 1);
|
||||
assert(2 * half == one);
|
||||
assert(2 * half == 1);
|
||||
assert(one / half == 2);
|
||||
assert(1 / half == 2);
|
||||
|
||||
// Sign handling
|
||||
rational<int> minus_half(-1,2);
|
||||
assert(-half == minus_half);
|
||||
assert(abs(minus_half) == half);
|
||||
|
||||
// Do we avoid overflow?
|
||||
#ifndef __MINGW32__
|
||||
int maxint = std::numeric_limits<int>::max();
|
||||
#else
|
||||
int maxint = INT_MAX;
|
||||
#endif
|
||||
rational<int> big(maxint, 2);
|
||||
assert(2 * big == maxint);
|
||||
|
||||
// Print some of the above results
|
||||
cout << half << "+" << half << "=" << one << endl;
|
||||
cout << one << "-" << half << "=" << half << endl;
|
||||
cout << two << "*" << half << "=" << one << endl;
|
||||
cout << one << "/" << half << "=" << two << endl;
|
||||
cout << "abs(" << minus_half << ")=" << half << endl;
|
||||
cout << "2 * " << big << "=" << maxint
|
||||
<< " (rational: " << rational<int>(maxint) << ")" << endl;
|
||||
|
||||
// Some extras
|
||||
rational<int> pi(22,7);
|
||||
cout << "pi = " << boost::rational_cast<double>(pi) << " (nearly)" << endl;
|
||||
|
||||
// Exception handling
|
||||
try {
|
||||
rational<int> r; // Forgot to initialise - set to 0
|
||||
r = 1/r; // Boom!
|
||||
}
|
||||
catch (const boost::bad_rational &e) {
|
||||
cout << "Bad rational, as expected: " << e.what() << endl;
|
||||
}
|
||||
catch (...) {
|
||||
cout << "Wrong exception raised!" << endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user