mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-11-04 05:50:31 -05:00 
			
		
		
		
	
		
			
	
	
		
			126 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			126 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
								 | 
							
								//  (C) Copyright Jeremy Murphy 2015.
							 | 
						||
| 
								 | 
							
								//  Use, modification and distribution are subject to 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/config.hpp>
							 | 
						||
| 
								 | 
							
								#define BOOST_TEST_MAIN
							 | 
						||
| 
								 | 
							
								#include <boost/array.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/math/common_factor_rt.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/mpl/list.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/test/test_case_template.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/test/unit_test.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/multiprecision/cpp_int.hpp>
							 | 
						||
| 
								 | 
							
								#include <utility>
							 | 
						||
| 
								 | 
							
								#include <boost/random.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Naive implmentation, any fancy versions we create should always agree with this:
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								template <class T>
							 | 
						||
| 
								 | 
							
								typename boost::enable_if_c<std::numeric_limits<T>::is_signed, T>::type unsigned_abs(T v) { return v < 0 ? -v : v; }
							 | 
						||
| 
								 | 
							
								template <class T>
							 | 
						||
| 
								 | 
							
								typename boost::disable_if_c<std::numeric_limits<T>::is_signed, T>::type unsigned_abs(T v) { return v; }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <class T>
							 | 
						||
| 
								 | 
							
								T euclid_textbook(T a, T b)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   using std::swap;
							 | 
						||
| 
								 | 
							
								   if(a < b)
							 | 
						||
| 
								 | 
							
								      swap(a, b);
							 | 
						||
| 
								 | 
							
								   while(b)
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      T t = b;
							 | 
						||
| 
								 | 
							
								      b = a % b;
							 | 
						||
| 
								 | 
							
								      a = t;
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								   return unsigned_abs(a);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef boost::mpl::list<boost::int32_t
							 | 
						||
| 
								 | 
							
								#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1500)
							 | 
						||
| 
								 | 
							
								   , boost::int64_t, boost::multiprecision::cpp_int
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								> signed_integral_test_types;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								BOOST_AUTO_TEST_CASE_TEMPLATE(test_zero, T, signed_integral_test_types)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    T a = boost::math::gcd(static_cast<T>(2), static_cast<T>(0));
							 | 
						||
| 
								 | 
							
								    BOOST_CHECK_EQUAL(a, static_cast<T>(2));
							 | 
						||
| 
								 | 
							
								    a = boost::math::gcd(static_cast<T>(0), static_cast<T>(2));
							 | 
						||
| 
								 | 
							
								    BOOST_CHECK_EQUAL(a, static_cast<T>(2));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								BOOST_AUTO_TEST_CASE_TEMPLATE(test_signed, T, signed_integral_test_types)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    T a = boost::math::gcd(static_cast<T>(-40902), static_cast<T>(-24140));
							 | 
						||
| 
								 | 
							
								    BOOST_CHECK_EQUAL(a, static_cast<T>(34));
							 | 
						||
| 
								 | 
							
								    a = boost::math::gcd(static_cast<T>(40902), static_cast<T>(24140));
							 | 
						||
| 
								 | 
							
								    BOOST_CHECK_EQUAL(a, static_cast<T>(34));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef boost::mpl::list<boost::uint32_t
							 | 
						||
| 
								 | 
							
								#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1500)
							 | 
						||
| 
								 | 
							
								   , boost::uint64_t, boost::multiprecision::uint256_t
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								> unsigned_integral_test_types;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								BOOST_AUTO_TEST_CASE_TEMPLATE(test_unsigned, T, unsigned_integral_test_types)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    T a = boost::math::gcd(static_cast<T>(40902), static_cast<T>(24140));
							 | 
						||
| 
								 | 
							
								    BOOST_CHECK_EQUAL(a, static_cast<T>(34));
							 | 
						||
