mirror of
https://github.com/boostorg/math.git
synced 2026-01-19 04:22:09 +00:00
Daryle Walker's GCD library submission
[SVN r11814]
This commit is contained in:
237
doc/common_factor.html
Normal file
237
doc/common_factor.html
Normal file
@@ -0,0 +1,237 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Boost GCD & LCM Library</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="white" text="black" link="blue" alink="red" vlink="purple">
|
||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)"
|
||||
align="middle" width="277" height="86">Greatest Common Divisor and Least
|
||||
Common Multiple</h1>
|
||||
|
||||
<p>The class and function templates in <cite><a
|
||||
href="../../../boost/math/common_factor.hpp"><boost/math/common_factor.hpp></a>
|
||||
</cite> provide run-time and compile-time evaluation of the greatest
|
||||
common divisor (GCD) or least common multiple (LCM) of two integers.
|
||||
These facilities are useful for many numeric-oriented generic
|
||||
programming problems.</p>
|
||||
|
||||
<h2><a name="contents">Contents</a></h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="#contents">Contents</a></li>
|
||||
<li><a href="#synopsis">Synopsis</a></li>
|
||||
<li><a href="#gcd_obj">GCD Function Object</a></li>
|
||||
<li><a href="#lcm_obj">LCM Function Object</a></li>
|
||||
<li><a href="#run_gcd_lcm">Run-time GCD & LCM
|
||||
Determination</a></li>
|
||||
<li><a href="#ct_gcd_lcm">Compile-time GCD & LCM
|
||||
Determination</a></li>
|
||||
<li><a href="#example">Example</a></li>
|
||||
<li><a href="#demo">Demonstration Program</a></li>
|
||||
<li><a href="#rationale">Rationale</a></li>
|
||||
<li><a href="#credits">Credits</a></li>
|
||||
</ul>
|
||||
|
||||
<h2><a name="synopsis">Synopsis</a></h2>
|
||||
|
||||
<blockquote><pre>
|
||||
namespace boost
|
||||
{
|
||||
namespace math
|
||||
{
|
||||
|
||||
template < typename IntegerType >
|
||||
class gcd_evaluator;
|
||||
template < typename IntegerType >
|
||||
class lcm_evaluator;
|
||||
|
||||
template < typename IntegerType >
|
||||
IntegerType gcd( IntegerType const &a, IntegerType const &b );
|
||||
template < typename IntegerType >
|
||||
IntegerType lcm( IntegerType const &a, IntegerType const &b );
|
||||
|
||||
template < unsigned long Value1, unsigned long Value2 >
|
||||
struct static_gcd;
|
||||
template < unsigned long Value1, unsigned long Value2 >
|
||||
struct static_lcm;
|
||||
|
||||
}
|
||||
}
|
||||
</pre></blockquote>
|
||||
|
||||
<h2><a name="gcd_obj">GCD Function Object</a></h2>
|
||||
|
||||
<blockquote><pre>
|
||||
template < typename IntegerType >
|
||||
class boost::math::gcd_evaluator
|
||||
{
|
||||
public:
|
||||
// Types
|
||||
typedef IntegerType result_type;
|
||||
typedef IntegerType first_argument_type;
|
||||
typedef IntegerType second_argument_type;
|
||||
|
||||
// Function object interface
|
||||
result_type operator ()( first_argument_type const &a,
|
||||
second_argument_type const &b ) const;
|
||||
};
|
||||
</pre></blockquote>
|
||||
|
||||
<p>The <code>boost::math::gcd_evaluator</code> class template defines
|
||||
a function object class to return the greatest common divisor of two
|
||||
integers. The template is parameterized by a single type, called
|
||||
<code>IntegerType</code> here. This type should be a numeric type
|
||||
that represents integers. The result of the function object is always
|
||||
nonnegative, even if either of the operator arguments is negative.</p>
|
||||
|
||||
<p>This function object class template is used in the corresponding
|
||||
version of the <a href="#run_gcd_lcm">GCD function template</a>. If
|
||||
a numeric type wants to customize evaluations of its greatest common
|
||||
divisors, then the type should specialize on the <code>gcd_evaluator</code>
|
||||
class template.</p>
|
||||
|
||||
<h2><a name="lcm_obj">LCM Function Object</a></h2>
|
||||
|
||||
<blockquote><pre>
|
||||
template < typename IntegerType >
|
||||
class boost::math::lcm_evaluator
|
||||
{
|
||||
public:
|
||||
// Types
|
||||
typedef IntegerType result_type;
|
||||
typedef IntegerType first_argument_type;
|
||||
typedef IntegerType second_argument_type;
|
||||
|
||||
// Function object interface
|
||||
result_type operator ()( first_argument_type const &a,
|
||||
second_argument_type const &b ) const;
|
||||
};
|
||||
</pre></blockquote>
|
||||
|
||||
<p>The <code>boost::math::lcm_evaluator</code> class template defines
|
||||
a function object class to return the least common multiple of two
|
||||
integers. The template is parameterized by a single type, called
|
||||
<code>IntegerType</code> here. This type should be a numeric type
|
||||
that represents integers. The result of the function object is always
|
||||
nonnegative, even if either of the operator arguments is negative.
|
||||
If the least common multiple is beyond the range of the integer type,
|
||||
the results are undefined.</p>
|
||||
|
||||
<p>This function object class template is used in the corresponding
|
||||
version of the <a href="#run_gcd_lcm">LCM function template</a>. If a
|
||||
numeric type wants to customize evaluations of its least common
|
||||
multiples, then the type should specialize on the <code>lcm_evaluator</code>
|
||||
class template.</p>
|
||||
|
||||
<h2><a name="run_gcd_lcm">Run-time GCD & LCM Determination</a></h2>
|
||||
|
||||
<blockquote><pre>
|
||||
template < typename IntegerType >
|
||||
IntegerType boost::math::gcd( IntegerType const &a, IntegerType const &b );
|
||||
|
||||
template < typename IntegerType >
|
||||
IntegerType boost::math::lcm( IntegerType const &a, IntegerType const &b );
|
||||
</pre></blockquote>
|
||||
|
||||
<p>The <code>boost::math::gcd</code> function template returns the greatest
|
||||
common (nonnegative) divisor of the two integers passed to it. The
|
||||
<code>boost::math::lcm</code> function template returns the least common
|
||||
(nonnegative) multiple of the two integers passed to it. The function
|
||||
templates are parameterized on the function arguments' <var>IntegerType</var>,
|
||||
which is also the return type. Internally, these function templates use
|
||||
an object of the corresponding version of the <code><a
|
||||
href="#gcd_obj">gcd_evaluator</a></code> and <code><a
|
||||
href="#lcm_obj">lcm_evaluator</a></code> class templates, respectively.</p>
|
||||
|
||||
<h2><a name="ct_gcd_lcm">Compile-time GCD & LCM Determination</a></h2>
|
||||
|
||||
<blockquote><pre>
|
||||
template < unsigned long Value1, unsigned long Value2 >
|
||||
struct boost::math::static_gcd
|
||||
{
|
||||
static unsigned long const value = <em>implementation_defined</em>;
|
||||
};
|
||||
|
||||
template < unsigned long Value1, unsigned long Value2 >
|
||||
struct boost::math::static_lcm
|
||||
{
|
||||
static unsigned long const value = <em>implementation_defined</em>;
|
||||
};
|
||||
</pre></blockquote>
|
||||
|
||||
<p>The <code>boost::math::static_gcd</code> and <code>boost::math::static_lcm</code>
|
||||
class templates take two value-based template parameters of the
|
||||
<code>unsigned long</code> type and have a single static constant data
|
||||
member, <code>value</code>, of that same type. The value of that member
|
||||
is the greatest common factor or least common multiple, respectively, of
|
||||
the template arguments. A compile-time error will occur if the least common
|
||||
multiple is beyond the range of an <code>unsigned long</code>.</p>
|
||||
|
||||
<h2><a name="example">Example</a></h2>
|
||||
|
||||
<blockquote><pre>
|
||||
#include <boost/math/common_factor.hpp>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
cout << "The GCD and LCM of 6 and 15 are "
|
||||
<< boost::math::gcd(6, 15) << " and "
|
||||
<< boost::math::lcm(6, 15) << ", respectively."
|
||||
<< endl;
|
||||
|
||||
cout << "The GCD and LCM of 8 and 9 are "
|
||||
<< boost::math::static_gcd<8, 9>::value
|
||||
<< " and "
|
||||
<< boost::math::static_lcm<8, 9>::value
|
||||
<< ", respectively." << endl;
|
||||
|
||||
int a[] = { 4, 5, 6 }, b[] = { 7, 8, 9 }, c[3];
|
||||
std::transform( a, a + 3, b, c, boost::math::gcd_evaluator<int>() );
|
||||
std::copy( c, c + 3, std::ostream_iterator<int>(cout, " ") );
|
||||
}
|
||||
</pre></blockquote>
|
||||
|
||||
<h2><a name="demo">Demonstration Program</a></h2>
|
||||
|
||||
<p>The program <a
|
||||
href="../test/common_factor_test.cpp">common_factor_test.cpp</a> is a
|
||||
demonstration of the results from instantiating various examples of the
|
||||
run-time GCD and LCM function templates and the compile-time GCD and
|
||||
LCM class templates. (The run-time GCD and LCM class templates are
|
||||
tested indirectly through the run-time function templates.)</p>
|
||||
|
||||
<h2><a name="rationale">Rationale</a></h2>
|
||||
|
||||
<p>The greatest common divisor and least common multiple functions are
|
||||
greatly used in some numeric contexts, including some of the other Boost
|
||||
libraries. Centralizing these functions to one header improves code
|
||||
factoring and eases maintainence.</p>
|
||||
|
||||
<h2><a name="credits">Credits</a></h2>
|
||||
|
||||
<p>The author of the Boost compilation of GCD and LCM computations is <a
|
||||
href="../../../people/daryle_walker.html">Daryle Walker</a>. The code was
|
||||
prompted by existing code hiding in the implementations of <a
|
||||
href="../../../people/paul_moore.htm">Paul Moore</a>'s <a
|
||||
href="../../rational/index.html">rational</a> library and Steve Cleary's <a
|
||||
href="../../pool/doc/index.html">pool</a> library. The code had updates by
|
||||
Helmut Zeisel.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised November 7, 2001</p>
|
||||
|
||||
<p>© Copyright Daryle Walker 2001. Permission to copy, use,
|
||||
modify, sell and distribute this document is granted provided this
|
||||
copyright notice appears in all copies. This document is provided
|
||||
"as is" without express or implied warranty, and with no claim
|
||||
as to its suitability for any purpose.</p>
|
||||
</body>
|
||||
</html>
|
||||
92
doc/index.html
Normal file
92
doc/index.html
Normal file
@@ -0,0 +1,92 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Boost Math Library</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="white" text="black">
|
||||
<table border="1" bgcolor="teal" cellpadding="2">
|
||||
<tr>
|
||||
<td bgcolor="white"><img src="../../c++boost.gif"
|
||||
alt="c++boost.gif (8819 bytes)" width="277"
|
||||
height="86"></td>
|
||||
<td><a href="../../index.htm"><font face="Arial"
|
||||
color="white"><big>Home</big></font></a></td>
|
||||
<td><a href="../libraries.htm"><font face="Arial"
|
||||
color="white"><big>Libraries</big></font></a></td>
|
||||
<td><a href="../../people/people.htm"><font face="Arial"
|
||||
color="white"><big>People</big></font></a></td>
|
||||
<td><a href="../../more/faq.htm"><font face="Arial"
|
||||
color="white"><big>FAQ</big></font></a></td>
|
||||
<td><a href="../../more/index.htm"><font face="Arial"
|
||||
color="white"><big>More</big></font></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1>Boost Math Library</h1>
|
||||
|
||||
<table border="1" cellpadding="5">
|
||||
<tr>
|
||||
<th>Header / Docs</th>
|
||||
<th>Contents</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<code><a href="../../../boost/math_fwd.hpp"><boost/math_fwd.hpp></a></code>
|
||||
</td>
|
||||
<td valign="top">Forward declaration header.
|
||||
</td>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<code><a href="../../../boost/math/octonion.hpp"><boost/math/octonion.hpp></a></code><br>
|
||||
<br><a href="octonion/index.htm">documentation</a>
|
||||
</td>
|
||||
<td valign="top">Octonion class templates and octonion algebra
|
||||
function templates.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<code><a href="../../../boost/math/quaternion.hpp"><boost/math/quaternion.hpp></a></code><br>
|
||||
<br><a href="quaternion/index.htm">documentation</a>
|
||||
</td>
|
||||
<td valign="top">Quaternion class templates and quaternion
|
||||
algebra function templates.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<code><a href="../../boost/math/special_functions/acosh.hpp"><boost/math/special_functions/acosh.hpp></a></code><br>
|
||||
<code><a href="../../boost/math/special_functions/asinh.hpp"><boost/math/special_functions/asinh.hpp></a></code><br>
|
||||
<code><a href="../../boost/math/special_functions/atanh.hpp"><boost/math/special_functions/atanh.hpp></a></code><br>
|
||||
<code><a href="../../boost/math/special_functions/sinc.hpp"><boost/math/special_functions/sinc.hpp></a></code><br>
|
||||
<code><a href="../../boost/math/special_functions/sinhc.hpp"><boost/math/special_functions/sinhc.hpp></a></code><br>
|
||||
<br><a href="special_functions/index.htm">documentation</a>
|
||||
</td>
|
||||
<td valign="top">"Special" mathematical function
|
||||
templates.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<code><a href="../../../boost/math/common_factor.hpp"><boost/math/common_factor.hpp></a></code><br>
|
||||
<br><a href="common_factor.html">documentation</a>
|
||||
</td>
|
||||
<td valign="top">Compile-time and run-time class and function
|
||||
templates for greatest common divisor and least common
|
||||
multiple.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2>Rationale</h2>
|
||||
|
||||
<p>The math sub-library of Boost helps segregate the large number of
|
||||
Boost headers. This sub-library should contain various math-related
|
||||
items.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised: 4 Oct 2001</p>
|
||||
</body>
|
||||
</html>
|
||||
464
include/boost/math/common_factor.hpp
Normal file
464
include/boost/math/common_factor.hpp
Normal file
@@ -0,0 +1,464 @@
|
||||
// Boost common_factor.hpp header file -------------------------------------//
|
||||
|
||||
// (C) Copyright Daryle Walker, Stephen Cleary, Paul Moore 2001. 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 updates, documentation, and revision history.
|
||||
|
||||
#ifndef BOOST_MATH_COMMON_FACTOR_HPP
|
||||
#define BOOST_MATH_COMMON_FACTOR_HPP
|
||||
|
||||
#include <boost/math_fwd.hpp> // self include
|
||||
|
||||
#include <boost/config.hpp> // for BOOST_STATIC_CONSTANT, etc.
|
||||
#include <boost/limits.hpp> // for std::numeric_limits
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace math
|
||||
{
|
||||
|
||||
|
||||
// Forward declarations for function templates -----------------------------//
|
||||
|
||||
template < typename IntegerType >
|
||||
IntegerType gcd( IntegerType const &a, IntegerType const &b );
|
||||
|
||||
template < typename IntegerType >
|
||||
IntegerType lcm( IntegerType const &a, IntegerType const &b );
|
||||
|
||||
|
||||
// Greatest common divisor evaluator class declaration ---------------------//
|
||||
|
||||
template < typename IntegerType >
|
||||
class gcd_evaluator
|
||||
{
|
||||
public:
|
||||
// Types
|
||||
typedef IntegerType result_type, first_argument_type, second_argument_type;
|
||||
|
||||
// Function object interface
|
||||
result_type operator ()( first_argument_type const &a,
|
||||
second_argument_type const &b ) const;
|
||||
|
||||
}; // boost::math::gcd_evaluator
|
||||
|
||||
|
||||
// Least common multiple evaluator class declaration -----------------------//
|
||||
|
||||
template < typename IntegerType >
|
||||
class lcm_evaluator
|
||||
{
|
||||
public:
|
||||
// Types
|
||||
typedef IntegerType result_type, first_argument_type, second_argument_type;
|
||||
|
||||
// Function object interface
|
||||
result_type operator ()( first_argument_type const &a,
|
||||
second_argument_type const &b ) const;
|
||||
|
||||
}; // boost::math::lcm_evaluator
|
||||
|
||||
|
||||
// Implementation details --------------------------------------------------//
|
||||
|
||||
namespace detail
|
||||
{
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
// Build GCD with Euclid's recursive algorithm
|
||||
template < unsigned long Value1, unsigned long Value2 >
|
||||
struct static_gcd_helper_t
|
||||
{
|
||||
private:
|
||||
BOOST_STATIC_CONSTANT( unsigned long, new_value1 = Value2 );
|
||||
BOOST_STATIC_CONSTANT( unsigned long, new_value2 = Value1 % Value2 );
|
||||
|
||||
#ifndef __BORLANDC__
|
||||
#define BOOST_DETAIL_GCD_HELPER_VAL(Value) Value
|
||||
#else
|
||||
typedef static_gcd_helper_t self_type;
|
||||
#define BOOST_DETAIL_GCD_HELPER_VAL(Value) (self_type:: Value )
|
||||
#endif
|
||||
|
||||
typedef static_gcd_helper_t< BOOST_DETAIL_GCD_HELPER_VAL(new_value1),
|
||||
BOOST_DETAIL_GCD_HELPER_VAL(new_value2) > next_step_type;
|
||||
|
||||
#undef BOOST_DETAIL_GCD_HELPER_VAL
|
||||
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT( unsigned long, value = next_step_type::value );
|
||||
};
|
||||
|
||||
// Non-recursive case
|
||||
template < unsigned long Value1 >
|
||||
struct static_gcd_helper_t< Value1, 0UL >
|
||||
{
|
||||
BOOST_STATIC_CONSTANT( unsigned long, value = Value1 );
|
||||
};
|
||||
#else
|
||||
// Use inner class template workaround from Peter Dimov
|
||||
template < unsigned long Value1 >
|
||||
struct static_gcd_helper2_t
|
||||
{
|
||||
template < unsigned long Value2 >
|
||||
struct helper
|
||||
{
|
||||
BOOST_STATIC_CONSTANT( unsigned long, value
|
||||
= static_gcd_helper2_t<Value2>::helper<Value1 % Value2>::value );
|
||||
};
|
||||
|
||||
template < >
|
||||
struct helper< 0UL >
|
||||
{
|
||||
BOOST_STATIC_CONSTANT( unsigned long, value = Value1 );
|
||||
};
|
||||
};
|
||||
|
||||
// Special case
|
||||
template < >
|
||||
struct static_gcd_helper2_t< 0UL >
|
||||
{
|
||||
template < unsigned long Value2 >
|
||||
struct helper
|
||||
{
|
||||
BOOST_STATIC_CONSTANT( unsigned long, value = Value2 );
|
||||
};
|
||||
};
|
||||
|
||||
// Build the GCD from the above template(s)
|
||||
template < unsigned long Value1, unsigned long Value2 >
|
||||
struct static_gcd_helper_t
|
||||
{
|
||||
BOOST_STATIC_CONSTANT( unsigned long, value
|
||||
= static_gcd_helper2_t<Value1>::helper<Value2>::value );
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
// Build the LCM from the GCD
|
||||
template < unsigned long Value1, unsigned long Value2 >
|
||||
struct static_lcm_helper_t
|
||||
{
|
||||
typedef static_gcd_helper_t<Value1, Value2> gcd_type;
|
||||
|
||||
BOOST_STATIC_CONSTANT( unsigned long, value = Value1 / gcd_type::value
|
||||
* Value2 );
|
||||
};
|
||||
|
||||
// Special case for zero-GCD values
|
||||
template < >
|
||||
struct static_lcm_helper_t< 0UL, 0UL >
|
||||
{
|
||||
BOOST_STATIC_CONSTANT( unsigned long, value = 0UL );
|
||||
};
|
||||
#else
|
||||
// Adapt GCD's inner class template workaround for LCM
|
||||
template < unsigned long Value1 >
|
||||
struct static_lcm_helper2_t
|
||||
{
|
||||
template < unsigned long Value2 >
|
||||
struct helper
|
||||
{
|
||||
typedef static_gcd_helper_t<Value1, Value2> gcd_type;
|
||||
|
||||
BOOST_STATIC_CONSTANT( unsigned long, value = Value1
|
||||
/ gcd_type::value * Value2 );
|
||||
};
|
||||
|
||||
template < >
|
||||
struct helper< 0UL >
|
||||
{
|
||||
BOOST_STATIC_CONSTANT( unsigned long, value = 0UL );
|
||||
};
|
||||
};
|
||||
|
||||
// Special case
|
||||
template < >
|
||||
struct static_lcm_helper2_t< 0UL >
|
||||
{
|
||||
template < unsigned long Value2 >
|
||||
struct helper
|
||||
{
|
||||
BOOST_STATIC_CONSTANT( unsigned long, value = 0UL );
|
||||
};
|
||||
};
|
||||
|
||||
// Build the LCM from the above template(s)
|
||||
template < unsigned long Value1, unsigned long Value2 >
|
||||
struct static_lcm_helper_t
|
||||
{
|
||||
BOOST_STATIC_CONSTANT( unsigned long, value
|
||||
= static_lcm_helper2_t<Value1>::helper<Value2>::value );
|
||||
};
|
||||
#endif
|
||||
|
||||
// Greatest common divisor for rings (including unsigned integers)
|
||||
template < typename RingType >
|
||||
RingType
|
||||
gcd_euclidean
|
||||
(
|
||||
RingType a,
|
||||
RingType b
|
||||
)
|
||||
{
|
||||
// Avoid repeated construction
|
||||
#ifndef __BORLANDC__
|
||||
RingType const zero = static_cast<RingType>( 0 );
|
||||
#else
|
||||
RingType zero = static_cast<RingType>( 0 );
|
||||
#endif
|
||||
|
||||
// Reduce by GCD-remainder property [GCD(a,b) == GCD(b,a MOD b)]
|
||||
while ( true )
|
||||
{
|
||||
if ( a == zero )
|
||||
return b;
|
||||
b %= a;
|
||||
|
||||
if ( b == zero )
|
||||
return a;
|
||||
a %= b;
|
||||
}
|
||||
}
|
||||
|
||||
// Greatest common divisor for (signed) integers
|
||||
template < typename IntegerType >
|
||||
inline
|
||||
IntegerType
|
||||
gcd_integer
|
||||
(
|
||||
IntegerType const & a,
|
||||
IntegerType const & b
|
||||
)
|
||||
{
|
||||
// Avoid repeated construction
|
||||
IntegerType const zero = static_cast<IntegerType>( 0 );
|
||||
IntegerType const result = gcd_euclidean( a, b );
|
||||
|
||||
return ( result < zero ) ? -result : result;
|
||||
}
|
||||
|
||||
// Least common multiple for rings (including unsigned integers)
|
||||
template < typename RingType >
|
||||
inline
|
||||
RingType
|
||||
lcm_euclidean
|
||||
(
|
||||
RingType const & a,
|
||||
RingType const & b
|
||||
)
|
||||
{
|
||||
RingType const zero = static_cast<RingType>( 0 );
|
||||
RingType const temp = gcd_euclidean( a, b );
|
||||
|
||||
return ( temp != zero ) ? ( a / temp * b ) : zero;
|
||||
}
|
||||
|
||||
// Least common multiple for (signed) integers
|
||||
template < typename IntegerType >
|
||||
inline
|
||||
IntegerType
|
||||
lcm_integer
|
||||
(
|
||||
IntegerType const & a,
|
||||
IntegerType const & b
|
||||
)
|
||||
{
|
||||
// Avoid repeated construction
|
||||
IntegerType const zero = static_cast<IntegerType>( 0 );
|
||||
IntegerType const result = lcm_euclidean( a, b );
|
||||
|
||||
return ( result < zero ) ? -result : result;
|
||||
}
|
||||
|
||||
// Function objects to find the best way of computing GCD or LCM
|
||||
template < typename T >
|
||||
struct gcd_optimal_evaluator
|
||||
{
|
||||
template < bool IsSpecialized, bool IsSigned >
|
||||
struct helper
|
||||
{
|
||||
T operator ()( T const &a, T const &b )
|
||||
{
|
||||
return gcd_euclidean( a, b );
|
||||
}
|
||||
};
|
||||
|
||||
template < >
|
||||
struct helper< true, true >
|
||||
{
|
||||
T operator ()( T const &a, T const &b )
|
||||
{
|
||||
return gcd_integer( a, b );
|
||||
}
|
||||
};
|
||||
|
||||
T operator ()( T const &a, T const &b )
|
||||
{
|
||||
typedef ::std::numeric_limits<T> limits_type;
|
||||
|
||||
typedef helper<limits_type::is_specialized, limits_type::is_signed>
|
||||
helper_type;
|
||||
|
||||
helper_type solver;
|
||||
|
||||
return solver( a, b );
|
||||
}
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
struct lcm_optimal_evaluator
|
||||
{
|
||||
template < bool IsSpecialized, bool IsSigned >
|
||||
struct helper
|
||||
{
|
||||
T operator ()( T const &a, T const &b )
|
||||
{
|
||||
return lcm_euclidean( a, b );
|
||||
}
|
||||
};
|
||||
|
||||
template < >
|
||||
struct helper< true, true >
|
||||
{
|
||||
T operator ()( T const &a, T const &b )
|
||||
{
|
||||
return lcm_integer( a, b );
|
||||
}
|
||||
};
|
||||
|
||||
T operator ()( T const &a, T const &b )
|
||||
{
|
||||
typedef ::std::numeric_limits<T> limits_type;
|
||||
|
||||
typedef helper<limits_type::is_specialized, limits_type::is_signed>
|
||||
helper_type;
|
||||
|
||||
helper_type solver;
|
||||
|
||||
return solver( a, b );
|
||||
}
|
||||
};
|
||||
|
||||
// Functions to find the GCD or LCM in the best way
|
||||
template < typename T >
|
||||
inline
|
||||
gcd_optimal
|
||||
(
|
||||
T const & a,
|
||||
T const & b
|
||||
)
|
||||
{
|
||||
gcd_optimal_evaluator<T> solver;
|
||||
|
||||
return solver( a, b );
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
inline
|
||||
lcm_optimal
|
||||
(
|
||||
T const & a,
|
||||
T const & b
|
||||
)
|
||||
{
|
||||
lcm_optimal_evaluator<T> solver;
|
||||
|
||||
return solver( a, b );
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
// Compile-time greatest common divisor evaluator class declaration --------//
|
||||
|
||||
template < unsigned long Value1, unsigned long Value2 >
|
||||
struct static_gcd
|
||||
{
|
||||
BOOST_STATIC_CONSTANT( unsigned long, value
|
||||
= (detail::static_gcd_helper_t<Value1, Value2>::value) );
|
||||
|
||||
}; // boost::math::static_gcd
|
||||
|
||||
|
||||
// Compile-time least common multiple evaluator class declaration ----------//
|
||||
|
||||
template < unsigned long Value1, unsigned long Value2 >
|
||||
struct static_lcm
|
||||
{
|
||||
BOOST_STATIC_CONSTANT( unsigned long, value
|
||||
= (detail::static_lcm_helper_t<Value1, Value2>::value) );
|
||||
|
||||
}; // boost::math::static_lcm
|
||||
|
||||
|
||||
// Greatest common divisor evaluator member function definition ------------//
|
||||
|
||||
template < typename IntegerType >
|
||||
inline
|
||||
typename gcd_evaluator<IntegerType>::result_type
|
||||
gcd_evaluator<IntegerType>::operator ()
|
||||
(
|
||||
first_argument_type const & a,
|
||||
second_argument_type const & b
|
||||
) const
|
||||
{
|
||||
return detail::gcd_optimal( a, b );
|
||||
}
|
||||
|
||||
|
||||
// Least common multiple evaluator member function definition --------------//
|
||||
|
||||
template < typename IntegerType >
|
||||
inline
|
||||
typename lcm_evaluator<IntegerType>::result_type
|
||||
lcm_evaluator<IntegerType>::operator ()
|
||||
(
|
||||
first_argument_type const & a,
|
||||
second_argument_type const & b
|
||||
) const
|
||||
{
|
||||
return detail::lcm_optimal( a, b );
|
||||
}
|
||||
|
||||
|
||||
// Greatest common divisor and least common multiple function definitions --//
|
||||
|
||||
template < typename IntegerType >
|
||||
inline
|
||||
IntegerType
|
||||
gcd
|
||||
(
|
||||
IntegerType const & a,
|
||||
IntegerType const & b
|
||||
)
|
||||
{
|
||||
gcd_evaluator<IntegerType> solver;
|
||||
|
||||
return solver( a, b );
|
||||
}
|
||||
|
||||
template < typename IntegerType >
|
||||
inline
|
||||
IntegerType
|
||||
lcm
|
||||
(
|
||||
IntegerType const & a,
|
||||
IntegerType const & b
|
||||
)
|
||||
{
|
||||
lcm_evaluator<IntegerType> solver;
|
||||
|
||||
return solver( a, b );
|
||||
}
|
||||
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_MATH_COMMON_FACTOR_HPP
|
||||
95
include/boost/math_fwd.hpp
Normal file
95
include/boost/math_fwd.hpp
Normal file
@@ -0,0 +1,95 @@
|
||||
// Boost math_fwd.hpp header file ------------------------------------------//
|
||||
|
||||
// (C) Copyright boost.org 2001. 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.
|
||||
|
||||
#ifndef BOOST_MATH_FWD_HPP
|
||||
#define BOOST_MATH_FWD_HPP
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace math
|
||||
{
|
||||
|
||||
|
||||
// From <boost/math/quaternion.hpp> ----------------------------------------//
|
||||
|
||||
template < typename T >
|
||||
class quaternion;
|
||||
|
||||
template < >
|
||||
class quaternion< float >;
|
||||
template < >
|
||||
class quaternion< double >;
|
||||
template < >
|
||||
class quaternion< long double >;
|
||||
|
||||
// Also has many function templates (including operators)
|
||||
|
||||
|
||||
// From <boost/math/octonion.hpp> ------------------------------------------//
|
||||
|
||||
template < typename T >
|
||||
class octonion;
|
||||
|
||||
template < >
|
||||
class octonion< float >;
|
||||
template < >
|
||||
class octonion< double >;
|
||||
template < >
|
||||
class octonion< long double >;
|
||||
|
||||
// Also has many function templates (including operators)
|
||||
|
||||
|
||||
// From <boost/math/special_functions/acosh.hpp> ---------------------------//
|
||||
|
||||
// Only has function template
|
||||
|
||||
|
||||
// From <boost/math/special_functions/asinh.hpp> ---------------------------//
|
||||
|
||||
// Only has function template
|
||||
|
||||
|
||||
// From <boost/math/special_functions/atanh.hpp> ---------------------------//
|
||||
|
||||
// Only has function template
|
||||
|
||||
|
||||
// From <boost/math/special_functions/sinc.hpp> ----------------------------//
|
||||
|
||||
// Only has function templates
|
||||
|
||||
|
||||
// From <boost/math/special_functions/sinhc.hpp> ---------------------------//
|
||||
|
||||
// Only has function templates
|
||||
|
||||
|
||||
// From <boost/math/common_factor.hpp> -------------------------------------//
|
||||
|
||||
template < typename IntegerType >
|
||||
class gcd_evaluator;
|
||||
template < typename IntegerType >
|
||||
class lcm_evaluator;
|
||||
|
||||
template < unsigned long Value1, unsigned long Value2 >
|
||||
struct static_gcd;
|
||||
template < unsigned long Value1, unsigned long Value2 >
|
||||
struct static_lcm;
|
||||
|
||||
// Also has a couple of function templates
|
||||
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_MATH_FWD_HPP
|
||||
115
test/common_factor_test.cpp
Normal file
115
test/common_factor_test.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
// Boost GCD & LCM common_factor.hpp test program --------------------------//
|
||||
|
||||
// (C) Copyright Daryle Walker 2001. 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.
|
||||
|
||||
// Revision History
|
||||
// 07 Nov 2001 Initial version (Daryle Walker)
|
||||
|
||||
#define BOOST_INCLUDE_MAIN
|
||||
|
||||
#include <boost/config.hpp> // for BOOST_MSVC
|
||||
#include <boost/cstdlib.hpp> // for boost::exit_success
|
||||
#include <boost/math/common_factor.hpp> // for boost::math::gcd, etc.
|
||||
#include <boost/test/test_tools.hpp> // for main, BOOST_TEST
|
||||
|
||||
#include <iostream> // for std::cout (std::endl indirectly)
|
||||
|
||||
|
||||
// Control to determine what kind of built-in integers are used
|
||||
#ifndef CONTROL_INT_TYPE
|
||||
#define CONTROL_INT_TYPE int
|
||||
#endif
|
||||
|
||||
|
||||
// Main testing function
|
||||
int
|
||||
test_main
|
||||
(
|
||||
int , // "argc" is unused
|
||||
char * [] // "argv" is unused
|
||||
)
|
||||
{
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
#ifndef BOOST_MSVC
|
||||
using boost::math::gcd;
|
||||
using boost::math::static_gcd;
|
||||
using boost::math::lcm;
|
||||
using boost::math::static_lcm;
|
||||
#else
|
||||
using namespace boost::math;
|
||||
#endif
|
||||
|
||||
typedef CONTROL_INT_TYPE int_type;
|
||||
|
||||
// GCD tests
|
||||
cout << "Doing tests on gcd." << endl;
|
||||
|
||||
BOOST_TEST( gcd<int_type>( 1, -1) == 1 );
|
||||
BOOST_TEST( gcd<int_type>( -1, 1) == 1 );
|
||||
BOOST_TEST( gcd<int_type>( 1, 1) == 1 );
|
||||
BOOST_TEST( gcd<int_type>( -1, -1) == 1 );
|
||||
BOOST_TEST( gcd<int_type>( 0, 0) == 0 );
|
||||
BOOST_TEST( gcd<int_type>( 7, 0) == 7 );
|
||||
BOOST_TEST( gcd<int_type>( 0, 9) == 9 );
|
||||
BOOST_TEST( gcd<int_type>( -7, 0) == 7 );
|
||||
BOOST_TEST( gcd<int_type>( 0, -9) == 9 );
|
||||
BOOST_TEST( gcd<int_type>( 42, 30) == 6 );
|
||||
BOOST_TEST( gcd<int_type>( 6, -9) == 3 );
|
||||
BOOST_TEST( gcd<int_type>(-10, -10) == 10 );
|
||||
BOOST_TEST( gcd<int_type>(-25, -10) == 5 );
|
||||
BOOST_TEST( gcd<int_type>( 3, 7) == 1 );
|
||||
BOOST_TEST( gcd<int_type>( 8, 9) == 1 );
|
||||
BOOST_TEST( gcd<int_type>( 7, 49) == 7 );
|
||||
|
||||
cout << "Doing tests on static_gcd." << endl;
|
||||
|
||||
BOOST_TEST( (static_gcd< 1, 1>::value) == 1 );
|
||||
BOOST_TEST( (static_gcd< 0, 0>::value) == 0 );
|
||||
BOOST_TEST( (static_gcd< 7, 0>::value) == 7 );
|
||||
BOOST_TEST( (static_gcd< 0, 9>::value) == 9 );
|
||||
BOOST_TEST( (static_gcd<42, 30>::value) == 6 );
|
||||
BOOST_TEST( (static_gcd< 3, 7>::value) == 1 );
|
||||
BOOST_TEST( (static_gcd< 8, 9>::value) == 1 );
|
||||
BOOST_TEST( (static_gcd< 7, 49>::value) == 7 );
|
||||
|
||||
// LCM tests
|
||||
cout << "Doing tests on lcm." << endl;
|
||||
|
||||
BOOST_TEST( lcm<int_type>( 1, -1) == 1 );
|
||||
BOOST_TEST( lcm<int_type>( -1, 1) == 1 );
|
||||
BOOST_TEST( lcm<int_type>( 1, 1) == 1 );
|
||||
BOOST_TEST( lcm<int_type>( -1, -1) == 1 );
|
||||
BOOST_TEST( lcm<int_type>( 0, 0) == 0 );
|
||||
BOOST_TEST( lcm<int_type>( 6, 0) == 0 );
|
||||
BOOST_TEST( lcm<int_type>( 0, 7) == 0 );
|
||||
BOOST_TEST( lcm<int_type>( -5, 0) == 0 );
|
||||
BOOST_TEST( lcm<int_type>( 0, -4) == 0 );
|
||||
BOOST_TEST( lcm<int_type>( 18, 30) == 90 );
|
||||
BOOST_TEST( lcm<int_type>( -6, 9) == 18 );
|
||||
BOOST_TEST( lcm<int_type>(-10, -10) == 10 );
|
||||
BOOST_TEST( lcm<int_type>( 25, -10) == 50 );
|
||||
BOOST_TEST( lcm<int_type>( 3, 7) == 21 );
|
||||
BOOST_TEST( lcm<int_type>( 8, 9) == 72 );
|
||||
BOOST_TEST( lcm<int_type>( 7, 49) == 49 );
|
||||
|
||||
cout << "Doing tests on static_lcm." << endl;
|
||||
|
||||
BOOST_TEST( (static_lcm< 1, 1>::value) == 1 );
|
||||
BOOST_TEST( (static_lcm< 0, 0>::value) == 0 );
|
||||
BOOST_TEST( (static_lcm< 6, 0>::value) == 0 );
|
||||
BOOST_TEST( (static_lcm< 0, 7>::value) == 0 );
|
||||
BOOST_TEST( (static_lcm<18, 30>::value) == 90 );
|
||||
BOOST_TEST( (static_lcm< 3, 7>::value) == 21 );
|
||||
BOOST_TEST( (static_lcm< 8, 9>::value) == 72 );
|
||||
BOOST_TEST( (static_lcm< 7, 49>::value) == 49 );
|
||||
|
||||
return boost::exit_success;
|
||||
}
|
||||
Reference in New Issue
Block a user