2
0
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:
Dave Abrahams
2001-11-29 21:42:58 +00:00
parent 28650c0720
commit d199e37ac9
5 changed files with 1003 additions and 0 deletions

237
doc/common_factor.html Normal file
View File

@@ -0,0 +1,237 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<title>Boost GCD &amp; 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">&lt;boost/math/common_factor.hpp&gt;</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 &amp; LCM
Determination</a></li>
<li><a href="#ct_gcd_lcm">Compile-time GCD &amp; 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 &lt; typename IntegerType &gt;
class gcd_evaluator;
template &lt; typename IntegerType &gt;
class lcm_evaluator;
template &lt; typename IntegerType &gt;
IntegerType gcd( IntegerType const &amp;a, IntegerType const &amp;b );
template &lt; typename IntegerType &gt;
IntegerType lcm( IntegerType const &amp;a, IntegerType const &amp;b );
template &lt; unsigned long Value1, unsigned long Value2 &gt;
struct static_gcd;
template &lt; unsigned long Value1, unsigned long Value2 &gt;
struct static_lcm;
}
}
</pre></blockquote>
<h2><a name="gcd_obj">GCD Function Object</a></h2>
<blockquote><pre>
template &lt; typename IntegerType &gt;
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 &amp;a,
second_argument_type const &amp;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 &lt; typename IntegerType &gt;
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 &amp;a,
second_argument_type const &amp;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 &amp; LCM Determination</a></h2>
<blockquote><pre>
template &lt; typename IntegerType &gt;
IntegerType boost::math::gcd( IntegerType const &amp;a, IntegerType const &amp;b );
template &lt; typename IntegerType &gt;
IntegerType boost::math::lcm( IntegerType const &amp;a, IntegerType const &amp;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 &amp; LCM Determination</a></h2>
<blockquote><pre>
template &lt; unsigned long Value1, unsigned long Value2 &gt;
struct boost::math::static_gcd
{
static unsigned long const value = <em>implementation_defined</em>;
};
template &lt; unsigned long Value1, unsigned long Value2 &gt;
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 &lt;boost/math/common_factor.hpp&gt;
#include &lt;algorithm&gt;
#include &lt;iterator&gt;
int main()
{
using std::cout;
using std::endl;
cout &lt;&lt; &quot;The GCD and LCM of 6 and 15 are &quot;
&lt;&lt; boost::math::gcd(6, 15) &lt;&lt; &quot; and &quot;
&lt;&lt; boost::math::lcm(6, 15) &lt;&lt; &quot;, respectively.&quot;
&lt;&lt; endl;
cout &lt;&lt; &quot;The GCD and LCM of 8 and 9 are &quot;
&lt;&lt; boost::math::static_gcd&lt;8, 9&gt;::value
&lt;&lt; &quot; and &quot;
&lt;&lt; boost::math::static_lcm&lt;8, 9&gt;::value
&lt;&lt; &quot;, respectively.&quot; &lt;&lt; endl;
int a[] = { 4, 5, 6 }, b[] = { 7, 8, 9 }, c[3];
std::transform( a, a + 3, b, c, boost::math::gcd_evaluator&lt;int&gt;() );
std::copy( c, c + 3, std::ostream_iterator&lt;int&gt;(cout, &quot; &quot;) );
}
</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>&copy; 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
&quot;as is&quot; 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
View 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">&lt;boost/math_fwd.hpp&gt;</a></code>
</td>
<td valign="top">Forward declaration header.
</td>
<tr>
<td align="center">
<code><a href="../../../boost/math/octonion.hpp">&lt;boost/math/octonion.hpp&gt;</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">&lt;boost/math/quaternion.hpp&gt;</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">&lt;boost/math/special_functions/acosh.hpp&gt;</a></code><br>
<code><a href="../../boost/math/special_functions/asinh.hpp">&lt;boost/math/special_functions/asinh.hpp&gt;</a></code><br>
<code><a href="../../boost/math/special_functions/atanh.hpp">&lt;boost/math/special_functions/atanh.hpp&gt;</a></code><br>
<code><a href="../../boost/math/special_functions/sinc.hpp">&lt;boost/math/special_functions/sinc.hpp&gt;</a></code><br>
<code><a href="../../boost/math/special_functions/sinhc.hpp">&lt;boost/math/special_functions/sinhc.hpp&gt;</a></code><br>
<br><a href="special_functions/index.htm">documentation</a>
</td>
<td valign="top">&quot;Special&quot; mathematical function
templates.
</td>
</tr>
<tr>
<td align="center">
<code><a href="../../../boost/math/common_factor.hpp">&lt;boost/math/common_factor.hpp&gt;</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>

View 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

View 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
View 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;
}