| 
								 | 
							
								    a = boost::math::gcd(static_cast<T>(1836311903), static_cast<T>(2971215073)); // 46th and 47th Fibonacci numbers. 47th is prime.
							 | 
						||
| 
								 | 
							
								    BOOST_CHECK_EQUAL(a, static_cast<T>(1));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef boost::mpl::list<boost::int32_t, boost::int64_t> short_signed_integral_test_types;
							 | 
						||
| 
								 | 
							
								typedef boost::mpl::list<boost::uint32_t, boost::uint64_t> short_unsigned_integral_test_types;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								BOOST_AUTO_TEST_CASE_TEMPLATE(signed_random_test, T, short_signed_integral_test_types)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   boost::random::mt19937 gen;
							 | 
						||
| 
								 | 
							
								   boost::uniform_int<T> dist((std::numeric_limits<T>::min)(), (std::numeric_limits<T>::max)());
							 | 
						||
| 
								 | 
							
								   for(unsigned i = 0; i < 100000; ++i)
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      T u = dist(gen);
							 | 
						||
| 
								 | 
							
								      T v = dist(gen);
							 | 
						||
| 
								 | 
							
								      BOOST_CHECK_EQUAL(boost::math::gcd(u, v), euclid_textbook(u, v));
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								BOOST_AUTO_TEST_CASE_TEMPLATE(test_random_unsigned, T, short_unsigned_integral_test_types)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   boost::random::mt19937 gen;
							 | 
						||
| 
								 | 
							
								   boost::uniform_int<T> dist((std::numeric_limits<T>::min)(), (std::numeric_limits<T>::max)());
							 | 
						||
| 
								 | 
							
								   for(unsigned i = 0; i < 100000; ++i)
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      T u = dist(gen);
							 | 
						||
| 
								 | 
							
								      T v = dist(gen);
							 | 
						||
| 
								 | 
							
								      BOOST_CHECK_EQUAL(boost::math::gcd(u, v), euclid_textbook(u, v));
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								BOOST_AUTO_TEST_CASE_TEMPLATE(test_gcd_range, T, unsigned_integral_test_types)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    std::vector<T> a;
							 | 
						||
| 
								 | 
							
								    typedef typename std::vector<T>::iterator I;
							 | 
						||
| 
								 | 
							
								    std::pair<T, I> d;
							 | 
						||
| 
								 | 
							
								    a.push_back(40902);
							 | 
						||
| 
								 | 
							
								    d = boost::math::gcd_range(a.begin(), a.end());
							 | 
						||
| 
								 | 
							
								    BOOST_CHECK(d == std::make_pair(T(40902), a.end()));
							 | 
						||
| 
								 | 
							
								    a.push_back(24140);
							 | 
						||
| 
								 | 
							
								    d = boost::math::gcd_range(a.begin(), a.end());
							 | 
						||
| 
								 | 
							
								    BOOST_CHECK(d == std::make_pair(T(34), a.end()));
							 | 
						||
| 
								 | 
							
								    a.push_back(85);
							 | 
						||
| 
								 | 
							
								    d = boost::math::gcd_range(a.begin(), a.end());
							 | 
						||
| 
								 | 
							
								    BOOST_CHECK(d == std::make_pair(T(17), a.end()));
							 | 
						||
| 
								 | 
							
								    a.push_back(23893);
							 | 
						||
| 
								 | 
							
								    d = boost::math::gcd_range(a.begin(), a.end());
							 | 
						||
| 
								 | 
							
								    BOOST_CHECK(d == std::make_pair(T(1), a.end()));
							 | 
						||
| 
								 | 
							
								    a.push_back(1024);
							 | 
						||
| 
								 | 
							
								    d = boost::math::gcd_range(a.begin(), a.end());
							 | 
						||
| 
								 | 
							
								    BOOST_CHECK(d == std::make_pair(T(1), a.end() - 1));
							 | 
						||
| 
								 | 
							
								}
							 |