summaryrefslogtreecommitdiff
path: root/libs/integer
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2015-04-08 03:09:47 +0000
committer <>2015-05-05 14:37:32 +0000
commitf2541bb90af059680aa7036f315f052175999355 (patch)
treea5b214744b256f07e1dc2bd7273035a7808c659f /libs/integer
parented232fdd34968697a68783b3195b1da4226915b5 (diff)
downloadboost-tarball-master.tar.gz
Imported from /home/lorry/working-area/delta_boost-tarball/boost_1_58_0.tar.bz2.HEADboost_1_58_0master
Diffstat (limited to 'libs/integer')
-rw-r--r--libs/integer/doc/gcd/math-gcd.qbk247
-rw-r--r--libs/integer/meta/libraries.json12
-rw-r--r--libs/integer/test/Jamfile.v22
-rw-r--r--libs/integer/test/common_factor_test.cpp473
-rw-r--r--libs/integer/test/fail_uint_65.cpp13
-rw-r--r--libs/integer/test/integer_test.cpp1
6 files changed, 748 insertions, 0 deletions
diff --git a/libs/integer/doc/gcd/math-gcd.qbk b/libs/integer/doc/gcd/math-gcd.qbk
new file mode 100644
index 000000000..4d3edd6b2
--- /dev/null
+++ b/libs/integer/doc/gcd/math-gcd.qbk
@@ -0,0 +1,247 @@
+
+[mathpart gcd_lcm Integer Utilities (Greatest Common Divisor and Least Common Multiple)]
+
+[section Introduction]
+
+The class and function templates in <boost/math/common_factor.hpp>
+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.
+
+[endsect]
+
+[section Synopsis]
+
+ 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 );
+
+ typedef ``['see-below]`` static_gcd_type;
+
+ template < static_gcd_type Value1, static_gcd_type Value2 >
+ struct static_gcd;
+ template < static_gcd_type Value1, static_gcd_type Value2 >
+ struct static_lcm;
+
+ }
+ }
+
+[endsect]
+
+[section GCD Function Object]
+
+[*Header: ] [@../../../../boost/math/common_factor_rt.hpp <boost/math/common_factor_rt.hpp>]
+
+ 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;
+ };
+
+The boost::math::gcd_evaluator 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 IntegerType 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.
+
+This function object class template is used in the corresponding version of
+the GCD function template. If a numeric type wants to customize evaluations
+of its greatest common divisors, then the type should specialize on the
+gcd_evaluator class template.
+
+[endsect]
+
+[section LCM Function Object]
+
+[*Header: ] [@../../../../boost/math/common_factor_rt.hpp <boost/math/common_factor_rt.hpp>]
+
+ 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;
+ };
+
+The boost::math::lcm_evaluator 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 IntegerType 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.
+
+This function object class template is used in the corresponding version
+of the LCM function template. If a numeric type wants to customize
+evaluations of its least common multiples, then the type should
+specialize on the lcm_evaluator class template.
+
+[endsect]
+
+[section:run_time Run-time GCD & LCM Determination]
+
+[*Header: ] [@../../../../boost/math/common_factor_rt.hpp <boost/math/common_factor_rt.hpp>]
+
+ 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 );
+
+The boost::math::gcd function template returns the greatest common
+(nonnegative) divisor of the two integers passed to it.
+The boost::math::lcm function template returns the least common
+(nonnegative) multiple of the two integers passed to it.
+The function templates are parameterized on the function arguments'
+IntegerType, which is also the return type. Internally, these function
+templates use an object of the corresponding version of the
+gcd_evaluator and lcm_evaluator class templates, respectively.
+
+[endsect]
+
+[section:compile_time Compile time GCD and LCM determination]
+
+[*Header: ] [@../../../../boost/math/common_factor_ct.hpp <boost/math/common_factor_ct.hpp>]
+
+ typedef ``['unspecified]`` static_gcd_type;
+
+ template < static_gcd_type Value1, static_gcd_type Value2 >
+ struct boost::math::static_gcd : public mpl::integral_c<static_gcd_type, implementation_defined>
+ {
+ };
+
+ template < static_gcd_type Value1, static_gcd_type Value2 >
+ struct boost::math::static_lcm : public mpl::integral_c<static_gcd_type, implementation_defined>
+ {
+ };
+
+The type `static_gcd_type` is the widest unsigned-integer-type that is supported
+for use in integral-constant-expressions by the compiler. Usually this
+the same type as `boost::uintmax_t`, but may fall back to being `unsigned long`
+for some older compilers.
+
+The boost::math::static_gcd and boost::math::static_lcm class templates
+take two value-based template parameters of the ['static_gcd_type] type
+and inherit from the type `boost::mpl::integral_c`.
+Inherited from the base class, they have a member /value/
+that 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 `static_gcd_type`.
+
+[h3 Example]
+
+ #include <boost/math/common_factor.hpp>
+ #include <algorithm>
+ #include <iterator>
+ #include <iostream>
+
+ 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, " ") );
+ }
+
+[endsect]
+
+[section:gcd_header Header <boost/math/common_factor.hpp>]
+
+This header simply includes the headers
+[@../../../../boost/math/common_factor_ct.hpp <boost/math/common_factor_ct.hpp>]
+and [@../../../../boost/math/common_factor_rt.hpp <boost/math/common_factor_rt.hpp>].
+
+Note this is a legacy header: it used to contain the actual implementation,
+but the compile-time and run-time facilities
+were moved to separate headers (since they were independent of each other).
+
+[endsect]
+
+[section:demo Demonstration Program]
+
+The program [@../../../../libs/math/test/common_factor_test.cpp common_factor_test.cpp] 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.)
+
+[endsect]
+
+[section Rationale]
+
+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.
+
+[endsect]
+
+[section:gcd_history History]
+
+* 13 May 2013 Moved into main Boost.Math Quickbook documentation.
+* 17 Dec 2005: Converted documentation to Quickbook Format.
+* 2 Jul 2002: Compile-time and run-time items separated to new headers.
+* 7 Nov 2001: Initial version
+
+[endsect]
+
+[section:gcd_credits Credits]
+
+The author of the Boost compilation of GCD and LCM computations is
+Daryle Walker. The code was prompted by existing code hiding in the
+implementations of Paul Moore's rational library and Steve Cleary's
+pool library. The code had updates by Helmut Zeisel.
+
+[endsect]
+
+[endmathpart]
+
+[/
+Copyright 2005, 2013 Daryle Walker.
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt).
+]
+
+
diff --git a/libs/integer/meta/libraries.json b/libs/integer/meta/libraries.json
new file mode 100644
index 000000000..6345c37fc
--- /dev/null
+++ b/libs/integer/meta/libraries.json
@@ -0,0 +1,12 @@
+{
+ "key": "integer",
+ "name": "Integer",
+ "description": "The organization of boost integer headers and classes is designed to take advantage of <stdint.h> types from the 1999 C standard without resorting to undefined behavior in terms of the 1998 C++ standard. The header <boost/cstdint.hpp> makes the standard integer types safely available in namespace boost without placing any names in namespace std.",
+ "category": [
+ "Math"
+ ],
+ "authors": "",
+ "maintainers": [
+ "Daryle Walker <darylew -at- hotmail.com>"
+ ]
+}
diff --git a/libs/integer/test/Jamfile.v2 b/libs/integer/test/Jamfile.v2
index 8a60c3680..e3b5be1d4 100644
--- a/libs/integer/test/Jamfile.v2
+++ b/libs/integer/test/Jamfile.v2
@@ -25,4 +25,6 @@ test-suite integer
[ compile-fail fail_uint_exact.cpp ]
[ compile-fail fail_uint_fast.cpp ]
[ compile-fail fail_uint_least.cpp ]
+ [ compile-fail fail_uint_65.cpp ]
+ [ run common_factor_test.cpp ]
;
diff --git a/libs/integer/test/common_factor_test.cpp b/libs/integer/test/common_factor_test.cpp
new file mode 100644
index 000000000..81ffc47cd
--- /dev/null
+++ b/libs/integer/test/common_factor_test.cpp
@@ -0,0 +1,473 @@
+// Boost GCD & LCM common_factor.hpp test program --------------------------//
+
+// (C) Copyright Daryle Walker 2001, 2006.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for most recent version including documentation.
+
+// Revision History
+// 01 Dec 2006 Various fixes for old compilers (Joaquin M Lopez Munoz)
+// 10 Nov 2006 Make long long and __int64 mutually exclusive (Daryle Walker)
+// 04 Nov 2006 Use more built-in numeric types, binary-GCD (Daryle Walker)
+// 03 Nov 2006 Use custom numeric types (Daryle Walker)
+// 02 Nov 2006 Change to Boost.Test's unit test system (Daryle Walker)
+// 07 Nov 2001 Initial version (Daryle Walker)
+
+#define BOOST_TEST_MAIN "Boost.Math GCD & LCM unit tests"
+
+#include <boost/integer/common_factor.hpp>
+
+#include <boost/config.hpp> // for BOOST_MSVC, etc.
+#include <boost/detail/workaround.hpp>
+#include <boost/operators.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+#include <istream> // for std::basic_istream
+#include <limits> // for std::numeric_limits
+#include <ostream> // for std::basic_ostream
+
+
+namespace {
+
+// TODO: add polynominal/non-real type; especially after any switch to the
+// binary-GCD algorithm for built-in types
+
+// Custom integer class (template)
+template < typename IntType, int ID = 0 >
+class my_wrapped_integer
+ : private ::boost::shiftable1<my_wrapped_integer<IntType, ID>,
+ ::boost::operators<my_wrapped_integer<IntType, ID> > >
+{
+ // Helper type-aliases
+ typedef my_wrapped_integer self_type;
+ typedef IntType self_type::* bool_type;
+
+ // Member data
+ IntType v_;
+
+public:
+ // Template parameters
+ typedef IntType int_type;
+
+ BOOST_STATIC_CONSTANT(int,id = ID);
+
+ // Lifetime management (use automatic destructor and copy constructor)
+ my_wrapped_integer( int_type const &v = int_type() ) : v_( v ) {}
+
+ // Accessors
+ int_type value() const { return this->v_; }
+
+ // Operators (use automatic copy assignment)
+ operator bool_type() const { return this->v_ ? &self_type::v_ : 0; }
+
+ self_type & operator ++() { ++this->v_; return *this; }
+ self_type & operator --() { --this->v_; return *this; }
+
+ self_type operator ~() const { return self_type( ~this->v_ ); }
+ self_type operator !() const { return self_type( !this->v_ ); }
+ self_type operator +() const { return self_type( +this->v_ ); }
+ self_type operator -() const { return self_type( -this->v_ ); }
+
+ bool operator <( self_type const &r ) const { return this->v_ < r.v_; }
+ bool operator ==( self_type const &r ) const { return this->v_ == r.v_; }
+
+ self_type &operator *=(self_type const &r) {this->v_ *= r.v_; return *this;}
+ self_type &operator /=(self_type const &r) {this->v_ /= r.v_; return *this;}
+ self_type &operator %=(self_type const &r) {this->v_ %= r.v_; return *this;}
+ self_type &operator +=(self_type const &r) {this->v_ += r.v_; return *this;}
+ self_type &operator -=(self_type const &r) {this->v_ -= r.v_; return *this;}
+ self_type &operator<<=(self_type const &r){this->v_ <<= r.v_; return *this;}
+ self_type &operator>>=(self_type const &r){this->v_ >>= r.v_; return *this;}
+ self_type &operator &=(self_type const &r) {this->v_ &= r.v_; return *this;}
+ self_type &operator |=(self_type const &r) {this->v_ |= r.v_; return *this;}
+ self_type &operator ^=(self_type const &r) {this->v_ ^= r.v_; return *this;}
+
+ // Input & output
+ friend std::istream & operator >>( std::istream &i, self_type &x )
+ { return i >> x.v_; }
+
+ friend std::ostream & operator <<( std::ostream &o, self_type const &x )
+ { return o << x.v_; }
+
+}; // my_wrapped_integer
+
+template < typename IntType, int ID >
+my_wrapped_integer<IntType, ID> abs( my_wrapped_integer<IntType, ID> const &x )
+{ return ( x < my_wrapped_integer<IntType, ID>(0) ) ? -x : +x; }
+
+typedef my_wrapped_integer<int> MyInt1;
+typedef my_wrapped_integer<unsigned> MyUnsigned1;
+typedef my_wrapped_integer<int, 1> MyInt2;
+typedef my_wrapped_integer<unsigned, 1> MyUnsigned2;
+
+// Without these explicit instantiations, MSVC++ 6.5/7.0 does not find
+// some friend operators in certain contexts.
+MyInt1 dummy1;
+MyUnsigned1 dummy2;
+MyInt2 dummy3;
+MyUnsigned2 dummy4;
+
+} // namespace
+
+#define BOOST_NO_MACRO_EXPAND /**/
+
+// Specialize numeric_limits for _some_ of our types
+namespace std
+{
+
+template < >
+class numeric_limits< MyInt1 >
+{
+ typedef MyInt1::int_type int_type;
+ typedef numeric_limits<int_type> limits_type;
+
+public:
+ BOOST_STATIC_CONSTANT(bool, is_specialized = limits_type::is_specialized);
+
+ static MyInt1 min BOOST_NO_MACRO_EXPAND() throw() { return (limits_type::min)(); }
+ static MyInt1 max BOOST_NO_MACRO_EXPAND() throw() { return (limits_type::max)(); }
+
+ BOOST_STATIC_CONSTANT(int, digits = limits_type::digits);
+ BOOST_STATIC_CONSTANT(int, digits10 = limits_type::digits10);
+#ifndef BOOST_NO_CXX11_NUMERIC_LIMITS
+ BOOST_STATIC_CONSTANT(int, max_digits10 = limits_type::max_digits10);
+#endif
+ BOOST_STATIC_CONSTANT(bool, is_signed = limits_type::is_signed);
+ BOOST_STATIC_CONSTANT(bool, is_integer = limits_type::is_integer);
+ BOOST_STATIC_CONSTANT(bool, is_exact = limits_type::is_exact);
+ BOOST_STATIC_CONSTANT(int, radix = limits_type::radix);
+ static MyInt1 epsilon() throw() { return limits_type::epsilon(); }
+ static MyInt1 round_error() throw() { return limits_type::round_error(); }
+
+ BOOST_STATIC_CONSTANT(int, min_exponent = limits_type::min_exponent);
+ BOOST_STATIC_CONSTANT(int, min_exponent10 = limits_type::min_exponent10);
+ BOOST_STATIC_CONSTANT(int, max_exponent = limits_type::max_exponent);
+ BOOST_STATIC_CONSTANT(int, max_exponent10 = limits_type::max_exponent10);
+
+ BOOST_STATIC_CONSTANT(bool, has_infinity = limits_type::has_infinity);
+ BOOST_STATIC_CONSTANT(bool, has_quiet_NaN = limits_type::has_quiet_NaN);
+ BOOST_STATIC_CONSTANT(bool, has_signaling_NaN = limits_type::has_signaling_NaN);
+ BOOST_STATIC_CONSTANT(float_denorm_style, has_denorm = limits_type::has_denorm);
+ BOOST_STATIC_CONSTANT(bool, has_denorm_loss = limits_type::has_denorm_loss);
+
+ static MyInt1 infinity() throw() { return limits_type::infinity(); }
+ static MyInt1 quiet_NaN() throw() { return limits_type::quiet_NaN(); }
+ static MyInt1 signaling_NaN() throw() {return limits_type::signaling_NaN();}
+ static MyInt1 denorm_min() throw() { return limits_type::denorm_min(); }
+
+ BOOST_STATIC_CONSTANT(bool, is_iec559 = limits_type::is_iec559);
+ BOOST_STATIC_CONSTANT(bool, is_bounded = limits_type::is_bounded);
+ BOOST_STATIC_CONSTANT(bool, is_modulo = limits_type::is_modulo);
+
+ BOOST_STATIC_CONSTANT(bool, traps = limits_type::traps);
+ BOOST_STATIC_CONSTANT(bool, tinyness_before = limits_type::tinyness_before);
+ BOOST_STATIC_CONSTANT(float_round_style, round_style = limits_type::round_style);
+
+}; // std::numeric_limits<MyInt1>
+
+template < >
+class numeric_limits< MyUnsigned1 >
+{
+ typedef MyUnsigned1::int_type int_type;
+ typedef numeric_limits<int_type> limits_type;
+
+public:
+ BOOST_STATIC_CONSTANT(bool, is_specialized = limits_type::is_specialized);
+
+ static MyUnsigned1 min BOOST_NO_MACRO_EXPAND() throw() { return (limits_type::min)(); }
+ static MyUnsigned1 max BOOST_NO_MACRO_EXPAND() throw() { return (limits_type::max)(); }
+
+ BOOST_STATIC_CONSTANT(int, digits = limits_type::digits);
+ BOOST_STATIC_CONSTANT(int, digits10 = limits_type::digits10);
+#ifndef BOOST_NO_CXX11_NUMERIC_LIMITS
+ BOOST_STATIC_CONSTANT(int, max_digits10 = limits_type::max_digits10);
+#endif
+ BOOST_STATIC_CONSTANT(bool, is_signed = limits_type::is_signed);
+ BOOST_STATIC_CONSTANT(bool, is_integer = limits_type::is_integer);
+ BOOST_STATIC_CONSTANT(bool, is_exact = limits_type::is_exact);
+ BOOST_STATIC_CONSTANT(int, radix = limits_type::radix);
+ static MyUnsigned1 epsilon() throw() { return limits_type::epsilon(); }
+ static MyUnsigned1 round_error() throw(){return limits_type::round_error();}
+
+ BOOST_STATIC_CONSTANT(int, min_exponent = limits_type::min_exponent);
+ BOOST_STATIC_CONSTANT(int, min_exponent10 = limits_type::min_exponent10);
+ BOOST_STATIC_CONSTANT(int, max_exponent = limits_type::max_exponent);
+ BOOST_STATIC_CONSTANT(int, max_exponent10 = limits_type::max_exponent10);
+
+ BOOST_STATIC_CONSTANT(bool, has_infinity = limits_type::has_infinity);
+ BOOST_STATIC_CONSTANT(bool, has_quiet_NaN = limits_type::has_quiet_NaN);
+ BOOST_STATIC_CONSTANT(bool, has_signaling_NaN = limits_type::has_signaling_NaN);
+ BOOST_STATIC_CONSTANT(float_denorm_style, has_denorm = limits_type::has_denorm);
+ BOOST_STATIC_CONSTANT(bool, has_denorm_loss = limits_type::has_denorm_loss);
+
+ static MyUnsigned1 infinity() throw() { return limits_type::infinity(); }
+ static MyUnsigned1 quiet_NaN() throw() { return limits_type::quiet_NaN(); }
+ static MyUnsigned1 signaling_NaN() throw()
+ { return limits_type::signaling_NaN(); }
+ static MyUnsigned1 denorm_min() throw(){ return limits_type::denorm_min(); }
+
+ BOOST_STATIC_CONSTANT(bool, is_iec559 = limits_type::is_iec559);
+ BOOST_STATIC_CONSTANT(bool, is_bounded = limits_type::is_bounded);
+ BOOST_STATIC_CONSTANT(bool, is_modulo = limits_type::is_modulo);
+
+ BOOST_STATIC_CONSTANT(bool, traps = limits_type::traps);
+ BOOST_STATIC_CONSTANT(bool, tinyness_before = limits_type::tinyness_before);
+ BOOST_STATIC_CONSTANT(float_round_style, round_style = limits_type::round_style);
+
+}; // std::numeric_limits<MyUnsigned1>
+
+#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
+// MSVC 6.0 lacks operator<< for __int64, see
+// http://support.microsoft.com/default.aspx?scid=kb;en-us;168440
+
+inline ostream& operator<<(ostream& os, __int64 i)
+{
+ char buf[20];
+ sprintf(buf,"%I64d", i);
+ os << buf;
+ return os;
+}
+
+inline ostream& operator<<(ostream& os, unsigned __int64 i)
+{
+ char buf[20];
+ sprintf(buf,"%I64u", i);
+ os << buf;
+ return os;
+}
+#endif
+
+} // namespace std
+
+// GCD tests
+
+// GCD on signed integer types
+template< class T > void gcd_int_test() // signed_test_types
+{
+ using boost::integer::gcd;
+
+ // Originally from Boost.Rational tests
+ BOOST_TEST_EQ( gcd<T>( 1, -1), static_cast<T>( 1) );
+ BOOST_TEST_EQ( gcd<T>( -1, 1), static_cast<T>( 1) );
+ BOOST_TEST_EQ( gcd<T>( 1, 1), static_cast<T>( 1) );
+ BOOST_TEST_EQ( gcd<T>( -1, -1), static_cast<T>( 1) );
+ BOOST_TEST_EQ( gcd<T>( 0, 0), static_cast<T>( 0) );
+ BOOST_TEST_EQ( gcd<T>( 7, 0), static_cast<T>( 7) );
+ BOOST_TEST_EQ( gcd<T>( 0, 9), static_cast<T>( 9) );
+ BOOST_TEST_EQ( gcd<T>( -7, 0), static_cast<T>( 7) );
+ BOOST_TEST_EQ( gcd<T>( 0, -9), static_cast<T>( 9) );
+ BOOST_TEST_EQ( gcd<T>( 42, 30), static_cast<T>( 6) );
+ BOOST_TEST_EQ( gcd<T>( 6, -9), static_cast<T>( 3) );
+ BOOST_TEST_EQ( gcd<T>(-10, -10), static_cast<T>(10) );
+ BOOST_TEST_EQ( gcd<T>(-25, -10), static_cast<T>( 5) );
+ BOOST_TEST_EQ( gcd<T>( 3, 7), static_cast<T>( 1) );
+ BOOST_TEST_EQ( gcd<T>( 8, 9), static_cast<T>( 1) );
+ BOOST_TEST_EQ( gcd<T>( 7, 49), static_cast<T>( 7) );
+}
+
+// GCD on unmarked signed integer type
+void gcd_unmarked_int_test()
+{
+ using boost::integer::gcd;
+
+ // The regular signed-integer GCD function performs the unsigned version,
+ // then does an absolute-value on the result. Signed types that are not
+ // marked as such (due to no std::numeric_limits specialization) may be off
+ // by a sign.
+ BOOST_TEST_EQ( abs(gcd<MyInt2>( 1, -1 )), MyInt2( 1) );
+ BOOST_TEST_EQ( abs(gcd<MyInt2>( -1, 1 )), MyInt2( 1) );
+ BOOST_TEST_EQ( abs(gcd<MyInt2>( 1, 1 )), MyInt2( 1) );
+ BOOST_TEST_EQ( abs(gcd<MyInt2>( -1, -1 )), MyInt2( 1) );
+ BOOST_TEST_EQ( abs(gcd<MyInt2>( 0, 0 )), MyInt2( 0) );
+ BOOST_TEST_EQ( abs(gcd<MyInt2>( 7, 0 )), MyInt2( 7) );
+ BOOST_TEST_EQ( abs(gcd<MyInt2>( 0, 9 )), MyInt2( 9) );
+ BOOST_TEST_EQ( abs(gcd<MyInt2>( -7, 0 )), MyInt2( 7) );
+ BOOST_TEST_EQ( abs(gcd<MyInt2>( 0, -9 )), MyInt2( 9) );
+ BOOST_TEST_EQ( abs(gcd<MyInt2>( 42, 30 )), MyInt2( 6) );
+ BOOST_TEST_EQ( abs(gcd<MyInt2>( 6, -9 )), MyInt2( 3) );
+ BOOST_TEST_EQ( abs(gcd<MyInt2>( -10, -10 )), MyInt2(10) );
+ BOOST_TEST_EQ( abs(gcd<MyInt2>( -25, -10 )), MyInt2( 5) );
+ BOOST_TEST_EQ( abs(gcd<MyInt2>( 3, 7 )), MyInt2( 1) );
+ BOOST_TEST_EQ( abs(gcd<MyInt2>( 8, 9 )), MyInt2( 1) );
+ BOOST_TEST_EQ( abs(gcd<MyInt2>( 7, 49 )), MyInt2( 7) );
+}
+
+// GCD on unsigned integer types
+template< class T > void gcd_unsigned_test() // unsigned_test_types
+{
+ using boost::integer::gcd;
+
+ // Note that unmarked types (i.e. have no std::numeric_limits
+ // specialization) are treated like non/unsigned types
+ BOOST_TEST_EQ( gcd<T>( 1u, 1u), static_cast<T>( 1u) );
+ BOOST_TEST_EQ( gcd<T>( 0u, 0u), static_cast<T>( 0u) );
+ BOOST_TEST_EQ( gcd<T>( 7u, 0u), static_cast<T>( 7u) );
+ BOOST_TEST_EQ( gcd<T>( 0u, 9u), static_cast<T>( 9u) );
+ BOOST_TEST_EQ( gcd<T>(42u, 30u), static_cast<T>( 6u) );
+ BOOST_TEST_EQ( gcd<T>( 3u, 7u), static_cast<T>( 1u) );
+ BOOST_TEST_EQ( gcd<T>( 8u, 9u), static_cast<T>( 1u) );
+ BOOST_TEST_EQ( gcd<T>( 7u, 49u), static_cast<T>( 7u) );
+}
+
+// GCD at compile-time
+void gcd_static_test()
+{
+ using boost::integer::static_gcd;
+
+ BOOST_TEST_EQ( (static_gcd< 1, 1>::value), 1 );
+ BOOST_TEST_EQ( (static_gcd< 0, 0>::value), 0 );
+ BOOST_TEST_EQ( (static_gcd< 7, 0>::value), 7 );
+ BOOST_TEST_EQ( (static_gcd< 0, 9>::value), 9 );
+ BOOST_TEST_EQ( (static_gcd<42, 30>::value), 6 );
+ BOOST_TEST_EQ( (static_gcd< 3, 7>::value), 1 );
+ BOOST_TEST_EQ( (static_gcd< 8, 9>::value), 1 );
+ BOOST_TEST_EQ( (static_gcd< 7, 49>::value), 7 );
+}
+
+// TODO: non-built-in signed and unsigned integer tests, with and without
+// numeric_limits specialization; polynominal tests; note any changes if
+// built-ins switch to binary-GCD algorithm
+
+
+// LCM tests
+
+// LCM on signed integer types
+template< class T > void lcm_int_test() // signed_test_types
+{
+ using boost::integer::lcm;
+
+ // Originally from Boost.Rational tests
+ BOOST_TEST_EQ( lcm<T>( 1, -1), static_cast<T>( 1) );
+ BOOST_TEST_EQ( lcm<T>( -1, 1), static_cast<T>( 1) );
+ BOOST_TEST_EQ( lcm<T>( 1, 1), static_cast<T>( 1) );
+ BOOST_TEST_EQ( lcm<T>( -1, -1), static_cast<T>( 1) );
+ BOOST_TEST_EQ( lcm<T>( 0, 0), static_cast<T>( 0) );
+ BOOST_TEST_EQ( lcm<T>( 6, 0), static_cast<T>( 0) );
+ BOOST_TEST_EQ( lcm<T>( 0, 7), static_cast<T>( 0) );
+ BOOST_TEST_EQ( lcm<T>( -5, 0), static_cast<T>( 0) );
+ BOOST_TEST_EQ( lcm<T>( 0, -4), static_cast<T>( 0) );
+ BOOST_TEST_EQ( lcm<T>( 18, 30), static_cast<T>(90) );
+ BOOST_TEST_EQ( lcm<T>( -6, 9), static_cast<T>(18) );
+ BOOST_TEST_EQ( lcm<T>(-10, -10), static_cast<T>(10) );
+ BOOST_TEST_EQ( lcm<T>( 25, -10), static_cast<T>(50) );
+ BOOST_TEST_EQ( lcm<T>( 3, 7), static_cast<T>(21) );
+ BOOST_TEST_EQ( lcm<T>( 8, 9), static_cast<T>(72) );
+ BOOST_TEST_EQ( lcm<T>( 7, 49), static_cast<T>(49) );
+}
+
+// LCM on unmarked signed integer type
+void lcm_unmarked_int_test()
+{
+ using boost::integer::lcm;
+
+ // The regular signed-integer LCM function performs the unsigned version,
+ // then does an absolute-value on the result. Signed types that are not
+ // marked as such (due to no std::numeric_limits specialization) may be off
+ // by a sign.
+ BOOST_TEST_EQ( abs(lcm<MyInt2>( 1, -1 )), MyInt2( 1) );
+ BOOST_TEST_EQ( abs(lcm<MyInt2>( -1, 1 )), MyInt2( 1) );
+ BOOST_TEST_EQ( abs(lcm<MyInt2>( 1, 1 )), MyInt2( 1) );
+ BOOST_TEST_EQ( abs(lcm<MyInt2>( -1, -1 )), MyInt2( 1) );
+ BOOST_TEST_EQ( abs(lcm<MyInt2>( 0, 0 )), MyInt2( 0) );
+ BOOST_TEST_EQ( abs(lcm<MyInt2>( 6, 0 )), MyInt2( 0) );
+ BOOST_TEST_EQ( abs(lcm<MyInt2>( 0, 7 )), MyInt2( 0) );
+ BOOST_TEST_EQ( abs(lcm<MyInt2>( -5, 0 )), MyInt2( 0) );
+ BOOST_TEST_EQ( abs(lcm<MyInt2>( 0, -4 )), MyInt2( 0) );
+ BOOST_TEST_EQ( abs(lcm<MyInt2>( 18, 30 )), MyInt2(90) );
+ BOOST_TEST_EQ( abs(lcm<MyInt2>( -6, 9 )), MyInt2(18) );
+ BOOST_TEST_EQ( abs(lcm<MyInt2>( -10, -10 )), MyInt2(10) );
+ BOOST_TEST_EQ( abs(lcm<MyInt2>( 25, -10 )), MyInt2(50) );
+ BOOST_TEST_EQ( abs(lcm<MyInt2>( 3, 7 )), MyInt2(21) );
+ BOOST_TEST_EQ( abs(lcm<MyInt2>( 8, 9 )), MyInt2(72) );
+ BOOST_TEST_EQ( abs(lcm<MyInt2>( 7, 49 )), MyInt2(49) );
+}
+
+// LCM on unsigned integer types
+template< class T > void lcm_unsigned_test() // unsigned_test_types
+{
+ using boost::integer::lcm;
+
+ // Note that unmarked types (i.e. have no std::numeric_limits
+ // specialization) are treated like non/unsigned types
+ BOOST_TEST_EQ( lcm<T>( 1u, 1u), static_cast<T>( 1u) );
+ BOOST_TEST_EQ( lcm<T>( 0u, 0u), static_cast<T>( 0u) );
+ BOOST_TEST_EQ( lcm<T>( 6u, 0u), static_cast<T>( 0u) );
+ BOOST_TEST_EQ( lcm<T>( 0u, 7u), static_cast<T>( 0u) );
+ BOOST_TEST_EQ( lcm<T>(18u, 30u), static_cast<T>(90u) );
+ BOOST_TEST_EQ( lcm<T>( 3u, 7u), static_cast<T>(21u) );
+ BOOST_TEST_EQ( lcm<T>( 8u, 9u), static_cast<T>(72u) );
+ BOOST_TEST_EQ( lcm<T>( 7u, 49u), static_cast<T>(49u) );
+}
+
+// LCM at compile-time
+void lcm_static_test()
+{
+ using boost::integer::static_lcm;
+
+ BOOST_TEST_EQ( (static_lcm< 1, 1>::value), 1 );
+ BOOST_TEST_EQ( (static_lcm< 0, 0>::value), 0 );
+ BOOST_TEST_EQ( (static_lcm< 6, 0>::value), 0 );
+ BOOST_TEST_EQ( (static_lcm< 0, 7>::value), 0 );
+ BOOST_TEST_EQ( (static_lcm<18, 30>::value), 90 );
+ BOOST_TEST_EQ( (static_lcm< 3, 7>::value), 21 );
+ BOOST_TEST_EQ( (static_lcm< 8, 9>::value), 72 );
+ BOOST_TEST_EQ( (static_lcm< 7, 49>::value), 49 );
+}
+
+// TODO: see GCD to-do
+
+// main
+
+// Various types to test with each GCD/LCM
+
+#define TEST_SIGNED_( test ) \
+ test<signed char>(); \
+ test<short>(); \
+ test<int>(); \
+ test<long>(); \
+ test<MyInt1>();
+
+#ifdef BOOST_HAS_LONG_LONG
+# define TEST_SIGNED( test ) \
+ TEST_SIGNED_( test ) \
+ test<boost::long_long_type>();
+#elif defined(BOOST_HAS_MS_INT64)
+# define TEST_SIGNED( test ) \
+ TEST_SIGNED_( test ) \
+ test<__int64>();
+#endif
+
+#define TEST_UNSIGNED_( test ) \
+ test<unsigned char>(); \
+ test<unsigned short>(); \
+ test<unsigned>(); \
+ test<unsigned long>(); \
+ test<MyUnsigned1>(); \
+ test<MyUnsigned2>();
+
+#ifdef BOOST_HAS_LONG_LONG
+# define TEST_UNSIGNED( test ) \
+ TEST_UNSIGNED_( test ) \
+ test<boost::ulong_long_type>();
+#elif defined(BOOST_HAS_MS_INT64)
+# define TEST_UNSIGNED( test ) \
+ TEST_UNSIGNED_( test ) \
+ test<unsigned __int64>();
+#endif
+
+int main()
+{
+ TEST_SIGNED( gcd_int_test )
+ gcd_unmarked_int_test();
+ TEST_UNSIGNED( gcd_unsigned_test )
+ gcd_static_test();
+
+ TEST_SIGNED( lcm_int_test )
+ lcm_unmarked_int_test();
+ TEST_UNSIGNED( lcm_unsigned_test )
+ lcm_static_test();
+
+ return boost::report_errors();
+}
diff --git a/libs/integer/test/fail_uint_65.cpp b/libs/integer/test/fail_uint_65.cpp
new file mode 100644
index 000000000..76b485e8d
--- /dev/null
+++ b/libs/integer/test/fail_uint_65.cpp
@@ -0,0 +1,13 @@
+// Copyright John Maddock 2012.
+// Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/integer.hpp>
+#include <iostream>
+
+int main()
+{
+ std::cout << std::numeric_limits<boost::uint_t<65>::least>::digits;
+ return 0;
+}
diff --git a/libs/integer/test/integer_test.cpp b/libs/integer/test/integer_test.cpp
index fd9e6df2a..a79db2d54 100644
--- a/libs/integer/test/integer_test.cpp
+++ b/libs/integer/test/integer_test.cpp
@@ -18,6 +18,7 @@
#include <boost/detail/lightweight_test.hpp> // for main, BOOST_TEST
#include <boost/integer.hpp> // for boost::int_t, boost::uint_t
#include <boost/type_traits/is_same.hpp>
+#include <boost/mpl/bool.hpp> // for mpl::true_ and false_
#include <climits> // for ULONG_MAX, LONG_MAX, LONG_MIN
#include <iostream> // for std::cout (std::endl indirectly)