Skip to content

Commit ca62e93

Browse files
committed
Separate the examples. Begin testing via Boost.Test and Multiprecision.
1 parent 7a66428 commit ca62e93

19 files changed

+1340
-4
lines changed

examples/example001_mul_div.cpp

1.51 KB
Binary file not shown.

examples/example001a_div_mod.cpp

436 Bytes
Binary file not shown.

examples/example002_shl_shr.cpp

1.47 KB
Binary file not shown.

examples/example003_sqrt.cpp

1.31 KB
Binary file not shown.

examples/example004_rootk_pow.cpp

1.53 KB
Binary file not shown.

examples/example005_powm.cpp

1.52 KB
Binary file not shown.

examples/example006_gcd.cpp

1.39 KB
Binary file not shown.

examples/example007_random_generator.cpp

+13-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
///////////////////////////////////////////////////////////////////
2-
// Copyright Christopher Kormanyos 2018. //
2+
// Copyright Christopher Kormanyos 2018 -2019. //
33
// Distributed under the Boost Software License, //
44
// Version 1.0. (See accompanying file LICENSE_1_0.txt //
55
// or copy at http://www.boost.org/LICENSE_1_0.txt) //
@@ -10,7 +10,7 @@
1010

1111
#include <wide_integer/generic_template_uintwide_t.h>
1212

13-
int main()
13+
bool wide_integer::example007_random_generator()
1414
{
1515
bool result_is_ok = true;
1616

@@ -65,5 +65,16 @@ int main()
6565
result_is_ok &= (n == "103688572923999614683274548975545468793316802532402235278881055800362044212101");
6666
}
6767

68+
return result_is_ok;
69+
}
70+
71+
#if !defined(WIDE_INTEGER_DISABLE_MAIN_IN_STANDALONE_EXAMPLES)
72+
73+
int main()
74+
{
75+
const bool result_is_ok = wide_integer::example007_random_generator();
76+
6877
std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl;
6978
}
79+
80+
#endif

examples/example008_miller_rabin_prime.cpp

+18-2
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
///////////////////////////////////////////////////////////////////
2-
// Copyright Christopher Kormanyos 2018. //
2+
// Copyright Christopher Kormanyos 2018 -2019. //
33
// Distributed under the Boost Software License, //
44
// Version 1.0. (See accompanying file LICENSE_1_0.txt //
55
// or copy at http://www.boost.org/LICENSE_1_0.txt) //
66
///////////////////////////////////////////////////////////////////
77

8+
// This Miller-Rabin primality test is loosely based on
9+
// an adaptation of some code from Boost.Multiprecision.
10+
// The Boost.Multiprecision code can be found here:
11+
// https://www.boost.org/doc/libs/1_68_0/libs/multiprecision/doc/html/boost_multiprecision/tut/primetest.html
12+
813
#include <cstdint>
914
#include <iomanip>
1015
#include <iostream>
1116

1217
#include <wide_integer/generic_template_uintwide_t.h>
1318

14-
int main()
19+
bool wide_integer::example008_miller_rabin_prime()
1520
{
1621
using wide_integer_type = wide_integer::generic_template::uintwide_t<256U>;
1722
using distribution_type = wide_integer::generic_template::uniform_int_distribution<wide_integer_type::my_digits, typename wide_integer_type::value_type>;
@@ -58,5 +63,16 @@ int main()
5863
}
5964
}
6065

66+
return result_is_ok;
67+
}
68+
69+
#if !defined(WIDE_INTEGER_DISABLE_MAIN_IN_STANDALONE_EXAMPLES)
70+
71+
int main()
72+
{
73+
const bool result_is_ok = wide_integer::example008_miller_rabin_prime();
74+
6175
std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl;
6276
}
77+
78+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
///////////////////////////////////////////////////////////////////
2+
// Copyright Christopher Kormanyos 2018 -2019. //
3+
// Distributed under the Boost Software License, //
4+
// Version 1.0. (See accompanying file LICENSE_1_0.txt //
5+
// or copy at http://www.boost.org/LICENSE_1_0.txt) //
6+
///////////////////////////////////////////////////////////////////
7+
8+
#include <algorithm>
9+
#include <chrono>
10+
#include <cstddef>
11+
#include <cstdint>
12+
#include <iomanip>
13+
#include <iostream>
14+
#include <limits>
15+
#include <iterator>
16+
#include <vector>
17+
18+
#include <wide_integer/generic_template_uintwide_t.h>
19+
20+
constexpr unsigned wide_integer_test9_digits2 = 1024U;
21+
22+
#define WIDE_INTEGER_USE_GENERIC_UINTWIDE_T
23+
//#define WIDE_INTEGER_USE_BOOST_MULTIPRECISION
24+
25+
#if defined(WIDE_INTEGER_USE_BOOST_MULTIPRECISION)
26+
#include <boost/multiprecision/cpp_int.hpp>
27+
#endif
28+
29+
class random_pcg32_fast_base
30+
{
31+
protected:
32+
using itype = std::uint64_t;
33+
34+
static constexpr bool is_mcg = false;
35+
36+
public:
37+
virtual ~random_pcg32_fast_base() = default;
38+
39+
protected:
40+
explicit random_pcg32_fast_base(const itype = itype()) { }
41+
42+
random_pcg32_fast_base(const random_pcg32_fast_base&) = default;
43+
44+
random_pcg32_fast_base& operator=(const random_pcg32_fast_base&) = default;
45+
46+
template<typename ArithmeticType>
47+
static ArithmeticType rotr(const ArithmeticType& value_being_shifted,
48+
const std::size_t bits_to_shift)
49+
{
50+
const std::size_t left_shift_amount =
51+
std::numeric_limits<ArithmeticType>::digits - bits_to_shift;
52+
53+
const ArithmeticType part1 = ((bits_to_shift > 0U) ? ArithmeticType(value_being_shifted >> bits_to_shift) : value_being_shifted);
54+
const ArithmeticType part2 = ((bits_to_shift > 0U) ? ArithmeticType(value_being_shifted << left_shift_amount) : 0U);
55+
56+
return ArithmeticType(part1 | part2);
57+
}
58+
59+
template<typename xtype,
60+
typename itype>
61+
struct xsh_rr_mixin
62+
{
63+
static xtype output(const itype internal_value)
64+
{
65+
using bitcount_t = std::size_t;
66+
67+
constexpr bitcount_t bits = bitcount_t(sizeof(itype) * 8U);
68+
constexpr bitcount_t xtypebits = bitcount_t(sizeof(xtype) * 8U);
69+
constexpr bitcount_t sparebits = bits - xtypebits;
70+
constexpr bitcount_t wantedopbits = ((xtypebits >= 128U) ? 7U
71+
: ((xtypebits >= 64U) ? 6U
72+
: ((xtypebits >= 32U) ? 5U
73+
: ((xtypebits >= 16U) ? 4U
74+
: 3U))));
75+
76+
constexpr bitcount_t opbits = ((sparebits >= wantedopbits) ? wantedopbits : sparebits);
77+
constexpr bitcount_t amplifier = wantedopbits - opbits;
78+
constexpr bitcount_t mask = (1ULL << opbits) - 1U;
79+
constexpr bitcount_t topspare = opbits;
80+
constexpr bitcount_t bottomspare = sparebits - topspare;
81+
constexpr bitcount_t xshift = (topspare + xtypebits) / 2U;
82+
83+
const bitcount_t rot =
84+
((opbits != 0U) ? (bitcount_t(internal_value >> (bits - opbits)) & mask)
85+
: 0U);
86+
87+
const bitcount_t amprot = (rot << amplifier) & mask;
88+
89+
const itype internal_value_xor = internal_value ^ itype(internal_value >> xshift);
90+
91+
const xtype result = rotr(xtype(internal_value_xor >> bottomspare), amprot);
92+
93+
return result;
94+
}
95+
};
96+
};
97+
98+
class random_pcg32_fast : public random_pcg32_fast_base
99+
{
100+
private:
101+
static constexpr itype default_multiplier = static_cast<itype>(6364136223846793005ULL);
102+
static constexpr itype default_increment = static_cast<itype>(1442695040888963407ULL);
103+
104+
public:
105+
using result_type = std::uint32_t;
106+
107+
static constexpr itype default_seed = static_cast<itype>(0xCAFEF00DD15EA5E5ULL);
108+
109+
explicit random_pcg32_fast(const itype state = default_seed)
110+
: random_pcg32_fast_base(state),
111+
my_inc (default_increment),
112+
my_state(is_mcg ? state | itype(3U) : bump(state + increment())) { }
113+
114+
random_pcg32_fast(const random_pcg32_fast& other)
115+
: random_pcg32_fast_base(other),
116+
my_inc (other.my_inc),
117+
my_state(other.my_state) { }
118+
119+
virtual ~random_pcg32_fast() = default;
120+
121+
random_pcg32_fast& operator=(const random_pcg32_fast& other)
122+
{
123+
static_cast<void>(random_pcg32_fast_base::operator=(other));
124+
125+
if(this != &other)
126+
{
127+
my_inc = other.my_inc;
128+
my_state = other.my_state;
129+
}
130+
131+
return *this;
132+
}
133+
134+
void seed(const itype state = default_seed)
135+
{
136+
my_inc = default_increment;
137+
138+
my_state = (is_mcg ? state | itype(3U) : bump(state + increment()));
139+
}
140+
141+
result_type operator()()
142+
{
143+
const result_type value =
144+
xsh_rr_mixin<result_type, itype>::output(base_generate0());
145+
146+
return value;
147+
}
148+
149+
private:
150+
itype my_inc;
151+
itype my_state;
152+
153+
itype multiplier() const
154+
{
155+
return default_multiplier;
156+
}
157+
158+
itype increment() const
159+
{
160+
return default_increment;
161+
}
162+
163+
itype bump(const itype state)
164+
{
165+
return itype(state * multiplier()) + increment();
166+
}
167+
168+
itype base_generate0()
169+
{
170+
const itype old_state = my_state;
171+
172+
my_state = bump(my_state);
173+
174+
return old_state;
175+
}
176+
};
177+
178+
179+
template<typename UnsignedIntegralIteratorType,
180+
typename RandomEngineType>
181+
void get_random_big_uint(RandomEngineType& rng, UnsignedIntegralIteratorType it_out)
182+
{
183+
using local_random_value_type = typename RandomEngineType::result_type;
184+
185+
using local_uint_type = typename std::iterator_traits<UnsignedIntegralIteratorType>::value_type;
186+
187+
constexpr std::size_t digits_of_uint___type = static_cast<std::size_t>(std::numeric_limits<local_uint_type>::digits);
188+
constexpr std::size_t digits_of_random_type = static_cast<std::size_t>(std::numeric_limits<local_random_value_type>::digits);
189+
190+
local_random_value_type next_random = rng();
191+
192+
*it_out = next_random;
193+
194+
for(std::size_t i = digits_of_random_type; i < digits_of_uint___type; i += digits_of_random_type)
195+
{
196+
(*it_out) <<= digits_of_random_type;
197+
198+
next_random = rng();
199+
200+
(*it_out) |= next_random;
201+
}
202+
}
203+
204+
#if defined(WIDE_INTEGER_USE_BOOST_MULTIPRECISION)
205+
using big_uint_backend_type =
206+
boost::multiprecision::cpp_int_backend<wide_integer_test9_digits2,
207+
wide_integer_test9_digits2,
208+
boost::multiprecision::unsigned_magnitude>;
209+
210+
using big_uint_type = boost::multiprecision::number<big_uint_backend_type>;
211+
#endif
212+
213+
#if defined(WIDE_INTEGER_USE_GENERIC_UINTWIDE_T)
214+
using big_uint_type = wide_integer::generic_template::uintwide_t<wide_integer_test9_digits2>;
215+
#endif
216+
217+
namespace local
218+
{
219+
std::vector<big_uint_type> a(64U);
220+
std::vector<big_uint_type> b(a.size());
221+
}
222+
223+
bool wide_integer::example009_compare_mul_with_boost()
224+
{
225+
random_pcg32_fast rng;
226+
227+
rng.seed(std::clock());
228+
229+
for(auto i = 0U; i < local::a.size(); ++i)
230+
{
231+
get_random_big_uint(rng, local::a.begin() + i);
232+
get_random_big_uint(rng, local::b.begin() + i);
233+
}
234+
235+
std::size_t count = 0U;
236+
237+
float total_time = 0.0F;
238+
239+
const std::clock_t start = std::clock();
240+
241+
do
242+
{
243+
const std::size_t index = count % local::a.size();
244+
245+
local::a[index] * local::b[index];
246+
247+
++count;
248+
}
249+
while((total_time = (float(std::clock() - start) / float(CLOCKS_PER_SEC))) < 10.0F);
250+
251+
// Boost.Multiprecision 1.71
252+
// bits: 16384, kops_per_sec: 4.7
253+
// bits: 32768, kops_per_sec: 1.2
254+
// bits: 65536, kops_per_sec: 0.3
255+
// bits: 131072, kops_per_sec: 0.075
256+
// bits: 262144, kops_per_sec: 0.019
257+
// bits: 524288, kops_per_sec: 0.0047
258+
259+
// Boost.Multiprecision + kara mult
260+
// bits: 16384, kops_per_sec: 4.8
261+
// bits: 32768, kops_per_sec: 1.6
262+
// bits: 65536, kops_per_sec: 0.5
263+
// bits: 131072, kops_per_sec: 0.15
264+
// bits: 262144, kops_per_sec: 0.043
265+
// bits: 524288, kops_per_sec: 0.011
266+
267+
const float kops_per_sec = (float(count) / total_time) / 1000.0F;
268+
269+
std::cout << "bits: "
270+
<< std::numeric_limits<big_uint_type>::digits
271+
<< ", kops_per_sec: "
272+
<< kops_per_sec
273+
<< count << std::endl;
274+
275+
const bool result_is_ok = (kops_per_sec > 1.0F);
276+
277+
return result_is_ok;
278+
}
279+
280+
#if !defined(WIDE_INTEGER_DISABLE_MAIN_IN_STANDALONE_EXAMPLES)
281+
282+
int main()
283+
{
284+
const bool result_is_ok = wide_integer::example009_compare_mul_with_boost();
285+
286+
std::cout << "result_is_ok: " << std::boolalpha << result_is_ok << std::endl;
287+
}
288+
289+
#endif

0 commit comments

Comments
 (0)