From 3db2d7cb7166cecfdace146d8ecbecf51cbc4861 Mon Sep 17 00:00:00 2001 From: "Justinas V. Daugmaudis" Date: Thu, 31 Aug 2017 10:09:45 +0300 Subject: [PATCH 1/8] Initial QRNG commit --- doc/Jamfile.v2 | 6 + doc/concepts.qbk | 64 + doc/random.qbk | 5 + .../random/detail/gray_coded_qrng_base.hpp | 103 ++ include/boost/random/detail/qrng_base.hpp | 203 +++ include/boost/random/faure.hpp | 367 ++++++ include/boost/random/niederreiter_base2.hpp | 389 ++++++ include/boost/random/sobol.hpp | 1118 +++++++++++++++++ test/Jamfile.v2 | 4 + test/faure_validate.cpp | 375 ++++++ test/niederreiter_base2_validade.cpp | 372 ++++++ test/sobol_validate.cpp | 371 ++++++ 12 files changed, 3377 insertions(+) create mode 100644 include/boost/random/detail/gray_coded_qrng_base.hpp create mode 100644 include/boost/random/detail/qrng_base.hpp create mode 100644 include/boost/random/faure.hpp create mode 100644 include/boost/random/niederreiter_base2.hpp create mode 100644 include/boost/random/sobol.hpp create mode 100644 test/faure_validate.cpp create mode 100644 test/niederreiter_base2_validade.cpp create mode 100644 test/sobol_validate.cpp diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 1a985a0..20b4de1 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -27,6 +27,7 @@ doxygen_files = discrete_distribution exponential_distribution extreme_value_distribution + faure fisher_f_distribution gamma_distribution generate_canonical @@ -42,6 +43,7 @@ doxygen_files = mersenne_twister negative_binomial_distribution non_central_chi_squared_distribution + niederreiter_base2 normal_distribution piecewise_constant_distribution piecewise_linear_distribution @@ -52,6 +54,7 @@ doxygen_files = seed_seq shuffle_order # shuffle_output + sobol student_t_distribution subtract_with_carry taus88 @@ -107,6 +110,9 @@ doxygen reference : rand48=\"@xmlonly rand48 @endxmlonly\" \\ mt11213b=\"@xmlonly mt11213b @endxmlonly\" \\ mt19937=\"@xmlonly mt19937 @endxmlonly\" \\ + niederreiter_base2=\"@xmlonly niederreiter_base2 @endxmlonly\" \\ + sobol=\"@xmlonly sobol @endxmlonly\" \\ + faure=\"@xmlonly faure @endxmlonly\" \\ ecuyer1988=\"@xmlonly ecuyer1988 @endxmlonly\" \\ lagged_fibonacci607=\"@xmlonly lagged_fibonacci607 @endxmlonly\" \\ lagged_fibonacci44497=\"@xmlonly lagged_fibonacci44497 @endxmlonly\" \\ diff --git a/doc/concepts.qbk b/doc/concepts.qbk index 0e1a6de..84de047 100644 --- a/doc/concepts.qbk +++ b/doc/concepts.qbk @@ -199,6 +199,70 @@ the generator, for example to re-run a test suite at a later time.] [endsect] +[section Quasi-Random Number Generator] + +A quasi-random number generator is a __UniformRandomNumberGenerator which +provides a deterministic sequence of quasi-random numbers, based on some +algorithm and internal state. [classref boost::random::niederreiter_base2 +Niederreiter Base 2] generator is an example of such a [qrng quasi-random +number generator]. The "quasi" modifier is used to denote more clearly that the +values produced by such a generator are neither random nor pseudo-random, but +they form a low discrepancy sequence. The intuitive idea is that a low discrepancy +sequence is more evenly distributed than a pseudo random sequence would be. +For example, if we generate a low discrepancy sequence of 2D points on a square, +this square would be covered more evenly, and the number of points falling to any +part of the square would be proportional to the number of points in the whole square. +Such sequences share some properties of random variables and in certain applications +such as the quasi-Monte Carlo method their lower discrepancy is an important advantage. + +[note Quasi-random sequences are known to give efficient numerical integration +rules in many Bayesian statistical problems where the posterior distribution can be +transformed into periodic functions on the n-dimensional hypercube.] + +Harold Niederreiter gives an extensive overview on random number generation +and quasi-Monte Carlo methods in his book "Random number generation and +quasi-Monte Carlo methods, Society for Industrial and Applied Mathematics, 1992". + +In addition to the __UniformRandomNumberGenerator requirements, +a quasi-random number generator has some additional requirements. In the +following table, `X` denotes a quasi-random number generator class, and `v` is +a const value of `X`. + +[table QuasiRandomNumberGenerator requirements + [[expression] [return type] [pre/post-condition]] + [[`X::dimension()`] [std::size_t] [the dimension of quasi-random domain. It must be no less than 1. + The return value of this function shall not change during the lifetime of the object.]] + ] + +[note The `operator()` returns a successive element of an n-dimensional (n = `X::dimension()`) vector +at each invocation. When all elements are exhausted, `operator()` begins anew with the starting +element of a subsequent n-dimensional vector.] + +Classes which model a quasi-random number generator shall also model +__EqualityComparable, i.e. implement `operator==`. Two quasi-random number +generators are defined to be /equivalent/ if they both return an identical +sequence of numbers starting from a given state. + +Classes which model a quasi-random number generator shall also model the +__Streamable concept, i.e. implement `operator<<` and `operator>>`. +`operator<<` writes all current state of the quasi-random number generator +to the given `ostream` so that `operator>>` can restore the state at a later +time. The state shall be written in a platform-independent manner, but it is +assumed that the `locales` used for writing and reading be the same. The +quasi-random number generator with the restored state and the original at +the just-written state shall be equivalent. + +Classes which model a quasi-random number generator should also model the +__CopyConstructible and __Assignable concepts. However, note that the +sequences of the original and the copy are strongly correlated (in fact, +they are identical), which may make them unsuitable for some problem domains. +Thus, copying quasi-random number generators is discouraged; they should +always be passed by (non-const) reference. + +The classes __niederreiter_base2, __sobol, __faure are models for a quasi-random number generator. + +[endsect] + [section Seed Sequence] A SeedSeq represents a sequence of values that can be used to diff --git a/doc/random.qbk b/doc/random.qbk index fd7a06e..637c39b 100644 --- a/doc/random.qbk +++ b/doc/random.qbk @@ -13,6 +13,7 @@ [template sup[text]''''''[text]''''''] [template prng[text] [link boost_random.reference.concepts.pseudo_random_number_generator [text]]] +[template qrng[text] [link boost_random.reference.concepts.quasi_random_number_generator [text]]] [template concepts[text] [link boost_random.reference.concepts [text]]] [template generators[text] [link boost_random.reference.generators [text]]] [template distributions[text] [link boost_random.reference.distributions [text]]] @@ -20,6 +21,7 @@ [def __NumberGenerator [link boost_random.reference.concepts.number_generator NumberGenerator]] [def __UniformRandomNumberGenerator [link boost_random.reference.concepts.uniform_random_number_generator UniformRandomNumberGenerator]] [def __PseudoRandomNumberGenerator [link boost_random.reference.concepts.pseudo_random_number_generator PseudoRandomNumberGenerator]] +[def __QuasiRandomNumberGenerator [link boost_random.reference.concepts.quasi_random_number_generator QuasiRandomNumberGenerator]] [def __SeedSeq [link boost_random.reference.concepts.seed_sequence SeedSeq]] [def __CopyConstructible [@boost:/doc/html/CopyConstructible.html CopyConstructible]] @@ -64,6 +66,9 @@ [def __ranlux64_4_01 [classref boost::random::ranlux64_4_01 ranlux64_4_01]] [def __ranlux24 [classref boost::random::ranlux24 ranlux24]] [def __ranlux48 [classref boost::random::ranlux48 ranlux48]] +[def __niederreiter_base2 [classref boost::random::niederreiter_base2 niederreiter_base2]] +[def __sobol [classref boost::random::sobol sobol]] +[def __faure [classref boost::random::faure faure]] [def __uniform_smallint [classref boost::random::uniform_smallint uniform_smallint]] [def __uniform_int_distribution [classref boost::random::uniform_int_distribution uniform_int_distribution]] diff --git a/include/boost/random/detail/gray_coded_qrng_base.hpp b/include/boost/random/detail/gray_coded_qrng_base.hpp new file mode 100644 index 0000000..d568887 --- /dev/null +++ b/include/boost/random/detail/gray_coded_qrng_base.hpp @@ -0,0 +1,103 @@ +/* boost random/detail/gray_coded_qrng_base.hpp header file + * + * Copyright Justinas Vygintas Daugmaudis 2010-2017 + * 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) + */ + +#ifndef BOOST_RANDOM_DETAIL_GRAY_CODED_QRNG_BASE_HPP +#define BOOST_RANDOM_DETAIL_GRAY_CODED_QRNG_BASE_HPP + +#include + +// Prerequisite headers for bitscan to work +#include +#include +#include +#include // find_lsb + +//!\file +//!Describes the gray-coded quasi-random number generator base class template. + +namespace boost { +namespace random { + +namespace detail { + +template +class gray_coded_qrng_base : public qrng_base +{ +private: + typedef gray_coded_qrng_base self_t; + typedef qrng_base base_t; + + // The base needs to access modifying member f-ns, and we + // don't want these functions to be available for the public use + friend class qrng_base; + +public: + typedef typename LatticeT::value_type result_type; + + explicit gray_coded_qrng_base(std::size_t dimension) + : base_t(dimension) + {} + + // default copy c-tor is fine + + // default assignment operator is fine + +protected: + void seed(std::size_t init, const char *msg) + { + this->curr_elem = 0; + if (init != this->seq_count) + { + base_t::derived().seed(); + + this->seq_count = init; + init ^= (init / 2); + for (int r = 0; init != 0; ++r, init >>= 1) + { + if (init & 1) + update_quasi(r, msg); + } + } + } + +private: + // Compute next state for this QRNG + void compute_next() + { + compute_seq(this->seq_count++); + } + + void compute_seq(std::size_t cnt) + { + // Find the position of the least-significant zero in sequence count. + // This is the bit that changes in the Gray-code representation as + // the count is advanced. + int r = multiprecision::detail::find_lsb(~cnt); + update_quasi(r, "compute_seq"); + } + + void update_quasi(int r, const char* msg) + { + if (r < LatticeT::bit_count) + { + // Calculate the next state. + for (std::size_t i = 0; i != this->dimension(); ++i) + this->quasi_state[i] ^= this->lattice(r, i); + } + else + { + boost::throw_exception( std::overflow_error(msg) ); + } + } +}; + +}} // namespace detail::random + +} // namespace boost + +#endif // BOOST_RANDOM_DETAIL_GRAY_CODED_QRNG_BASE_HPP diff --git a/include/boost/random/detail/qrng_base.hpp b/include/boost/random/detail/qrng_base.hpp new file mode 100644 index 0000000..cbf5ded --- /dev/null +++ b/include/boost/random/detail/qrng_base.hpp @@ -0,0 +1,203 @@ +/* boost random/detail/quasi_random_number_generator_base.hpp header file + * + * Copyright Justinas Vygintas Daugmaudis 2010-2017 + * 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) + */ + +#ifndef BOOST_RANDOM_DETAIL_QRNG_BASE_HPP +#define BOOST_RANDOM_DETAIL_QRNG_BASE_HPP + +#include +#include + +#include +#include + +#include + +#include + +//!\file +//!Describes the quasi-random number generator base class template. + +namespace boost { +namespace random { + +namespace detail { + +template +class qrng_base +{ +public: + typedef typename LatticeT::value_type result_type; + + explicit qrng_base(std::size_t dimension) + // Guard against invalid dimensions before creating the lattice + : lattice(prevent_zero_dimension(dimension)) + , quasi_state(dimension) + { + derived().seed(); + } + + // default copy c-tor is fine + + // default assignment operator is fine + + //!Returns: The dimension of of the quasi-random domain. + //! + //!Throws: nothing. + std::size_t dimension() const { return quasi_state.size(); } + + //!Requirements: *this is mutable. + //! + //!Returns: Returns a successive element of an s-dimensional + //!(s = X::dimension()) vector at each invocation. When all elements are + //!exhausted, X::operator() begins anew with the starting element of a + //!subsequent s-dimensional vector. + //! + //!Throws: overflow_error. + result_type operator()() + { + return curr_elem != dimension() ? load_cached(): next_state(); + } + + //!Fills a range with quasi-random values. + template void generate(Iter first, Iter last) + { + for (; first != last; ++first) + *first = this->operator()(); + } + + //!Requirements: *this is mutable. + //! + //!Effects: Advances *this state as if z consecutive + //!X::operator() invocations were executed. + //! + //!Throws: overflow_error. + void discard(std::size_t z) + { + const std::size_t dimension_value = dimension(); + + std::size_t vec_n = z / dimension_value; + std::size_t elem_n = z - vec_n * dimension_value; // z % Dimension + std::size_t vec_offset = vec_n + (curr_elem + elem_n) / dimension_value; + // Discards vec_offset consecutive s-dimensional vectors + discard_vector(vec_offset); + // Sets up the proper position of the element-to-read + curr_elem += (z - dimension_value * vec_offset); + } + + //!Writes a @c DerivedT to a @c std::ostream. + BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, DerivedT, s) + { + os << s.dimension() << " " << s.seq_count << " " << s.curr_elem; + return os; + } + + //!Reads a @c DerivedT from a @c std::istream. + BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, DerivedT, s) + { + std::size_t dim, seed, z; + if (is >> dim >> std::ws >> seed >> std::ws >> z) // initialize iff success! + { + if (s.dimension() != dim) + { + prevent_zero_dimension(dim); + s.lattice.resize(dim); + s.quasi_state.resize(dim); + } + // Fast-forward to the correct state + s.seed(seed); + s.discard(z); + } + return is; + } + + //!Returns true if the two generators will produce identical sequences. + BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(DerivedT, x, y) + { + const std::size_t dimension_value = x.dimension(); + + // Note that two generators with different seq_counts and curr_elems can + // produce the same sequence because the generator triple + // (D, S, D) is equivalent to (D, S + 1, 0), where D is dimension, S -- seq_count, + // and the last one is curr_elem. + + return (dimension_value == y.dimension()) && + (x.seq_count + (x.curr_elem / dimension_value) == y.seq_count + (y.curr_elem / dimension_value)) && + (x.curr_elem % dimension_value == y.curr_elem % dimension_value); + } + + //!Returns true if the two generators will produce different sequences, + BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(DerivedT) + +protected: + DerivedT& derived() throw() + { + return *static_cast(this); + } + + void reset_state() + { + curr_elem = 0; + seq_count = 0; + std::fill(quasi_state.begin(), quasi_state.end(), result_type /*zero*/()); + } + +private: + inline static std::size_t prevent_zero_dimension(std::size_t dimension) + { + if (dimension == 0) + boost::throw_exception( std::invalid_argument("qrng_base: zero dimension") ); + return dimension; + } + + // Load the result from the saved state. + result_type load_cached() + { + return quasi_state[curr_elem++]; + } + + result_type next_state() + { + derived().compute_next(); + + curr_elem = 0; + return load_cached(); + } + + // Discards z consecutive s-dimensional vectors, + // and preserves the position of the element-to-read + void discard_vector(std::size_t z) + { + std::size_t inc_seq_count = seq_count + z; + // Here we check that no overflow occurs before we + // begin seeding the new value + if (inc_seq_count > seq_count) + { + std::size_t tmp = curr_elem; + + derived().seed(inc_seq_count); + + curr_elem = tmp; + } + else if (inc_seq_count < seq_count) // Increment overflowed? + { + boost::throw_exception( std::overflow_error("discard_vector") ); + } + } + +protected: + LatticeT lattice; + std::size_t curr_elem; + std::size_t seq_count; + std::vector quasi_state; +}; + +}} // namespace detail::random + +} // namespace boost + +#endif // BOOST_RANDOM_DETAIL_QRNG_BASE_HPP diff --git a/include/boost/random/faure.hpp b/include/boost/random/faure.hpp new file mode 100644 index 0000000..a923063 --- /dev/null +++ b/include/boost/random/faure.hpp @@ -0,0 +1,367 @@ +/* boost random/faure.hpp header file + * + * Copyright Justinas Vygintas Daugmaudis 2010-2017 + * 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) + */ + +#ifndef BOOST_RANDOM_FAURE_HPP +#define BOOST_RANDOM_FAURE_HPP + +#include + +#include +#include + +#include + +#include + +#include + +//!\file +//!Describes the quasi-random number generator class template faure. + +namespace boost { +namespace random { + +/** @cond */ +namespace detail { +namespace fr { + +// There is no particular reason why 187 first primes were chosen +// to be put into this table. The only reason was, perhaps, that +// the number of dimensions for Faure generator would be around +// the same number as the number of dimensions supported by the +// Sobol qrng. +struct prime_table +{ + typedef unsigned short value_type; + + BOOST_STATIC_CONSTANT(int, number_of_primes = 187); + + // A function that returns lower bound prime for a given n + static value_type lower_bound(std::size_t n) + { + static const value_type prim_a[number_of_primes] = { + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, + 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, + 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, + 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, + 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, + 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, + 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, + 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, + 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, + 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, + 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, + 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, + 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, + 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, + 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, + 1097, 1103, 1109, 1117 }; + + if (n > prim_a[number_of_primes - 1]) + { + std::ostringstream os; + os << "The Faure quasi-random number generator only supports up to " + << prim_a[number_of_primes - 1] << " dimensions."; + throw std::invalid_argument(os.str()); + } + + return *std::lower_bound(prim_a, prim_a + number_of_primes, n); + } +}; + +// Returns the integer part of the logarithm base Base of arg. +// In erroneous situations, e.g., integer_log(base, 0) the function +// returns 0 and does not report the error. This is the intended +// behavior. +inline std::size_t integer_log(std::size_t base, std::size_t arg) +{ + std::size_t ilog = 0; + while( base <= arg ) + { + arg /= base; ++ilog; + } + return ilog; +} + +// Perform exponentiation by squaring +inline std::size_t integer_pow(std::size_t base, std::size_t exp) +{ + std::size_t result = 1; + while (exp) + { + if (exp & 1) + result *= base; + exp >>= 1; + base *= base; + } + return result; +} + +// Computes a table of binomial coefficients modulo qs. +template +struct binomial_coefficients +{ + typedef RealType value_type; + + // Binomial values modulo qs_base will never be bigger than qs_base. + // We can choose an appropriate integer type to hold modulo values and + // shave off memory footprint. + typedef prime_table::value_type packed_uint_t; + + // default copy c-tor is fine + + explicit binomial_coefficients(std::size_t dimension) + { + resize(dimension); + } + + void resize(std::size_t dimension) + { + qs_base = fr::prime_table::lower_bound(dimension); + inv_qs_base = static_cast(1) / static_cast(qs_base); + + // Throw away previously computed coefficients. + // This will trigger recomputation on next update + coeff.clear(); + } + + void update(std::size_t seq, std::vector& quasi) + { + if (!quasi.empty()) + { + const std::size_t hisum = n_elements(seq); + if( coeff.size() != size_hint(hisum) ) + recompute_tables(hisum); + + typename std::vector::iterator it = quasi.begin(); + + *it = compute_recip(seq, hisum, ytemp.rbegin()); + + // Find other components using the Faure method. + ++it; + for ( ; it != quasi.end(); ++it) + { + *it = RealType(); + RealType r = inv_qs_base; + + for (std::size_t i = 0; i != hisum; ++i) + { + RealType ztemp = RealType(); + for (std::size_t j = i; j != hisum; ++j) + ztemp += ytemp[j] * upper_element(i, j, hisum); + + // Sum ( J <= I <= HISUM ) ( old ytemp(i) * binom(i,j) ) mod QS. + ytemp[i] = std::fmod(ztemp, static_cast(qs_base)); + *it += ytemp[i] * r; + r *= inv_qs_base; + } + } + } + } + +private: + inline std::size_t n_elements(std::size_t seq) const + { + return integer_log(qs_base, seq) + 1; + } + + inline static std::size_t size_hint(std::size_t n) + { + return n * (n + 1) / 2; + } + + packed_uint_t& upper_element(std::size_t i, std::size_t j, std::size_t dim) + { + BOOST_ASSERT( i < dim ); + BOOST_ASSERT( j < dim ); + BOOST_ASSERT( i <= j ); + return coeff[(i * (2 * dim - i + 1)) / 2 + j - i]; + } + + template + RealType compute_recip(std::size_t seq, std::size_t n, Iterator out) const + { + // Here we do + // Sum ( 0 <= J <= HISUM ) YTEMP(J) * QS**J + // Sum ( 0 <= J <= HISUM ) YTEMP(J) / QS**(J+1) + // in one go + RealType r = RealType(); + std::size_t m, k = integer_pow(qs_base, n - 1); + for( ; n != 0; --n, ++out, seq = m, k /= qs_base ) + { + m = seq % k; + RealType v = (seq - m) / k; // RealType <- IntType + r += v; + r *= inv_qs_base; + *out = v; // saves double dereference + } + return r; + } + + void compute_coefficients(const std::size_t n) + { + // Resize and initialize to zero + coeff.resize(size_hint(n)); + std::fill(coeff.begin(), coeff.end(), packed_uint_t()); + + // The first row and the diagonal is assigned to 1 + upper_element(0, 0, n) = 1; + for (std::size_t i = 1; i < n; ++i) + { + upper_element(0, i, n) = 1; + upper_element(i, i, n) = 1; + } + + // Computes binomial coefficients MOD qs_base + for (std::size_t i = 1; i < n; ++i) + { + for (std::size_t j = i + 1; j < n; ++j) + { + upper_element(i, j, n) = ( upper_element(i, j-1, n) + + upper_element(i-1, j-1, n) ) % qs_base; + } + } + } + + void recompute_tables(std::size_t n) + { + ytemp.resize(n); + compute_coefficients(n); + } + +private: + packed_uint_t qs_base; + RealType inv_qs_base; + + // here we cache precomputed data; note that binomial coefficients have + // to be recomputed iff the integer part of the logarithm of seq changes, + // which happens relatively rarely. + std::vector coeff; // packed upper (!) triangular matrix + std::vector ytemp; +}; + +}} // namespace detail::fr +/** @endcond */ + +//!class template faure implements a quasi-random number generator as described in +//! \blockquote +//!Henri Faure, +//!Discrepance de suites associees a un systeme de numeration (en dimension s), +//!Acta Arithmetica, +//!Volume 41, 1982, pages 337-351. +//! \endblockquote +// +//! \blockquote +//!Bennett Fox, +//!Algorithm 647: +//!Implementation and Relative Efficiency of Quasirandom +//!Sequence Generators, +//!ACM Transactions on Mathematical Software, +//!Volume 12, Number 4, December 1986, pages 362-376. +//! \endblockquote +//! +//!\attention\b Important: This implementation supports up to 229 dimensions. +//! +//!In the following documentation @c X denotes the concrete class of the template +//!faure returning objects of type @c RealType, u and v are the values of @c X. +//! +//!Some member functions may throw exceptions of type @c std::bad_alloc. +//! +//! \copydoc friendfunctions +template +class faure : public detail::qrng_base< + faure + , detail::fr::binomial_coefficients + > +{ + typedef faure self_t; + + typedef detail::fr::binomial_coefficients lattice_t; + typedef detail::qrng_base base_t; + + friend class detail::qrng_base; + +public: + typedef RealType result_type; + + /** @copydoc boost::random::niederreiter_base2::min() */ + static result_type min /** @cond */ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ () { return static_cast(0); } + + /** @copydoc boost::random::niederreiter_base2::max() */ + static result_type max /** @cond */ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ () { return static_cast(1); } + + //!Effects: Constructs the s-dimensional default Faure quasi-random number generator. + //! + //!Throws: bad_alloc, invalid_argument. + explicit faure(std::size_t s) + : base_t(s) // initialize the binomial table here + {} + + /** @copydetails boost::random::niederreiter_base2::seed() + * Throws: bad_alloc. + */ + void seed() + { + seed(0); + } + + /** @copydetails boost::random::niederreiter_base2::seed(std::size_t) + * Throws: bad_alloc. + */ + void seed(std::size_t init) + { + compute_seq(init); + this->curr_elem = 0; + this->seq_count = init; + } + + //=========================Doxygen needs this!============================== + + //!Requirements: *this is mutable. + //! + //!Returns: Returns a successive element of an s-dimensional + //!(s = X::dimension()) vector at each invocation. When all elements are + //!exhausted, X::operator() begins anew with the starting element of a + //!subsequent s-dimensional vector. + //! + //!Throws: bad_alloc. + + // Fixed in Doxygen 1.7.0 -- id 612458: Fixed problem handling @copydoc for function operators. + result_type operator()() + { + return base_t::operator()(); + } + + /** @copydoc boost::random::niederreiter_base2::discard(std::size_t) + * Throws: bad_alloc. + */ + void discard(std::size_t z) + { + base_t::discard(z); + } + +private: +/** @cond hide_private_members */ + void compute_seq(std::size_t seq) + { + this->lattice.update(seq, this->quasi_state); + } + void compute_next() + { + compute_seq(++this->seq_count); + } +/** @endcond */ +}; + +} // namespace random + +typedef random::faure faure; + +} // namespace boost + +#endif // BOOST_RANDOM_FAURE_HPP diff --git a/include/boost/random/niederreiter_base2.hpp b/include/boost/random/niederreiter_base2.hpp new file mode 100644 index 0000000..4e19d07 --- /dev/null +++ b/include/boost/random/niederreiter_base2.hpp @@ -0,0 +1,389 @@ +/* boost random/nierderreiter_base2.hpp header file + * + * Copyright Justinas Vygintas Daugmaudis 2010-2017 + * 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) + */ + +#ifndef BOOST_RANDOM_NIEDERREITER_BASE2_HPP +#define BOOST_RANDOM_NIEDERREITER_BASE2_HPP + +#include +#include +#include + +#include +#include + +#include +#include + +//!\file +//!Describes the quasi-random number generator class template niederreiter_base2. +//! +//!\b Note: it is especially useful in conjunction with class template uniform_real. + +namespace boost { +namespace random { + +/** @cond */ +namespace detail { +namespace nb2 { + +/* + Primitive polynomials in binary encoding + { + { 1, 0, 0, 0, 0, 0 }, 1 + { 0, 1, 0, 0, 0, 0 }, x + { 1, 1, 0, 0, 0, 0 }, 1 + x + { 1, 1, 1, 0, 0, 0 }, 1 + x + x^2 + { 1, 1, 0, 1, 0, 0 }, 1 + x + x^3 + { 1, 0, 1, 1, 0, 0 }, 1 + x^2 + x^3 + { 1, 1, 0, 0, 1, 0 }, 1 + x + x^4 + { 1, 0, 0, 1, 1, 0 }, 1 + x^3 + x^4 + { 1, 1, 1, 1, 1, 0 }, 1 + x + x^2 + x^3 + x^4 + { 1, 0, 1, 0, 0, 1 }, 1 + x^2 + x^5 + { 1, 0, 0, 1, 0, 1 }, 1 + x^3 + x^5 + { 1, 1, 1, 1, 0, 1 }, 1 + x + x^2 + x^3 + x^5 + { 1, 1, 1, 0, 1, 1 } 1 + x + x^2 + x^4 + x^5 + }; +*/ + +// Maximum allowed space dimension +#define BOOST_RANDOM_NIEDERREITER_BASE2_MAX_DIMENSION 54 + +struct niederreiter_tables +{ + BOOST_STATIC_CONSTANT(int, max_dimension = BOOST_RANDOM_NIEDERREITER_BASE2_MAX_DIMENSION); + + // Binary irreducible polynomials (primes in the ring GF(2)[X]), evaluated at X=2. + static unsigned short polynomial(std::size_t n) + { + static const unsigned short nb2_a[max_dimension] = { + 2, 3, 7, 11, 13, 19, 25, 31, 37, 41, + 47, 55, 59, 61, 67, 73, 87, 91, 97, 103, + 109, 115, 117, 131, 137, 143, 145, 157, + 167, 171, 185, 191, 193, 203, 211, 213, + 229, 239, 241, 247, 253, 283, 285, 299, + 301, 313, 319, 333, 351, 355, 357, 361, 369, + 375 + }; + + return nb2_a[n]; + } +}; + +// Return the base 2 logarithm for a given bitset v +template +inline typename boost::dynamic_bitset::size_type +bitset_log2(const boost::dynamic_bitset& v) +{ + typedef boost::dynamic_bitset bitset_t; + typedef typename bitset_t::size_type size_type; + + if (v.none()) + throw std::invalid_argument("bitset_log2"); + + size_type up = v.size() - 1; + size_type low = v.find_next(0); + + // Binary lookup for the most significant set bit + while (low < up) + { + size_type m = low + (up - low) / 2; + + // Check if any bit is present after mid + size_type p = v.find_next(m); + if (p != bitset_t::npos) + low = p; + else + up = m; + } + + return low; +} + + +// Multiply polynomials over Z_2. +template +inline boost::dynamic_bitset +modulo2_multiply(int P, boost::dynamic_bitset v) +{ + boost::dynamic_bitset pt (v.size()); + for (; P; P >>= 1, v <<= 1) + if (P & 1) pt ^= v; + return pt; +} + + +// Calculate the values of the constants V(J,R) as +// described in BFN section 3.3. +// +// px = appropriate irreducible polynomial for current dimension +// pb = polynomial defined in section 2.3 of BFN. +// pb is modified +template +inline void calculate_v(const boost::dynamic_bitset& pb, + int& pb_degree, std::vector& v) +{ + const T arbitrary_element = static_cast(1); // arbitray element of Z_2 + + // Now choose a value of Kj as defined in section 3.3. + // We must have 0 <= Kj < E*J = M. + // The limit condition on Kj does not seem very relevant + // in this program. + int kj = pb_degree; + + pb_degree = bitset_log2(pb); + + // Now choose values of V in accordance with + // the conditions in section 3.3. + std::fill(v.begin(), v.begin() + kj, T()); + + // Quoting from BFN: "Our program currently sets each K_q + // equal to eq. This has the effect of setting all unrestricted + // values of v to 1." + // Actually, it sets them to the arbitrary chosen value. + // Whatever. + for (int r = kj; r < pb_degree; ++r) + v[r] = arbitrary_element; + + // Calculate the remaining V's using the recursion of section 2.3, + // remembering that the B's have the opposite sign. + for (int r = pb_degree; r < v.size(); ++r) + { + T term = T /*zero*/ (); + boost::dynamic_bitset<> pb_c = pb; + for (int k = -pb_degree; k < 0; ++k, pb_c >>= 1) + { + if( pb_c.test(0) ) + term ^= v[r + k]; + } + v[r] = term; + } +} + +} // namespace nb2 + +template +struct niederreiter_base2_lattice +{ + typedef IntType value_type; + + BOOST_STATIC_CONSTANT(int, bit_count = std::numeric_limits::digits); + + explicit niederreiter_base2_lattice(std::size_t dimension) + { + resize(dimension); + } + + void resize(std::size_t dimension) + { + if (dimension > nb2::niederreiter_tables::max_dimension) + { + throw std::invalid_argument("The Niederreiter base 2 quasi-random number generator only supports up to " + BOOST_PP_STRINGIZE(BOOST_RANDOM_NIEDERREITER_BASE2_MAX_DIMENSION) " dimensions."); + } + + // Initialize the bit array + bits.resize(boost::extents[bit_count][dimension]); + + // Reserve temporary space for lattice computation + boost::multi_array ci(boost::extents[bit_count][bit_count]); + + std::vector v; + + // Compute Niedderreiter base 2 lattice + for (std::size_t dim = 0; dim != dimension; ++dim) + { + const int poly = nb2::niederreiter_tables::polynomial(dim); + if (static_cast(poly) > + static_cast(std::numeric_limits::max())) { + boost::throw_exception( std::range_error("niederreiter_base2: polynomial value outside the given IntType range") ); + } + + const int degree = multiprecision::detail::find_msb(poly); // integer log2(poly) + const int max_degree = degree * ((bit_count / degree) + 1); + + v.resize(degree + max_degree); + + // For each dimension, we need to calculate powers of an + // appropriate irreducible polynomial, see Niederreiter + // page 65, just below equation (19). + // Copy the appropriate irreducible polynomial into PX, + // and its degree into E. Set polynomial B = PX ** 0 = 1. + // M is the degree of B. Subsequently B will hold higher + // powers of PX. + int pb_degree = 0; + boost::dynamic_bitset<> pb(max_degree, 1); + + int j = 0; + while (j < bit_count) + { + // Now multiply B by PX so B becomes PX**J. + // In section 2.3, the values of Bi are defined with a minus sign : + // don't forget this if you use them later! + nb2::modulo2_multiply(poly, boost::move(pb)).swap(pb); + + // If U = 0, we need to set B to the next power of PX + // and recalculate V. + nb2::calculate_v(pb, pb_degree, v); + + // Niederreiter (page 56, after equation (7), defines two + // variables Q and U. We do not need Q explicitly, but we + // do need U. + + // Advance Niederreiter's state variables. + for (int u = 0; u < degree && j < bit_count; ++u, ++j) + { + // Now C is obtained from V. Niederreiter + // obtains A from V (page 65, near the bottom), and then gets + // C from A (page 56, equation (7)). However this can be done + // in one step. Here CI(J,R) corresponds to + // Niederreiter's C(I,J,R). + for (int r = 0; r < bit_count; ++r) { + ci[r][j] = v[r + u]; + } + } + } + + // The array CI now holds the values of C(I,J,R) for this value + // of I. We pack them into array CJ so that CJ(I,R) holds all + // the values of C(I,J,R) for J from 1 to NBITS. + for (int r = 0; r < bit_count; ++r) + { + IntType term = 0; + for (int j = 0; j < bit_count; ++j) + term = 2*term + ci[r][j]; + bits[r][dim] = term; + } + } + } + + value_type operator()(int i, int j) const + { + return bits[i][j]; + } + +private: + boost::multi_array bits; +}; + +} // namespace detail +/** @endcond */ + +//!class template niederreiter_base2 implements a quasi-random number generator as described in +//! \blockquote +//!Bratley, Fox, Niederreiter, ACM Trans. Model. Comp. Sim. 2, 195 (1992). +//! \endblockquote +//! +//!\attention \b Important: This implementation supports up to 20 dimensions. +//! +//!In the following documentation @c X denotes the concrete class of the template +//!niederreiter_base2 returning objects of type @c IntType, u and v are the values of @c X. +//! +//!Some member functions may throw exceptions of type std::overflow_error. This +//!happens when the quasi-random domain is exhausted and the generator cannot produce +//!any more values. The length of the low discrepancy sequence is given by +//! \f$L=Dimension \times 2^{digits}\f$, where digits = std::numeric_limits::digits. +template +class niederreiter_base2 : public detail::gray_coded_qrng_base< + niederreiter_base2, + detail::niederreiter_base2_lattice > +{ + typedef niederreiter_base2 self_t; + typedef detail::niederreiter_base2_lattice lattice_t; + typedef detail::gray_coded_qrng_base base_t; + +public: + typedef IntType result_type; + + //!Returns: Tight lower bound on the set of values returned by operator(). + //! + //!Throws: nothing. + static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return 0; } + + //!Returns: Tight upper bound on the set of values returned by operator(). + //! + //!Throws: nothing. + static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () { return std::numeric_limits::max(); } + + //!Effects: Constructs the default s-dimensional Niederreiter base 2 quasi-random number generator. + //! + //!Throws: bad_alloc, invalid_argument, range_error. + explicit niederreiter_base2(std::size_t s) + : base_t(s) // initialize lattice here + {} + + //!Requirements: *this is mutable. + //! + //!Effects: Resets the quasi-random number generator state to + //!the one given by the default construction. Equivalent to u.seed(0). + //! + //!\brief Throws: nothing. + void seed() + { + base_t::reset_state(); + } + + //!Requirements: *this is mutable. + //! + //!Effects: Effectively sets the quasi-random number generator state to the init-th + //!vector in the s-dimensional quasi-random domain, where s == X::dimension(). + //!\code + //!X u, v; + //!for(int i = 0; i < N; ++i) + //! for( std::size_t j = 0; j < u.dimension(); ++j ) + //! u(); + //!v.seed(N); + //!assert(u() == v()); + //!\endcode + //! + //!\brief Throws: overflow_error. + void seed(std::size_t init) + { + base_t::seed(init, "niederreiter_base2::seed"); + } + + //=========================Doxygen needs this!============================== + + //!Requirements: *this is mutable. + //! + //!Returns: Returns a successive element of an s-dimensional + //!(s = X::dimension()) vector at each invocation. When all elements are + //!exhausted, X::operator() begins anew with the starting element of a + //!subsequent s-dimensional vector. + //! + //!Throws: overflow_error. + result_type operator()() + { + return base_t::operator()(); + } + + //!Requirements: *this is mutable. + //! + //!Effects: Advances *this state as if z consecutive + //!X::operator() invocations were executed. + //!\code + //!X u = v; + //!for(int i = 0; i < N; ++i) + //! u(); + //!v.discard(N); + //!assert(u() == v()); + //!\endcode + //! + //!Throws: overflow_error. + void discard(std::size_t z) + { + base_t::discard(z); + } +}; + +} // namespace random + +typedef random::niederreiter_base2 niederreiter_base2; + +} // namespace boost + +#endif // BOOST_RANDOM_NIEDERREITER_BASE2_HPP diff --git a/include/boost/random/sobol.hpp b/include/boost/random/sobol.hpp new file mode 100644 index 0000000..b688a1f --- /dev/null +++ b/include/boost/random/sobol.hpp @@ -0,0 +1,1118 @@ +/* boost random/sobol.hpp header file + * + * Copyright Justinas Vygintas Daugmaudis 2010-2017 + * 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) + */ + +#ifndef BOOST_RANDOM_SOBOL_HPP +#define BOOST_RANDOM_SOBOL_HPP + +#include + +#include + +#include +#include + +#include + +#include + +//!\file +//!Describes the quasi-random number generator class template sobol. +//! +//!\b Note: it is especially useful in conjunction with class template uniform_real. + +namespace boost { +namespace random { + +/** @cond */ +namespace detail { +namespace sbl { + +// Maximum allowed space dimension +#define BOOST_RANDOM_SOBOL_MAX_DIMENSION 1111 + +// Data on the primitive binary polynomials (a) and the corresponding +// starting values m, for Sobol sequences in up to 1111 dimensions, +// taken from: +// P. Bratley and B. L. Fox, Algorithm 659, ACM Trans. +// Math. Soft. 14 (1), 88-100 (1988), +// as modified by: +// S. Joe and F. Y. Kuo, ACM Trans. Math. Soft 29 (1), 49-57 (2003). +struct sobol_tables +{ + BOOST_STATIC_CONSTANT(int, max_dimension = BOOST_RANDOM_SOBOL_MAX_DIMENSION); + BOOST_STATIC_CONSTANT(int, num_polynomials = max_dimension - 1); + + // log2(polynomial(num_polynomials - 1)), i.e., integer log2 of the last polynomial in the table + BOOST_STATIC_CONSTANT(int, max_degree = 13); + + static unsigned short polynomial(std::size_t n) + { + // successive primitive binary-coefficient polynomials p(z) + // = a_0 + a_1 z + a_2 z^2 + ... a_31 z^31, where a_i is the + // i-th bit of sobol_a[j] for the j-th polynomial. + static const unsigned short sobol_a[num_polynomials] = { + 3,7,11,13,19,25,37,59,47,61,55,41,67,97,91, + 109,103,115,131,193,137,145,143,241,157,185,167,229,171,213, + 191,253,203,211,239,247,285,369,299,301,333,351,355,357,361, + 391,397,425,451,463,487,501,529,539,545,557,563,601,607,617, + 623,631,637,647,661,675,677,687,695,701,719,721,731,757,761, + 787,789,799,803,817,827,847,859,865,875,877,883,895,901,911, + 949,953,967,971,973,981,985,995,1001,1019,1033,1051,1063, + 1069,1125,1135,1153,1163,1221,1239,1255,1267,1279,1293,1305, + 1315,1329,1341,1347,1367,1387,1413,1423,1431,1441,1479,1509, + 1527,1531,1555,1557,1573,1591,1603,1615,1627,1657,1663,1673, + 1717,1729,1747,1759,1789,1815,1821,1825,1849,1863,1869,1877, + 1881,1891,1917,1933,1939,1969,2011,2035,2041,2053,2071,2091, + 2093,2119,2147,2149,2161,2171,2189,2197,2207,2217,2225,2255, + 2257,2273,2279,2283,2293,2317,2323,2341,2345,2363,2365,2373, + 2377,2385,2395,2419,2421,2431,2435,2447,2475,2477,2489,2503, + 2521,2533,2551,2561,2567,2579,2581,2601,2633,2657,2669, + 2681,2687,2693,2705,2717,2727,2731,2739, + 2741,2773,2783,2793,2799,2801,2811,2819,2825,2833,2867,2879, + 2881,2891,2905,2911,2917,2927,2941,2951,2955,2963,2965,2991, + 2999,3005,3017,3035,3037,3047,3053,3083,3085,3097,3103,3159, + 3169,3179,3187,3205,3209,3223,3227,3229,3251,3263,3271,3277, + 3283,3285,3299,3305,3319,3331,3343,3357,3367,3373,3393,3399, + 3413,3417,3427,3439,3441,3475,3487,3497,3515,3517,3529,3543, + 3547,3553,3559,3573,3589,3613,3617,3623,3627,3635,3641,3655, + 3659,3669,3679,3697,3707,3709,3713,3731,3743,3747,3771,3791, + 3805,3827,3833,3851,3865,3889,3895,3933,3947,3949,3957,3971, + 3985,3991,3995,4007,4013,4021,4045,4051,4069,4073,4179,4201, + 4219,4221,4249,4305,4331,4359,4383,4387,4411,4431,4439,4449, + 4459,4485,4531,4569,4575,4621,4663,4669,4711,4723,4735,4793, + 4801,4811,4879,4893,4897,4921,4927,4941,4977,5017,5027,5033, + 5127,5169,5175,5199,5213,5223,5237,5287,5293,5331,5391,5405, + 5453,5523,5573,5591,5597,5611,5641,5703,5717,5721,5797,5821, + 5909,5913, + 5955,5957,6005,6025,6061,6067,6079,6081, + 6231,6237,6289,6295,6329,6383,6427,6453,6465,6501,6523,6539, + 6577,6589,6601,6607,6631,6683,6699,6707,6761,6795,6865,6881, + 6901,6923,6931,6943,6999,7057,7079,7103,7105,7123,7173,7185, + 7191,7207,7245,7303,7327,7333,7355,7365,7369,7375,7411,7431, + 7459,7491,7505,7515,7541,7557,7561,7701,7705,7727,7749,7761, + 7783,7795,7823,7907,7953,7963,7975,8049,8089,8123,8125,8137, + 8219,8231,8245,8275,8293,8303,8331,8333,8351,8357,8367,8379, + 8381,8387,8393,8417,8435,8461,8469,8489,8495,8507,8515,8551, + 8555,8569,8585,8599,8605,8639,8641,8647,8653,8671,8675,8689, + 8699,8729,8741,8759,8765,8771,8795,8797,8825,8831,8841,8855, + 8859,8883,8895,8909,8943,8951,8955,8965,8999,9003,9031,9045, + 9049,9071,9073,9085,9095,9101,9109,9123,9129,9137,9143,9147, + 9185,9197,9209,9227,9235,9247,9253,9257,9277,9297,9303,9313, + 9325,9343,9347,9371,9373,9397,9407,9409,9415,9419,9443,9481, + 9495,9501,9505,9517,9529,9555,9557,9571,9585,9591,9607,9611, + 9621,9625, + 9631,9647,9661,9669,9679,9687,9707,9731, + 9733,9745,9773,9791,9803,9811,9817,9833,9847,9851,9863,9875, + 9881,9905,9911,9917,9923,9963,9973,10003,10025,10043,10063, + 10071,10077,10091,10099,10105,10115,10129,10145,10169,10183, + 10187,10207,10223,10225,10247,10265,10271,10275,10289,10299, + 10301,10309,10343,10357,10373,10411,10413,10431,10445,10453, + 10463,10467,10473,10491,10505,10511,10513,10523,10539,10549, + 10559,10561,10571,10581,10615,10621,10625,10643,10655,10671, + 10679,10685,10691,10711,10739,10741,10755,10767,10781,10785, + 10803,10805,10829,10857,10863,10865,10875,10877,10917,10921, + 10929,10949,10967,10971,10987,10995,11009,11029,11043,11045, + 11055,11063,11075,11081,11117,11135,11141,11159,11163,11181, + 11187,11225,11237,11261,11279,11297,11307,11309,11327,11329, + 11341,11377,11403,11405,11413,11427,11439,11453,11461,11473, + 11479,11489,11495,11499,11533,11545,11561,11567,11575,11579, + 11589,11611,11623,11637,11657,11663,11687,11691,11701,11747, + 11761,11773,11783,11795,11797,11817,11849,11855,11867,11869, + 11873,11883,11919, + 11921,11927,11933,11947,11955,11961, + 11999,12027,12029,12037,12041,12049,12055,12095,12097,12107, + 12109,12121,12127,12133,12137,12181,12197,12207,12209,12239, + 12253,12263,12269,12277,12287,12295,12309,12313,12335,12361, + 12367,12391,12409,12415,12433,12449,12469,12479,12481,12499, + 12505,12517,12527,12549,12559,12597,12615,12621,12639,12643, + 12657,12667,12707,12713,12727,12741,12745,12763,12769,12779, + 12781,12787,12799,12809,12815,12829,12839,12857,12875,12883, + 12889,12901,12929,12947,12953,12959,12969,12983,12987,12995, + 13015,13019,13031,13063,13077,13103,13137,13149,13173,13207, + 13211,13227,13241,13249,13255,13269,13283,13285,13303,13307, + 13321,13339,13351,13377,13389,13407,13417,13431,13435,13447, + 13459,13465,13477,13501,13513,13531,13543,13561,13581,13599, + 13605,13617,13623,13637,13647,13661,13677,13683,13695,13725, + 13729,13753,13773,13781,13785,13795,13801,13807,13825,13835, + 13855,13861,13871,13883,13897,13905,13915,13939,13941,13969, + 13979,13981,13997,14027,14035,14037,14051,14063,14085,14095, + 14107,14113,14125,14137,14145, + 14151,14163,14193,14199,14219,14229, + 14233,14243,14277,14287,14289,14295,14301,14305,14323,14339, + 14341,14359,14365,14375,14387,14411,14425,14441,14449,14499, + 14513,14523,14537,14543,14561,14579,14585,14593,14599,14603, + 14611,14641,14671,14695,14701,14723,14725,14743,14753,14759, + 14765,14795,14797,14803,14831,14839,14845,14855,14889,14895, + 14909,14929,14941,14945,14951,14963,14965,14985,15033,15039, + 15053,15059,15061,15071,15077,15081,15099,15121,15147,15149, + 15157,15167,15187,15193,15203,15205,15215,15217,15223,15243, + 15257,15269,15273,15287,15291,15313,15335,15347,15359,15373, + 15379,15381,15391,15395,15397,15419,15439,15453,15469,15491, + 15503,15517,15527,15531,15545,15559,15593,15611,15613,15619, + 15639,15643,15649,15661,15667,15669,15681,15693,15717,15721, + 15741,15745,15765,15793,15799,15811,15825,15835,15847,15851, + 15865,15877,15881,15887,15899,15915,15935,15937,15955,15973, + 15977,16011,16035,16061,16069,16087,16093,16097,16121,16141, + 16153,16159,16165,16183,16189,16195,16197,16201,16209,16215, + 16225,16259,16265,16273,16299, + 16309,16355,16375,16381, + }; + + return sobol_a[n]; + } + + static unsigned short vinit(std::size_t degree, std::size_t dim) + { + // starting direction #'s m[i] = sobol_minit[i][j] for i=0..d of the + // degree-d primitive polynomial sobol_a[j]. + static const unsigned short sobol_minit[max_degree][num_polynomials] = { + /* [0][*] */ + { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1 }, + /* [1][*] */ + { 0, + 1,3,1,3,1,3,3,1,3,1,3,1,3,1,1,3,1,3,1,3, + 1,3,3,1,1,1,3,1,3,1,3,3,1,3,1,1,1,3,1,3,1,1,1,3,3,1,3,3,1,1, + 3,3,1,3,3,3,1,3,1,3,1,1,3,3,1,1,1,1,3,1,1,3,1,1,1,3,3,1,3,3, + 1,3,3,3,1,3,3,3,1,3,3,1,3,3,3,1,3,1,3,1,1,3,3,1,3,3,1,1,1,3, + 3,1,3,3,1,3,1,1,3,3,3,1,1,1,3,1,1,3,1,1,3,3,1,3,1,3,3,3,3,1, + 1,1,3,3,1,1,3,1,1,1,1,1,1,3,1,3,1,1,1,3,1,3,1,3,3,3,1,1,3,3, + 1,3,1,3,1,1,3,1,3,1,3,1,3,1,1,1,3,3,1,3,3,1,3,1,1,1,3,1,3,1, + 1,3,1,1,3,3,1,1,3,3,3,1,3,3,3,1,3,1,3,1,1,1,3,1,1,1,3,1,1,1, + 1,1,3,3,3,1,1,1,1,3,3,3,1,3,3,1,1,1,1,3,1,1,3,1,3,3,1,1,3,3, + 1,1,1,1,3,1,3,3,1,3,3,1,1,1,3,3,3,1,3,3,1,3,3,1,3,1,3,3,3,1, + 3,1,1,3,1,3,1,1,1,3,3,3,1,1,3,1,3,1,1,1,1,1,1,3,1,1,3,1,3,3, + 1,1,1,1,3,1,3,1,3,1,1,1,1,3,3,1,1,1,1,1,3,3,3,1,1,3,3,3,3,3, + 1,3,3,1,3,3,3,3,1,1,1,1,1,1,3,1,1,3,1,1,1,3,1,1,1,3,3,3,1,3, + 1,1,3,3,3,1,3,3,1,3,1,3,3,1,3,3,3,1,1, + 3,3,1,3,1,3,1,1,1,3,3,3,3,1,3,1,1,3,1, + 3,1,1,1,3,1,3,1,3,1,3,3,3,3,3,3,3,3,1,3,3,3,3,3,1,3,1,3,3,3, + 1,3,1,3,1,3,3,1,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,3,3,1,1,3,3,1, + 1,1,3,3,1,1,3,3,3,3,1,1,3,1,3,3,1,3,3,1,1,1,3,3,3,1,1,3,3,3, + 3,3,1,1,1,3,1,3,3,1,3,3,3,3,1,1,3,1,1,3,1,3,1,3,1,3,3,1,1,3, + 3,1,3,3,1,3,3,1,1,3,1,3,3,1,1,3,1,3,1,3,1,1,3,3,1,1,1,3,3,1, + 3,1,1,3,3,1,1,3,1,3,1,1,1,1,1,3,1,1,1,1,3,1,3,1,1,3,3,1,1,3, + 1,3,1,3,3,3,1,3,3,3,1,1,3,3,3,1,1,1,1,3,1,3,1,3,1,1,3,3,1,1, + 1,3,3,1,3,1,3,1,1,1,1,1,1,3,1,3,3,1,3,3,3,1,3,1,1,3,3,1,1,3, + 3,1,1,1,3,1,3,3,1,1,3,1,1,3,1,3,1,1,1,3,3,3,3,1,1,3,3,1,1,1, + 1,3,1,1,3,3,3,1,1,3,3,1,3,3,1,1,3,3,3,3,3,3,3,1,3,3,1,3,1,3, + 1,1,3,3,1,1,1,3,1,3,3,1,3,3,1,3,1,1,3,3,3,1,1,1,3,1,1,1,3,3, + 3,1,3,3,1,3,1,1,3,3,3,1,3,3,1,1,1,3,1,3,3,3,3,3,3,3,3,1,3,3, + 1,3,1,1,3,3,3,1,3,3,3,3,3,1,3,3,3,1,1,1, + 3,3,1,3,3,1,3,1,3,1,3,1,3,3,3,3,3,3, + 1,1,3,1,3,1,1,1,1,1,3,1,1,1,3,1,3,1,1,3,3,3,1,3,1,3,1,1,3,1, + 3,3,1,3,1,3,3,1,3,3,1,3,3,3,3,3,3,1,3,1,1,3,3,3,1,1,3,3,3,3, + 3,3,3,1,3,3,3,3,1,3,1,3,3,3,1,3,1,3,1,1,1,3,3,1,3,1,1,3,3,1, + 3,1,1,1,1,3,1,3,1,1,3,1,3,1,3,3,3,3,3,3,1,3,3,3,3,1,3,3,1,3, + 3,3,3,3,1,1,1,1,3,3,3,1,3,3,1,1,3,3,1,1,3,3,1,3,1,1,3,1,3,3, + 3,3,3,1,3,1,1,3,3,3,3,1,3,1,1,3,3,3,3,3,3,1,1,3,1,3,1,1,3,1, + 1,1,1,3,3,1,1,3,1,1,1,3,1,3,1,1,3,3,1,3,1,1,3,3,3,3,3,1,3,1, + 1,1,3,1,1,1,3,1,1,3,1,3,3,3,3,3,1,1,1,3,3,3,3,1,3,3,3,3,1,1, + 3,3,3,1,3,1,1,3,3,1,3,3,1,1,1,1,1,3,1,1,3,3,1,1,1,3,1,1,3,3, + 1,3,3,3,3,3,3,3,3,1,1,3,3,1,1,3,1,3,3,3,3,3,1}, + /* [2][*] */ + { 0,0, + 7,5,1,3,3,7,5,5,7,7,1,3,3,7,5,1,1,5,3,7, + 1,7,5,1,3,7,7,1,1,1,5,7,7,5,1,3,3,7,5,5,5,3,3,3,1,1,5,1,1,5, + 3,3,3,3,1,3,7,5,7,3,7,1,3,3,5,1,3,5,5,7,7,7,1,1,3,3,1,1,5,1, + 5,7,5,1,7,5,3,3,1,5,7,1,7,5,1,7,3,1,7,1,7,3,3,5,7,3,3,5,1,3, + 3,1,3,5,1,3,3,3,7,1,1,7,3,1,3,7,5,5,7,5,5,3,1,3,3,3,1,3,3,7, + 3,3,1,7,5,1,7,7,5,7,5,1,3,1,7,3,7,3,5,7,3,1,3,3,3,1,5,7,3,3, + 7,7,7,5,3,1,7,1,3,7,5,3,3,3,7,1,1,3,1,5,7,1,3,5,3,5,3,3,7,5, + 5,3,3,1,3,7,7,7,1,5,7,1,3,1,1,7,1,3,1,7,1,5,3,5,3,1,1,5,5,3, + 3,5,7,1,5,3,7,7,3,5,3,3,1,7,3,1,3,5,7,1,3,7,1,5,1,3,1,5,3,1, + 7,1,5,5,5,3,7,1,1,7,3,1,1,7,5,7,5,7,7,3,7,1,3,7,7,3,5,1,1,7, + 1,5,5,5,1,5,1,7,5,5,7,1,1,7,1,7,7,1,1,3,3,3,7,7,5,3,7,3,1,3, + 7,5,3,3,5,7,1,1,5,5,7,7,1,1,1,1,5,5,5,7,5,7,1,1,3,5,1,3,3,7, + 3,7,5,3,5,3,1,7,1,7,7,1,1,7,7,7,5,5,1,1,7,5,5,7,5,1,1,5,5,5, + 5,5,5,1,3,1,5,7,3,3,5,7,3,7,1,7,7,1,3, + 5,1,5,5,3,7,3,7,7,5,7,5,7,1,1,5,3,5,1, + 5,3,7,1,5,7,7,3,5,1,3,5,1,5,3,3,3,7,3,5,1,3,7,7,3,7,5,3,3,1, + 7,5,1,1,3,7,1,7,1,7,3,7,3,5,7,3,5,3,1,1,1,5,7,7,3,3,1,1,1,5, + 5,7,3,1,1,3,3,7,3,3,5,1,3,7,3,3,7,3,5,7,5,7,7,3,3,5,1,3,5,3, + 1,3,5,1,1,3,7,7,1,5,1,3,7,3,7,3,5,1,7,1,1,3,5,3,7,1,5,5,1,1, + 3,1,3,3,7,1,7,3,1,7,3,1,7,3,5,3,5,7,3,3,3,5,1,7,7,1,3,1,3,7, + 7,1,3,7,3,1,5,3,1,1,1,5,3,3,7,1,5,3,5,1,3,1,3,1,5,7,7,1,1,5, + 3,1,5,1,1,7,7,3,5,5,1,7,1,5,1,1,3,1,5,7,5,7,7,1,5,1,1,3,5,1, + 5,5,3,1,3,1,5,5,3,3,3,3,1,1,3,1,3,5,5,7,5,5,7,5,7,1,3,7,7,3, + 5,5,7,5,5,3,3,3,1,7,1,5,5,5,3,3,5,1,3,1,3,3,3,7,1,7,7,3,7,1, + 1,5,7,1,7,1,7,7,1,3,7,5,1,3,5,5,5,1,1,7,1,7,1,7,7,3,1,1,5,1, + 5,1,5,3,5,5,5,5,5,3,3,7,3,3,5,5,3,7,1,5,7,5,1,5,5,3,5,5,7,5, + 3,5,5,5,1,5,5,5,5,1,3,5,3,1,7,5,5,7,1,5,3,3,1,5,3,7,1,7,5,1, + 1,3,1,1,7,1,5,5,3,7,3,7,5,3,1,1,3,1,3,5, + 5,7,5,3,7,7,7,3,7,3,7,1,3,1,7,7,1,7, + 3,7,3,7,3,7,3,5,1,1,7,3,1,5,5,7,1,5,5,5,7,1,5,5,1,5,5,3,1,3, + 1,7,3,1,3,5,7,7,7,1,1,7,3,1,5,5,5,1,1,1,1,1,5,3,5,1,3,5,3,1, + 1,1,1,3,7,3,7,5,7,1,5,5,7,5,3,3,7,5,3,1,1,3,1,3,1,1,3,7,1,7, + 1,1,5,1,7,5,3,7,3,5,3,1,1,5,5,1,7,7,3,7,3,7,1,5,1,5,3,7,3,5, + 7,7,7,3,3,1,1,5,5,3,7,1,1,1,3,5,3,1,1,3,3,7,5,1,1,3,7,1,5,7, + 3,7,5,5,7,3,5,3,1,5,3,1,1,7,5,1,7,3,7,5,1,7,1,7,7,1,1,7,1,5, + 5,1,1,7,5,7,1,5,3,5,3,3,7,1,5,1,1,5,5,3,3,7,5,5,1,1,1,3,1,5, + 7,7,1,7,5,7,3,7,3,1,3,7,3,1,5,5,3,5,1,3,5,5,5,1,1,7,7,1,5,5, + 1,3,5,1,5,3,5,3,3,7,5,7,3,7,3,1,3,7,7,3,3,1,1,3,3,3,3,3,5,5, + 3,3,3,1,3,5,7,7,1,5,7,3,7,1,1,3,5,7,5,3,3,3}, + /* [3][*] */ + { 0,0,0,0, + 1,7,9,13,11,1,3,7,9,5,13,13,11,3,15,5,3, + 15,7,9,13,9,1,11,7,5,15,1,15,11,5,11,1,7,9,7,7,1,15,15,15,13, + 3,3,15,5,9,7,13,3,7,5,11,9,1,9,1,5,7,13,9,9,1,7,3,5,1,11,11, + 13,7,7,9,9,1,1,3,9,15,1,5,13,1,9,9,9,9,9,13,11,3,5,11,11,13, + 5,3,15,1,11,11,7,13,15,11,13,9,11,15,15,13,3,15,7,9,11,13,11, + 9,9,5,13,9,1,13,7,7,7,7,7,5,9,7,13,11,9,11,15,3,13,11,1,11,3, + 3,9,11,1,7,1,15,15,3,1,9,1,7,13,11,3,13,11,7,3,3,5,13,11,5, + 11,1,3,9,7,15,7,5,13,7,9,13,15,13,9,7,15,7,9,5,11,11,13,13,9, + 3,5,13,9,11,15,11,7,1,7,13,3,13,3,13,9,15,7,13,13,3,13,15,15, + 11,9,13,9,15,1,1,15,11,11,7,1,11,13,9,13,3,5,11,13,9,9,13,1, + 11,15,13,3,13,7,15,1,15,3,3,11,7,13,7,7,9,7,5,15,9,5,5,7,15, + 13,15,5,15,5,3,1,11,7,1,5,7,9,3,11,1,15,1,3,15,11,13,5,13,1, + 7,1,15,7,5,1,1,15,13,11,11,13,5,11,7,9,7,1,5,3,9,5,5,11,5,1, + 7,1,11,7,9,13,15,13,3,1,11,13,15,1,1,11,9,13,3,13,11,15,13,9, + 9,9,5,5,5,5,1,15,5,9, + 11,7,15,5,3,13,5,3,11,5,1,11,13,9,11, + 3,7,13,15,1,7,11,1,13,1,15,1,9,7,3,9,11,1,9,13,13,3,11,7,9,1, + 7,15,9,1,5,13,5,11,3,9,15,11,13,5,1,7,7,5,13,7,7,9,5,11,11,1, + 1,15,3,13,9,13,9,9,11,5,5,13,15,3,9,15,3,11,11,15,15,3,11,15, + 15,3,1,3,1,3,3,1,3,13,1,11,5,15,7,15,9,1,7,1,9,11,15,1,13,9, + 13,11,7,3,7,3,13,7,9,7,7,3,3,9,9,7,5,11,13,13,7,7,15,9,5,5,3, + 3,13,3,9,3,1,11,1,3,11,15,11,11,11,9,13,7,9,15,9,11,1,3,3,9, + 7,15,13,13,7,15,9,13,9,15,13,15,9,13,1,11,7,11,3,13,5,1,7,15, + 3,13,7,13,13,11,3,5,3,13,11,9,9,3,11,11,7,9,13,11,7,15,13,7, + 5,3,1,5,15,15,3,11,1,7,3,15,11,5,5,3,5,5,1,15,5,1,5,3,7,5,11, + 3,13,9,13,15,5,3,5,9,5,3,11,1,13,9,15,3,5,11,9,1,3,15,9,9,9, + 11,7,5,13,1,15,3,13,9,13,5,1,5,1,13,13,7,7,1,9,5,11,9,11,13, + 3,15,15,13,15,7,5,7,9,7,9,9,9,11,9,3,11,15,13,13,5,9,15,1,1, + 9,5,13,3,13,15,3,1,3,11,13,1,15,9,9,3,1,9,1,9,1,13,11,15,7, + 11,15,13,15,1,9,9,7, + 3,5,11,7,3,9,5,15,7,5,3,13,7,1,1,9, + 15,15,15,11,3,5,15,13,7,15,15,11,11,9,5,15,9,7,3,13,1,1,5,1, + 3,1,7,1,1,5,1,11,11,9,9,5,13,7,7,7,1,1,9,9,11,11,15,7,5,5,3, + 11,1,3,7,13,7,7,7,3,15,15,11,9,3,9,3,15,13,5,3,3,3,5,9,15,9, + 9,1,5,9,9,15,5,15,7,9,1,9,9,5,11,5,15,15,11,7,7,7,1,1,11,11, + 13,15,3,13,5,1,7,1,11,3,13,15,3,5,3,5,7,3,9,9,5,1,7,11,9,3,5, + 11,13,13,13,9,15,5,7,1,15,11,9,15,15,13,13,13,1,11,9,15,9,5, + 15,5,7,3,11,3,15,7,13,11,7,3,7,13,5,13,15,5,13,9,1,15,11,5,5, + 1,11,3,3,7,1,9,7,15,9,9,3,11,15,7,1,3,1,1,1,9,1,5,15,15,7,5, + 5,7,9,7,15,13,13,11,1,9,11,1,13,1,7,15,15,5,5,1,11,3,9,11,9, + 9,9,1,9,3,5,15,1,1,9,7,3,3,1,9,9,11,9,9,13,13,3,13,11,13,5,1, + 5,5,9,9,3,13,13,9,15,9,11,7,11,9,13,9,1,15,9,7,7,1,7,9,9,15, + 1,11,1,13,13,15,9,13,7,15,3,9,3,1,13,7,5,9,3,1,7,1,1,13,3,3, + 11,1,7,13,15,15,5,7,13,13,15,11,13,1,13,13,3,9,15,15,11,15,9, + 15,1,13,15,1,1,5, + 11,5,1,11,11,5,3,9,1,3,5,13,9,7,7,1, + 9,9,15,7,5,5,15,13,9,7,13,3,13,11,13,7,9,13,13,13,15,9,5,5,3, + 3,3,1,3,15}, + /* [4][*] */ + { 0,0,0,0,0,0, + 9,3,27,15,29,21,23,19,11,25,7,13,17,1, + 25,29,3,31,11,5,23,27,19,21,5,1,17,13,7,15,9,31,25,3,5,23,7, + 3,17,23,3,3,21,25,25,23,11,19,3,11,31,7,9,5,17,23,17,17,25, + 13,11,31,27,19,17,23,7,5,11,19,19,7,13,21,21,7,9,11,1,5,21, + 11,13,25,9,7,7,27,15,25,15,21,17,19,19,21,5,11,3,5,29,31,29, + 5,5,1,31,27,11,13,1,3,7,11,7,3,23,13,31,17,1,27,11,25,1,23, + 29,17,25,7,25,27,17,13,17,23,5,17,5,13,11,21,5,11,5,9,31,19, + 17,9,9,27,21,15,15,1,1,29,5,31,11,17,23,19,21,25,15,11,5,5,1, + 19,19,19,7,13,21,17,17,25,23,19,23,15,13,5,19,25,9,7,3,21,17, + 25,1,27,25,27,25,9,13,3,17,25,23,9,25,9,13,17,17,3,15,7,7,29, + 3,19,29,29,19,29,13,15,25,27,1,3,9,9,13,31,29,31,5,15,29,1, + 19,5,9,19,5,15,3,5,7,15,17,17,23,11,9,23,19,3,17,1,27,9,9,17, + 13,25,29,23,29,11,31,25,21,29,19,27,31,3,5,3,3,13,21,9,29,3, + 17,11,11,9,21,19,7,17,31,25,1,27,5,15,27,29,29,29,25,27,25,3, + 21,17,25,13,15,17,13,23,9,3,11,7,9,9,7,17,7,1, + 27,1,9,5,31,21,25,25,21,11,1,23,19,27, + 15,3,5,23,9,25,7,29,11,9,13,5,11,1,3,31,27,3,17,27,11,13,15, + 29,15,1,15,23,25,13,21,15,3,29,29,5,25,17,11,7,15,5,21,7,31, + 13,11,23,5,7,23,27,21,29,15,7,27,27,19,7,15,27,27,19,19,9,15, + 1,3,29,29,5,27,31,9,1,7,3,19,19,29,9,3,21,31,29,25,1,3,9,27, + 5,27,25,21,11,29,31,27,21,29,17,9,17,13,11,25,15,21,11,19,31, + 3,19,5,3,3,9,13,13,3,29,7,5,9,23,13,21,23,21,31,11,7,7,3,23, + 1,23,5,9,17,21,1,17,29,7,5,17,13,25,17,9,19,9,5,7,21,19,13,9, + 7,3,9,3,15,31,29,29,25,13,9,21,9,31,7,15,5,31,7,15,27,25,19, + 9,9,25,25,23,1,9,7,11,15,19,15,27,17,11,11,31,13,25,25,9,7, + 13,29,19,5,19,31,25,13,25,15,5,9,29,31,9,29,27,25,27,11,17,5, + 17,3,23,15,9,9,17,17,31,11,19,25,13,23,15,25,21,31,19,3,11, + 25,7,15,19,7,5,3,13,13,1,23,5,25,11,25,15,13,21,11,23,29,5, + 17,27,9,19,15,5,29,23,19,1,27,3,23,21,19,27,11,17,13,27,11, + 31,23,5,9,21,31,29,11,21,17,15,7,15,7,9,21,27,25, + 29,11,3,21,13,23,19,27,17,29,25,17,9, + 1,19,23,5,23,1,17,17,13,27,23,7,7,11,13,17,13,11,21,13,23,1, + 27,13,9,7,1,27,29,5,13,25,21,3,31,15,13,3,19,13,1,27,15,17,1, + 3,13,13,13,31,29,27,7,7,21,29,15,17,17,21,19,17,3,15,5,27,27, + 3,31,31,7,21,3,13,11,17,27,25,1,9,7,29,27,21,23,13,25,29,15, + 17,29,9,15,3,21,15,17,17,31,9,9,23,19,25,3,1,11,27,29,1,31, + 29,25,29,1,23,29,25,13,3,31,25,5,5,11,3,21,9,23,7,11,23,11,1, + 1,3,23,25,23,1,23,3,27,9,27,3,23,25,19,29,29,13,27,5,9,29,29, + 13,17,3,23,19,7,13,3,19,23,5,29,29,13,13,5,19,5,17,9,11,11, + 29,27,23,19,17,25,13,1,13,3,11,1,17,29,1,13,17,9,17,21,1,11, + 1,1,25,5,7,29,29,19,19,1,29,13,3,1,31,15,13,3,1,11,19,5,29, + 13,29,23,3,1,31,13,19,17,5,5,1,29,23,3,19,25,19,27,9,27,13, + 15,29,23,13,25,25,17,19,17,15,27,3,25,17,27,3,27,31,23,13,31, + 11,15,7,21,19,27,19,21,29,7,31,13,9,9,7,21,13,11,9,11,29,19, + 11,19,21,5,29,13,7,19,19,27,23,31,1,27,21,7,3,7,11, + 23,13,29,11,31,19,1,5,5,11,5,3,27,5, + 7,11,31,1,27,31,31,23,5,21,27,9,25,3,15,19,1,19,9,5,25,21,15, + 25,29,15,21,11,19,15,3,7,13,11,25,17,1,5,31,13,29,23,9,5,29, + 7,17,27,7,17,31,9,31,9,9,7,21,3,3,3,9,11,21,11,31,9,25,5,1, + 31,13,29,9,29,1,11,19,7,27,13,31,7,31,7,25,23,21,29,11,11,13, + 11,27,1,23,31,21,23,21,19,31,5,31,25,25,19,17,11,25,7,13,1, + 29,17,23,15,7,29,17,13,3,17}, + /* [5][*] */ + { 0,0,0,0,0,0,0,0,0,0,0,0, + 37,33,7,5,11,39,63,59,17,15,23,29,3,21, + 13,31,25,9,49,33,19,29,11,19,27,15,25,63,55,17,63,49,19,41, + 59,3,57,33,49,53,57,57,39,21,7,53,9,55,15,59,19,49,31,3,39,5, + 5,41,9,19,9,57,25,1,15,51,11,19,61,53,29,19,11,9,21,19,43,13, + 13,41,25,31,9,11,19,5,53,37,7,51,45,7,7,61,23,45,7,59,41,1, + 29,61,37,27,47,15,31,35,31,17,51,13,25,45,5,5,33,39,5,47,29, + 35,47,63,45,37,47,59,21,59,33,51,9,27,13,25,43,3,17,21,59,61, + 27,47,57,11,17,39,1,63,21,59,17,13,31,3,31,7,9,27,37,23,31,9, + 45,43,31,63,21,39,51,27,7,53,11,1,59,39,23,49,23,7,55,59,3, + 19,35,13,9,13,15,23,9,7,43,55,3,19,9,27,33,27,49,23,47,19,7, + 11,55,27,35,5,5,55,35,37,9,33,29,47,25,11,47,53,61,59,3,53, + 47,5,19,59,5,47,23,45,53,3,49,61,47,39,29,17,57,5,17,31,23, + 41,39,5,27,7,29,29,33,31,41,31,29,17,29,29,9,9,31,27,53,35,5, + 61,1,49,13,57,29,5,21,43,25,57,49,37,27,11,61,37,49,5,63,63, + 3,45,37,63,21,21,19,27,59,21,45,23,13,15,3,43,63,39,19, + 63,31,41,41,15,43,63,53,1,63,31,7,17, + 11,61,31,51,37,29,59,25,63,59,47,15,27,19,29,45,35,55,39,19, + 43,21,19,13,17,51,37,5,33,35,49,25,45,1,63,47,9,63,15,25,25, + 15,41,13,3,19,51,49,37,25,49,13,53,47,23,35,29,33,21,35,23,3, + 43,31,63,9,1,61,43,3,11,55,11,35,1,63,35,49,19,45,9,57,51,1, + 47,41,9,11,37,19,55,23,55,55,13,7,47,37,11,43,17,3,25,19,55, + 59,37,33,43,1,5,21,5,63,49,61,21,51,15,19,43,47,17,9,53,45, + 11,51,25,11,25,47,47,1,43,29,17,31,15,59,27,63,11,41,51,29,7, + 27,63,31,43,3,29,39,3,59,59,1,53,63,23,63,47,51,23,61,39,47, + 21,39,15,3,9,57,61,39,37,21,51,1,23,43,27,25,11,13,21,43,7, + 11,33,55,1,37,35,27,61,39,5,19,61,61,57,59,21,59,61,57,25,55, + 27,31,41,33,63,19,57,35,13,63,35,17,11,11,49,41,55,5,45,17, + 35,5,31,31,37,17,45,51,1,39,49,55,19,41,13,5,51,5,49,1,21,13, + 17,59,51,11,3,61,1,33,37,33,61,25,27,59,7,49,13,63,3,33,3,15, + 9,13,35,39,11,59,59,1,57,11,5,57,13,31,13,11,55,45,9,55,55, + 19,25,41,23,45,29,63,59,27,39,21,37,7, + 61,49,35,39,9,29,7,25,23,57,5,19,15,33,49,37,25,17,45,29,15, + 25,3,3,49,11,39,15,19,57,39,15,11,3,57,31,55,61,19,5,41,35, + 59,61,39,41,53,53,63,31,9,59,13,35,55,41,49,5,41,25,27,43,5, + 5,43,5,5,17,5,15,27,29,17,9,3,55,31,1,45,45,13,57,17,3,61,15, + 49,15,47,9,37,45,9,51,61,21,33,11,21,63,63,47,57,61,49,9,59, + 19,29,21,23,55,23,43,41,57,9,39,27,41,35,61,29,57,63,21,31, + 59,35,49,3,49,47,49,33,21,19,21,35,11,17,37,23,59,13,37,35, + 55,57,1,29,45,11,1,15,9,33,19,53,43,39,23,7,13,13,1,19,41,55, + 1,13,15,59,55,15,3,57,37,31,17,1,3,21,29,25,55,9,37,33,53,41, + 51,19,57,13,63,43,19,7,13,37,33,19,15,63,51,11,49,23,57,47, + 51,15,53,41,1,15,37,61,11,35,29,33,23,55,11,59,19,61,61,45, + 13,49,13,63,5,61,5,31,17,61,63,13,27,57,1,21,5,11,39,57,51, + 53,39,25,41,39,37,23,31,25,33,17,57,29,27,23,47,41,29,19,47, + 41,25,5,51,43,39,29,7,31,45,51,49,55,17,43,49,45,9,29,3,5,47, + 9,15,19, + 51,45,57,63,9,21,59,3,9,13,45,23,15, + 31,21,15,51,35,9,11,61,23,53,29,51,45,31,29,5,35,29,53,35,17, + 59,55,27,51,59,27,47,15,29,37,7,49,55,5,19,45,29,19,57,33,53, + 45,21,9,3,35,29,43,31,39,3,45,1,41,29,5,59,41,33,35,27,19,13, + 25,27,43,33,35,17,17,23,7,35,15,61,61,53,5,15,23,11,13,43,55, + 47,25,43,15,57,45,1,49,63,57,15,31,31,7,53,27,15,47,23,7,29, + 53,47,9,53,3,25,55,45,63,21,17,23,31,27,27,43,63,55,63,45,51, + 15,27,5,37,43,11,27,5,27,59,21,7,39,27,63,35,47,55,17,17,17, + 3,19,21,13,49,61,39,15}, + /* [6][*] */ + { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 13,33,115,41,79,17,29,119,75,73,105,7, + 59,65,21,3,113,61,89,45,107,21,71,79,19,71,61,41,57,121,87, + 119,55,85,121,119,11,23,61,11,35,33,43,107,113,101,29,87,119, + 97,29,17,89,5,127,89,119,117,103,105,41,83,25,41,55,69,117, + 49,127,29,1,99,53,83,15,31,73,115,35,21,89,5,1,91,53,35,95, + 83,19,85,55,51,101,33,41,55,45,95,61,27,37,89,75,57,61,15, + 117,15,21,27,25,27,123,39,109,93,51,21,91,109,107,45,15,93, + 127,3,53,81,79,107,79,87,35,109,73,35,83,107,1,51,7,59,33, + 115,43,111,45,121,105,125,87,101,41,95,75,1,57,117,21,27,67, + 29,53,117,63,1,77,89,115,49,127,15,79,81,29,65,103,33,73,79, + 29,21,113,31,33,107,95,111,59,99,117,63,63,99,39,9,35,63,125, + 99,45,93,33,93,9,105,75,51,115,11,37,17,41,21,43,73,19,93,7, + 95,81,93,79,81,55,9,51,63,45,89,73,19,115,39,47,81,39,5,5,45, + 53,65,49,17,105,13,107,5,5,19,73,59,43,83,97,115,27,1,69,103, + 3,99,103,63,67,25,121,97,77,13,83,103,41,11,27,81,37,33,125, + 71,41,41,59,41,87,123, + 43,101,63,45,39,21,97,15,97,111,21,49, + 13,17,79,91,65,105,75,1,45,67,83,107,125,87,15,81,95,105,65, + 45,59,103,23,103,99,67,99,47,117,71,89,35,53,73,9,115,49,37, + 1,35,9,45,81,19,127,17,17,105,89,49,101,7,37,33,11,95,95,17, + 111,105,41,115,5,69,101,27,27,101,103,53,9,21,43,79,91,65, + 117,87,125,55,45,63,85,83,97,45,83,87,113,93,95,5,17,77,77, + 127,123,45,81,85,121,119,27,85,41,49,15,107,21,51,119,11,87, + 101,115,63,63,37,121,109,7,43,69,19,77,49,71,59,35,7,13,55, + 101,127,103,85,109,29,61,67,21,111,67,23,57,75,71,101,123,41, + 107,101,107,125,27,47,119,41,19,127,33,31,109,7,91,91,39,125, + 105,47,125,123,91,9,103,45,23,117,9,125,73,11,37,61,79,21,5, + 47,117,67,53,85,33,81,121,47,61,51,127,29,65,45,41,95,57,73, + 33,117,61,111,59,123,65,47,105,23,29,107,37,81,67,29,115,119, + 75,73,99,103,7,57,45,61,95,49,101,101,35,47,119,39,67,31,103, + 7,61,127,87,3,35,29,73,95,103,71,75,51,87,57,97,11,105,87,41, + 73,109,69,35,121,39,111,1,77, + 39,47,53,91,3,17,51,83,39,125,85,111, + 21,69,85,29,55,11,117,1,47,17,65,63,47,117,17,115,51,25,33, + 123,123,83,51,113,95,121,51,91,109,43,55,35,55,87,33,37,5,3, + 45,21,105,127,35,17,35,37,97,97,21,77,123,17,89,53,105,75,25, + 125,13,47,21,125,23,55,63,61,5,17,93,57,121,69,73,93,121,105, + 75,91,67,95,75,9,69,97,99,93,11,53,19,73,5,33,79,107,65,69, + 79,125,25,93,55,61,17,117,69,97,87,111,37,93,59,79,95,53,115, + 53,85,85,65,59,23,75,21,67,27,99,79,27,3,95,27,69,19,75,47, + 59,41,85,77,99,55,49,93,93,119,51,125,63,13,15,45,61,19,105, + 115,17,83,7,7,11,61,37,63,89,95,119,113,67,123,91,33,37,99, + 43,11,33,65,81,79,81,107,63,63,55,89,91,25,93,101,27,55,75, + 121,79,43,125,73,27,109,35,21,71,113,89,59,95,41,45,113,119, + 113,39,59,73,15,13,59,67,121,27,7,105,15,59,59,35,91,89,23, + 125,97,53,41,91,111,29,31,3,103,61,71,35,7,119,29,45,49,111, + 41,109,59,125,13,27,19,79,9,75,83,81,33,91,109,33,29,107,111, + 101,107,109,65,59,43,37, + 1,9,15,109,37,111,113,119,79,73,65, + 71,93,17,101,87,97,43,23,75,109,41,49,53,31,97,105,109,119, + 51,9,53,113,97,73,89,79,49,61,105,13,99,53,71,7,87,21,101,5, + 71,31,123,121,121,73,79,115,13,39,101,19,37,51,83,97,55,81, + 91,127,105,89,63,47,49,75,37,77,15,49,107,23,23,35,19,69,17, + 59,63,73,29,125,61,65,95,101,81,57,69,83,37,11,37,95,1,73,27, + 29,57,7,65,83,99,69,19,103,43,95,25,19,103,41,125,97,71,105, + 83,83,61,39,9,45,117,63,31,5,117,67,125,41,117,43,77,97,15, + 29,5,59,25,63,87,39,39,77,85,37,81,73,89,29,125,109,21,23, + 119,105,43,93,97,15,125,29,51,69,37,45,31,75,109,119,53,5, + 101,125,121,35,29,7,63,17,63,13,69,15,105,51,127,105,9,57,95, + 59,109,35,49,23,33,107,55,33,57,79,73,69,59,107,55,11,63,95, + 103,23,125,91,31,91,51,65,61,75,69,107,65,101,59,35,15}, + /* [7][*] */ + { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 7,23,39,217,141,27,53,181,169,35,15, + 207,45,247,185,117,41,81,223,151,81,189,61,95,185,23,73,113, + 239,85,9,201,83,53,183,203,91,149,101,13,111,239,3,205,253, + 247,121,189,169,179,197,175,217,249,195,95,63,19,7,5,75,217, + 245,111,189,165,169,141,221,249,159,253,207,249,219,23,49, + 127,237,5,25,177,37,103,65,167,81,87,119,45,79,143,57,79,187, + 143,183,75,97,211,149,175,37,135,189,225,241,63,33,43,13,73, + 213,57,239,183,117,21,29,115,43,205,223,15,3,159,51,101,127, + 99,239,171,113,171,119,189,245,201,27,185,229,105,153,189,33, + 35,137,77,97,17,181,55,197,201,155,37,197,137,223,25,179,91, + 23,235,53,253,49,181,249,53,173,97,247,67,115,103,159,239,69, + 173,217,95,221,247,97,91,123,223,213,129,181,87,239,85,89, + 249,141,39,57,249,71,101,159,33,137,189,71,253,205,171,13, + 249,109,131,199,189,179,31,99,113,41,173,23,189,197,3,135,9, + 95,195,27,183,1,123,73,53,99,197,59,27,101,55,193,31,61,119, + 11,7,255,233,53,157,193,97,83,65,81,239,167,69,71,109, + 97,137,71,193,189,115,79,205,37,227, + 53,33,91,229,245,105,77,229,161,103,93,13,161,229,223,69,15, + 25,23,233,93,25,217,247,61,75,27,9,223,213,55,197,145,89,199, + 41,201,5,149,35,119,183,53,11,13,3,179,229,43,55,187,233,47, + 133,91,47,71,93,105,145,45,255,221,115,175,19,129,5,209,197, + 57,177,115,187,119,77,211,111,33,113,23,87,137,41,7,83,43, + 121,145,5,219,27,11,111,207,55,97,63,229,53,33,149,23,187, + 153,91,193,183,59,211,93,139,59,179,163,209,77,39,111,79,229, + 85,237,199,137,147,25,73,121,129,83,87,93,205,167,53,107,229, + 213,95,219,109,175,13,209,97,61,147,19,13,123,73,35,141,81, + 19,171,255,111,107,233,113,133,89,9,231,95,69,33,1,253,219, + 253,247,129,11,251,221,153,35,103,239,7,27,235,181,5,207,53, + 149,155,225,165,137,155,201,97,245,203,47,39,35,105,239,49, + 15,253,7,237,213,55,87,199,27,175,49,41,229,85,3,149,179,129, + 185,249,197,15,97,197,139,203,63,33,251,217,199,199,99,249, + 33,229,177,13,209,147,97,31,125,177,137, + 187,11,91,223,29,169,231,59,31,163,41, + 57,87,247,25,127,101,207,187,73,61,105,27,91,171,243,33,3,1, + 21,229,93,71,61,37,183,65,211,53,11,151,165,47,5,129,79,101, + 147,169,181,19,95,77,139,197,219,97,239,183,143,9,13,209,23, + 215,53,137,203,19,151,171,133,219,231,3,15,253,225,33,111, + 183,213,169,119,111,15,201,123,121,225,113,113,225,161,165,1, + 139,55,3,93,217,193,97,29,69,231,161,93,69,143,137,9,87,183, + 113,183,73,215,137,89,251,163,41,227,145,57,81,57,11,135,145, + 161,175,159,25,55,167,157,211,97,247,249,23,129,159,71,197, + 127,141,219,5,233,131,217,101,131,33,157,173,69,207,239,81, + 205,11,41,169,65,193,77,201,173,1,221,157,1,15,113,147,137, + 205,225,73,45,49,149,113,253,99,17,119,105,117,129,243,75, + 203,53,29,247,35,247,171,31,199,213,29,251,7,251,187,91,11, + 149,13,205,37,249,137,139,9,7,113,183,205,187,39,3,79,155, + 227,89,185,51,127,63,83,41,133,183,181,127,19,255,219,59,251, + 3,187,57,217,115,217,229,181,185,149,83,115,11, + 123,19,109,165,103,123,219,129,155, + 207,177,9,49,181,231,33,233,67,155,41,9,95,123,65,117,249,85, + 169,129,241,173,251,225,147,165,69,81,239,95,23,83,227,249, + 143,171,193,9,21,57,73,97,57,29,239,151,159,191,47,51,1,223, + 251,251,151,41,119,127,131,33,209,123,53,241,25,31,183,107, + 25,115,39,11,213,239,219,109,185,35,133,123,185,27,55,245,61, + 75,205,213,169,163,63,55,49,83,195,51,31,41,15,203,41,63,127, + 161,5,143,7,199,251,95,75,101,15,43,237,197,117,167,155,21, + 83,205,255,49,101,213,237,135,135,21,73,93,115,7,85,223,237, + 79,89,5,57,239,67,65,201,155,71,85,195,89,181,119,135,147, + 237,173,41,155,67,113,111,21,183,23,103,207,253,69,219,205, + 195,43,197,229,139,177,129,69,97,201,163,189,11,99,91,253, + 239,91,145,19,179,231,121,7,225,237,125,191,119,59,175,237, + 131,79,43,45,205,199,251,153,207,37,179,113,255,107,217,61,7, + 181,247,31,13,113,145,107,233,233,43,79,23,169,137,129,183, + 53,91,55,103,223,87,177,157,79,213,139, + 183,231,205,143,129,243,205,93,59, + 15,89,9,11,47,133,227,75,9,91,19,171,163,79,7,103,5,119,155, + 75,11,71,95,17,13,243,207,187}, + /* [8][*] */ + { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 235,307,495,417,57,151,19,119,375,451, + 55,449,501,53,185,317,17,21,487,13,347,393,15,391,307,189, + 381,71,163,99,467,167,433,337,257,179,47,385,23,117,369,425, + 207,433,301,147,333,85,221,423,49,3,43,229,227,201,383,281, + 229,207,21,343,251,397,173,507,421,443,399,53,345,77,385,317, + 155,187,269,501,19,169,235,415,61,247,183,5,257,401,451,95, + 455,49,489,75,459,377,87,463,155,233,115,429,211,419,143,487, + 195,209,461,193,157,193,363,181,271,445,381,231,135,327,403, + 171,197,181,343,113,313,393,311,415,267,247,425,233,289,55, + 39,247,327,141,5,189,183,27,337,341,327,87,429,357,265,251, + 437,201,29,339,257,377,17,53,327,47,375,393,369,403,125,429, + 257,157,217,85,267,117,337,447,219,501,41,41,193,509,131,207, + 505,421,149,111,177,167,223,291,91,29,305,151,177,337,183, + 361,435,307,507,77,181,507,315,145,423,71,103,493,271,469, + 339,237,437,483,31,219,61,131,391,233,219,69,57,459,225,421, + 7,461,111,451,277,185,193,125,251,199,73,71,7,409,417,149, + 193,53,437,29,467,229,31,35,75,105, + 503,75,317,401,367,131,365,441,433,93,377,405,465,259,283, + 443,143,445,3,461,329,309,77,323,155,347,45,381,315,463,207, + 321,157,109,479,313,345,167,439,307,235,473,79,101,245,19, + 381,251,35,25,107,187,115,113,321,115,445,61,77,293,405,13, + 53,17,171,299,41,79,3,485,331,13,257,59,201,497,81,451,199, + 171,81,253,365,75,451,149,483,81,453,469,485,305,163,401,15, + 91,3,129,35,239,355,211,387,101,299,67,375,405,357,267,363, + 79,83,437,457,39,97,473,289,179,57,23,49,79,71,341,287,95, + 229,271,475,49,241,261,495,353,381,13,291,37,251,105,399,81, + 89,265,507,205,145,331,129,119,503,249,1,289,463,163,443,63, + 123,361,261,49,429,137,355,175,507,59,277,391,25,185,381,197, + 39,5,429,119,247,177,329,465,421,271,467,151,45,429,137,471, + 11,17,409,347,199,463,177,11,51,361,95,497,163,351,127,395, + 511,327,353,49,105,151,321,331,329,509,107,109,303,467,287, + 161,45,385,289,363,331,265,407,37,433,315,343,63,51,185,71, + 27,267, + 503,239,293,245,281,297,75,461,371, + 129,189,189,339,287,111,111,379,93,27,185,347,337,247,507, + 161,231,43,499,73,327,263,331,249,493,37,25,115,3,167,197, + 127,357,497,103,125,191,165,55,101,95,79,351,341,43,125,135, + 173,289,373,133,421,241,281,213,177,363,151,227,145,363,239, + 431,81,397,241,67,291,255,405,421,399,75,399,105,329,41,425, + 7,283,375,475,427,277,209,411,3,137,195,289,509,121,55,147, + 275,251,19,129,285,415,487,491,193,219,403,23,97,65,285,75, + 21,373,261,339,239,495,415,333,107,435,297,213,149,463,199, + 323,45,19,301,121,499,187,229,63,425,99,281,35,125,349,87, + 101,59,195,511,355,73,263,243,101,165,141,11,389,219,187,449, + 447,393,477,305,221,51,355,209,499,479,265,377,145,411,173, + 11,433,483,135,385,341,89,209,391,33,395,319,451,119,341,227, + 375,61,331,493,411,293,47,203,375,167,395,155,5,237,361,489, + 127,21,345,101,371,233,431,109,119,277,125,263,73,135,123,83, + 123,405,69,75,287,401,23,283,393,41,379,431,11,475,505,19, + 365,265,271, + 499,489,443,165,91,83,291,319,199, + 107,245,389,143,137,89,125,281,381,215,131,299,249,375,455, + 43,73,281,217,297,229,431,357,81,357,171,451,481,13,387,491, + 489,439,385,487,177,393,33,71,375,443,129,407,395,127,65,333, + 309,119,197,435,497,373,71,379,509,387,159,265,477,463,449, + 47,353,249,335,505,89,141,55,235,187,87,363,93,363,101,67, + 215,321,331,305,261,411,491,479,65,307,469,415,131,315,487, + 83,455,19,113,163,503,99,499,251,239,81,167,391,255,317,363, + 359,395,419,307,251,267,171,461,183,465,165,163,293,477,223, + 403,389,97,335,357,297,19,469,501,249,85,213,311,265,379,297, + 283,393,449,463,289,159,289,499,407,129,137,221,43,89,403, + 271,75,83,445,453,389,149,143,423,499,317,445,157,137,453, + 163,87,23,391,119,427,323,173,89,259,377,511,249,31,363,229, + 353,329,493,427,57,205,389,91,83,13,219,439,45,35,371,441,17, + 267,501,53,25,333,17,201,475,257,417,345,381,377,55,403,77, + 389,347,363,211,413,419,5,167,219,201,285,425,11,77,269,489, + 281,403,79, + 425,125,81,331,437,271,397,299,475, + 271,249,413,233,261,495,171,69,27,409,21,421,367,81,483,255, + 15,219,365,497,181,75,431,99,325,407,229,281,63,83,493,5,113, + 15,271,37,87,451,299,83,451,311,441,47,455,47,253,13,109,369, + 347,11,409,275,63,441,15}, + /* [9][*] */ + { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 519,307,931,1023,517,771,151,1023, + 539,725,45,927,707,29,125,371,275,279,817,389,453,989,1015, + 29,169,743,99,923,981,181,693,309,227,111,219,897,377,425, + 609,227,19,221,143,581,147,919,127,725,793,289,411,835,921, + 957,443,349,813,5,105,457,393,539,101,197,697,27,343,515,69, + 485,383,855,693,133,87,743,747,475,87,469,763,721,345,479, + 965,527,121,271,353,467,177,245,627,113,357,7,691,725,355, + 889,635,737,429,545,925,357,873,187,351,677,999,921,477,233, + 765,495,81,953,479,89,173,473,131,961,411,291,967,65,511,13, + 805,945,369,827,295,163,835,259,207,331,29,315,999,133,967, + 41,117,677,471,717,881,755,351,723,259,879,455,721,289,149, + 199,805,987,851,423,597,129,11,733,549,153,285,451,559,377, + 109,357,143,693,615,677,701,475,767,85,229,509,547,151,389, + 711,785,657,319,509,99,1007,775,359,697,677,85,497,105,615, + 891,71,449,835,609,377,693,665,627,215,911,503,729,131,19, + 895,199,161,239,633,1013,537,255,23,149,679,1021,595,199,557, + 659,251,829,727,439,495,647,223, + 949,625,87,481,85,799,917,769,949, + 739,115,499,945,547,225,1015,469,737,495,353,103,17,665,639, + 525,75,447,185,43,729,577,863,735,317,99,17,477,893,537,519, + 1017,375,297,325,999,353,343,729,135,489,859,267,141,831,141, + 893,249,807,53,613,131,547,977,131,999,175,31,341,739,467, + 675,241,645,247,391,583,183,973,433,367,131,467,571,309,385, + 977,111,917,935,473,345,411,313,97,149,959,841,839,669,431, + 51,41,301,247,1015,377,329,945,269,67,979,581,643,823,557,91, + 405,117,801,509,347,893,303,227,783,555,867,99,703,111,797, + 873,541,919,513,343,319,517,135,871,917,285,663,301,15,763, + 89,323,757,317,807,309,1013,345,499,279,711,915,411,281,193, + 739,365,315,375,809,469,487,621,857,975,537,939,585,129,625, + 447,129,1017,133,83,3,415,661,53,115,903,49,79,55,385,261, + 345,297,199,385,617,25,515,275,849,401,471,377,661,535,505, + 939,465,225,929,219,955,659,441,117,527,427,515,287,191,33, + 389,197,825,63,417,949,35,571,9,131,609,439,95,19,569,893, + 451,397,971,801, + 125,471,187,257,67,949,621,453,411, + 621,955,309,783,893,597,377,753,145,637,941,593,317,555,375, + 575,175,403,571,555,109,377,931,499,649,653,329,279,271,647, + 721,665,429,957,803,767,425,477,995,105,495,575,687,385,227, + 923,563,723,481,717,111,633,113,369,955,253,321,409,909,367, + 33,967,453,863,449,539,781,911,113,7,219,725,1015,971,1021, + 525,785,873,191,893,297,507,215,21,153,645,913,755,371,881, + 113,903,225,49,587,201,927,429,599,513,97,319,331,833,325, + 887,139,927,399,163,307,803,169,1019,869,537,907,479,335,697, + 479,353,769,787,1023,855,493,883,521,735,297,1011,991,879, + 855,591,415,917,375,453,553,189,841,339,211,601,57,765,745, + 621,209,875,639,7,595,971,263,1009,201,23,77,621,33,535,963, + 661,523,263,917,103,623,231,47,301,549,337,675,189,357,1005, + 789,189,319,721,1005,525,675,539,191,813,917,51,167,415,579, + 755,605,721,837,529,31,327,799,961,279,409,847,649,241,285, + 545,407,161,591,73,313,811,17,663,269,261,37,783,127,917,231, + 577,975,793, + 921,343,751,139,221,79,817,393,545, + 11,781,71,1,699,767,917,9,107,341,587,903,965,599,507,843, + 739,579,397,397,325,775,565,925,75,55,979,931,93,957,857,753, + 965,795,67,5,87,909,97,995,271,875,671,613,33,351,69,811,669, + 729,401,647,241,435,447,721,271,745,53,775,99,343,451,427, + 593,339,845,243,345,17,573,421,517,971,499,435,769,75,203, + 793,985,343,955,735,523,659,703,303,421,951,405,631,825,735, + 433,841,485,49,749,107,669,211,497,143,99,57,277,969,107,397, + 563,551,447,381,187,57,405,731,769,923,955,915,737,595,341, + 253,823,197,321,315,181,885,497,159,571,981,899,785,947,217, + 217,135,753,623,565,717,903,581,955,621,361,869,87,943,907, + 853,353,335,197,771,433,743,195,91,1023,63,301,647,205,485, + 927,1003,987,359,577,147,141,1017,701,273,89,589,487,859,343, + 91,847,341,173,287,1003,289,639,983,685,697,35,701,645,911, + 501,705,873,763,745,657,559,699,315,347,429,197,165,955,859, + 167,303,833,531,473,635,641,195,589,821,205,3,635,371,891, + 249,123, + 77,623,993,401,525,427,71,655,951, + 357,851,899,535,493,323,1003,343,515,859,1017,5,423,315,1011, + 703,41,777,163,95,831,79,975,235,633,723,297,589,317,679,981, + 195,399,1003,121,501,155}, + /* [10][*] */ + { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 7,2011,1001,49,825,415,1441,383,1581, + 623,1621,1319,1387,619,839,217,75,1955,505,281,1629,1379,53, + 1111,1399,301,209,49,155,1647,631,129,1569,335,67,1955,1611, + 2021,1305,121,37,877,835,1457,669,1405,935,1735,665,551,789, + 1543,1267,1027,1,1911,163,1929,67,1975,1681,1413,191,1711, + 1307,401,725,1229,1403,1609,2035,917,921,1789,41,2003,187,67, + 1635,717,1449,277,1903,1179,363,1211,1231,647,1261,1029,1485, + 1309,1149,317,1335,171,243,271,1055,1601,1129,1653,205,1463, + 1681,1621,197,951,573,1697,1265,1321,1805,1235,1853,1307,945, + 1197,1411,833,273,1517,1747,1095,1345,869,57,1383,221,1713, + 335,1751,1141,839,523,1861,1105,389,1177,1877,805,93,1591, + 423,1835,99,1781,1515,1909,1011,303,385,1635,357,973,1781, + 1707,1363,1053,649,1469,623,1429,1241,1151,1055,503,921,3, + 349,1149,293,45,303,877,1565,1583,1001,663,1535,395,1141, + 1481,1797,643,1507,465,2027,1695,367,937,719,545,1991,83,819, + 239,1791,1461,1647,1501,1161,1629,139,1595,1921,1267,1415, + 509,347,777,1083,363,269,1015, + 1809,1105,1429,1471,2019,381,2025, + 1223,827,1733,887,1321,803,1951,1297,1995,833,1107,1135,1181, + 1251,983,1389,1565,273,137,71,735,1005,933,67,1471,551,457, + 1667,1729,919,285,1629,1815,653,1919,1039,531,393,1411,359, + 221,699,1485,471,1357,1715,595,1677,153,1903,1281,215,781, + 543,293,1807,965,1695,443,1985,321,879,1227,1915,839,1945, + 1993,1165,51,557,723,1491,817,1237,947,1215,1911,1225,1965, + 1889,1503,1177,73,1767,303,177,1897,1401,321,921,217,1779, + 327,1889,333,615,1665,1825,1639,237,1205,361,129,1655,983, + 1089,1171,401,677,643,749,303,1407,1873,1579,1491,1393,1247, + 789,763,49,5,1607,1891,735,1557,1909,1765,1777,1127,813,695, + 97,731,1503,1751,333,769,865,693,377,1919,957,1359,1627,1039, + 1783,1065,1665,1917,1947,991,1997,841,459,221,327,1595,1881, + 1269,1007,129,1413,475,1105,791,1983,1359,503,691,659,691, + 343,1375,1919,263,1373,603,1383,297,781,145,285,767,1739, + 1715,715,317,1333,85,831,1615,81,1667,1467,1457,1453,1825, + 109,387,1207,2039,213,1351,1329,1173, + 57,1769,951,183,23,451,1155,1551, + 2037,811,635,1671,1451,863,1499,1673,363,1029,1077,1525,277, + 1023,655,665,1869,1255,965,277,1601,329,1603,1901,395,65, + 1307,2029,21,1321,543,1569,1185,1905,1701,413,2041,1697,725, + 1417,1847,411,211,915,1891,17,1877,1699,687,1089,1973,1809, + 851,1495,1257,63,1323,1307,609,881,1543,177,617,1505,1747, + 1537,925,183,77,1723,1877,1703,397,459,521,257,1177,389,1947, + 1553,1583,1831,261,485,289,1281,1543,1591,1123,573,821,1065, + 1933,1373,2005,905,207,173,1573,1597,573,1883,1795,1499,1743, + 553,335,333,1645,791,871,1157,969,557,141,223,1129,1685,423, + 1069,391,99,95,1847,531,1859,1833,1833,341,237,1997,1799,409, + 431,1917,363,335,1039,1085,1657,1975,1527,1111,659,389,899, + 595,1439,1861,1979,1569,1087,1009,165,1895,1481,1583,29,1193, + 1673,1075,301,1081,1377,1747,1497,1103,1789,887,739,1577,313, + 1367,1299,1801,1131,1837,73,1865,1065,843,635,55,1655,913, + 1037,223,1871,1161,461,479,511,1721,1107,389,151,35,375,1099, + 937,1185,1701,769,639,1633, + 1609,379,1613,2031,685,289,975,671, + 1599,1447,871,647,99,139,1427,959,89,117,841,891,1959,223, + 1697,1145,499,1435,1809,1413,1445,1675,171,1073,1349,1545, + 2039,1027,1563,859,215,1673,1919,1633,779,411,1845,1477,1489, + 447,1545,351,1989,495,183,1639,1385,1805,1097,1249,1431,1571, + 591,697,1509,709,31,1563,165,513,1425,1299,1081,145,1841, + 1211,941,609,845,1169,1865,1593,347,293,1277,157,211,93,1679, + 1799,527,41,473,563,187,1525,575,1579,857,703,1211,647,709, + 981,285,697,163,981,153,1515,47,1553,599,225,1147,381,135, + 821,1965,609,1033,983,503,1117,327,453,2005,1257,343,1649, + 1199,599,1877,569,695,1587,1475,187,973,233,511,51,1083,665, + 1321,531,1875,1939,859,1507,1979,1203,1965,737,921,1565,1943, + 819,223,365,167,1705,413,1577,745,1573,655,1633,1003,91,1123, + 477,1741,1663,35,715,37,1513,815,941,1379,263,1831,1735,1111, + 1449,353,1941,1655,1349,877,285,1723,125,1753,985,723,175, + 439,791,1051,1261,717,1555,1757,1777,577,1583,1957,873,331, + 1163,313,1,1963,963,1905,821, + 1677,185,709,545,1723,215,1885, + 1249,583,1803,839,885,485,413,1767,425,129,1035,329,1263, + 1881,1779,1565,359,367,453,707,1419,831,1889,887,1871,1869, + 747,223,1547,1799,433,1441,553,2021,1303,1505,1735,1619,1065, + 1161,2047,347,867,881,1447,329,781,1065,219,589,645,1257, + 1833,749,1841,1733,1179,1191,1025,1639,1955,1423,1685,1711, + 493,549,783,1653,397,895,233,759,1505,677,1449,1573,1297, + 1821,1691,791,289,1187,867,1535,575,183}, + /* [11][*] */ + { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 3915,97,3047,937,2897,953,127,1201, + 3819,193,2053,3061,3759,1553,2007,2493,603,3343,3751,1059, + 783,1789,1589,283,1093,3919,2747,277,2605,2169,2905,721,4069, + 233,261,1137,3993,3619,2881,1275,3865,1299,3757,1193,733,993, + 1153,2945,3163,3179,437,271,3493,3971,1005,2615,2253,1131, + 585,2775,2171,2383,2937,2447,1745,663,1515,3767,2709,1767, + 3185,3017,2815,1829,87,3341,793,2627,2169,1875,3745,367,3783, + 783,827,3253,2639,2955,3539,1579,2109,379,2939,3019,1999, + 2253,2911,3733,481,1767,1055,4019,4085,105,1829,2097,2379, + 1567,2713,737,3423,3941,2659,3961,1755,3613,1937,1559,2287, + 2743,67,2859,325,2601,1149,3259,2403,3947,2011,175,3389,3915, + 1315,2447,141,359,3609,3933,729,2051,1755,2149,2107,1741, + 1051,3681,471,1055,845,257,1559,1061,2803,2219,1315,1369, + 3211,4027,105,11,1077,2857,337,3553,3503,3917,2665,3823,3403, + 3711,2085,1103,1641,701,4095,2883,1435,653,2363,1597,767,869, + 1825,1117,1297,501,505,149,873,2673,551,1499,2793,3277,2143, + 3663,533,3991,575,1877,1009,3929,473,3009,2595,3249,675,3593, + 2453,1567,973,595,1335,1715,589,85, + 2265,3069,461,1659,2627,1307,1731,1501,1699,3545,3803,2157, + 453,2813,2047,2999,3841,2361,1079,573,69,1363,1597,3427,2899, + 2771,1327,1117,1523,3521,2393,2537,1979,3179,683,2453,453, + 1227,779,671,3483,2135,3139,3381,3945,57,1541,3405,3381,2371, + 2879,1985,987,3017,3031,3839,1401,3749,2977,681,1175,1519, + 3355,907,117,771,3741,3337,1743,1227,3335,2755,1909,3603, + 2397,653,87,2025,2617,3257,287,3051,3809,897,2215,63,2043, + 1757,3671,297,3131,1305,293,3865,3173,3397,2269,3673,717, + 3041,3341,3595,3819,2871,3973,1129,513,871,1485,3977,2473, + 1171,1143,3063,3547,2183,3993,133,2529,2699,233,2355,231, + 3241,611,1309,3829,1839,1495,301,1169,1613,2673,243,3601, + 3669,2813,2671,2679,3463,2477,1795,617,2317,1855,1057,1703, + 1761,2515,801,1205,1311,473,3963,697,1221,251,381,3887,1761, + 3093,3721,2079,4085,379,3601,3845,433,1781,29,1897,1599,2163, + 75,3475,3957,1641,3911,2959,2833,1279,1099,403,799,2183,2699, + 1711,2037,727,289,1785,1575,3633,2367,1261,3953,1735,171, + 1959, + 2867,859,2951,3211,15,1279,1323,599, + 1651,3951,1011,315,3513,3351,1725,3793,2399,287,4017,3571, + 1007,541,3115,429,1585,1285,755,1211,3047,915,3611,2697,2129, + 3669,81,3939,2437,915,779,3567,3701,2479,3807,1893,3927,2619, + 2543,3633,2007,3857,3837,487,1769,3759,3105,2727,3155,2479, + 1341,1657,2767,2541,577,2105,799,17,2871,3637,953,65,69,2897, + 3841,3559,4067,2335,3409,1087,425,2813,1705,1701,1237,821, + 1375,3673,2693,3925,1541,1871,2285,847,4035,1101,2029,855, + 2733,2503,121,2855,1069,3463,3505,1539,607,1349,575,2301, + 2321,1101,333,291,2171,4085,2173,2541,1195,925,4039,1379,699, + 1979,275,953,1755,1643,325,101,2263,3329,3673,3413,1977,2727, + 2313,1419,887,609,2475,591,2613,2081,3805,3435,2409,111,3557, + 3607,903,231,3059,473,2959,2925,3861,2043,3887,351,2865,369, + 1377,2639,1261,3625,3279,2201,2949,3049,449,1297,897,1891, + 411,2773,749,2753,1825,853,2775,3547,3923,3923,987,3723,2189, + 3877,3577,297,2763,1845,3083,2951,483,2169,3985,245,3655, + 3441,1023,235,835,3693,3585,327,1003,543,3059,2637, + 2923,87,3617,1031,1043,903,2913, + 2177,2641,3279,389,2009,525,4085,3299,987,2409,813,2683,373, + 2695,3775,2375,1119,2791,223,325,587,1379,2877,2867,3793,655, + 831,3425,1663,1681,2657,1865,3943,2977,1979,2271,3247,1267, + 1747,811,159,429,2001,1195,3065,553,1499,3529,1081,2877,3077, + 845,1793,2409,3995,2559,4081,1195,2955,1117,1409,785,287, + 1521,1607,85,3055,3123,2533,2329,3477,799,3683,3715,337,3139, + 3311,431,3511,2299,365,2941,3067,1331,1081,1097,2853,2299, + 495,1745,749,3819,619,1059,3559,183,3743,723,949,3501,733, + 2599,3983,3961,911,1899,985,2493,1795,653,157,433,2361,3093, + 3119,3679,2367,1701,1445,1321,2397,1241,3305,3985,2349,4067, + 3805,3073,2837,1567,3783,451,2441,1181,487,543,1201,3735, + 2517,733,1535,2175,3613,3019}, + /* [12][*] */ + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2319,653,1379,1675,1951,7075,2087, + 7147,1427,893,171,2019,7235,5697,3615,1961,7517,6849,2893, + 1883,2863,2173,4543,73,381,3893,6045,1643,7669,1027,1549, + 3983,1985,6589,7497,2745,2375,7047,1117,1171,1975,5199,3915, + 3695,8113,4303,3773,7705,6855,1675,2245,2817,1719,569,1021, + 2077,5945,1833,2631,4851,6371,833,7987,331,1899,8093,6719, + 6903,5903,5657,5007,2689,6637,2675,1645,1819,689,6709,7717, + 6295,7013,7695,3705,7069,2621,3631,6571,6259,7261,3397,7645, + 1115,4753,2047,7579,2271,5403,4911,7629,4225,1209,6955,6951, + 1829,5579,5231,1783,4285,7425,599,5785,3275,5643,2263,657, + 6769,6261,1251,3249,4447,4111,3991,1215,131,4397,3487,7585, + 5565,7199,3573,7105,7409,1671,949,3889,5971,3333,225,3647, + 5403,3409,7459,6879,5789,6567,5581,4919,1927,4407,8085,4691, + 611,3005,591,753,589,171,5729,5891,1033,3049,6567,5257,8003, + 1757,4489,4923,6379,5171,1757,689,3081,1389,4113,455,2761, + 847,7575,5829,633,6629,1103,7635,803,6175,6587,2711,3879,67, + 1179,4761,7281,1557,3379,2459,4273,4127,7147,35, + 3549,395,3735,5787,4179,5889,5057, + 7473,4713,2133,2897,1841,2125,1029,1695,6523,1143,5105,7133, + 3351,2775,3971,4503,7589,5155,4305,1641,4717,2427,5617,1267, + 399,5831,4305,4241,3395,3045,4899,1713,171,411,7099,5473, + 5209,1195,1077,1309,2953,7343,4887,3229,6759,6721,6775,675, + 4039,2493,7511,3269,4199,6625,7943,2013,4145,667,513,2303, + 4591,7941,2741,987,8061,3161,5951,1431,831,5559,7405,1357, + 4319,4235,5421,2559,4415,2439,823,1725,6219,4903,6699,5451, + 349,7703,2927,7809,6179,1417,5987,3017,4983,3479,4525,4643, + 4911,227,5475,2287,5581,6817,1937,1421,4415,7977,1789,3907, + 6815,6789,6003,5609,4507,337,7427,7943,3075,6427,1019,7121, + 4763,81,3587,2929,1795,8067,2415,1265,4025,5599,4771,3025, + 2313,6129,7611,6881,5253,4413,7869,105,3173,1629,2537,1023, + 4409,7209,4413,7107,7469,33,1955,2881,5167,6451,4211,179, + 5573,7879,3387,7759,5455,7157,1891,5683,5689,6535,3109,6555, + 6873,1249,4251,6437,49,2745,1201,7327,4179,6783,623,2779, + 5963,2585,6927,5333,4033,285,7467,4443,4917,3, + 4319,5517,3449,813,5499,2515,5771, + 3357,2073,4395,4925,2643,7215,5817,1199,1597,1619,7535,4833, + 609,4797,8171,6847,793,6757,8165,3371,2431,5235,4739,7703, + 7223,6525,5891,5605,4433,3533,5267,5125,5037,225,6717,1121, + 5741,2013,4327,4839,569,5227,7677,4315,2391,5551,859,3627, + 6377,3903,4311,6527,7573,4905,7731,1909,1555,3279,1949,1887, + 6675,5509,2033,5473,3539,5033,5935,6095,4761,1771,1271,1717, + 4415,5083,6277,3147,7695,2461,4783,4539,5833,5583,651,1419, + 2605,5511,3913,5795,2333,2329,4431,3725,6069,2699,7055,6879, + 1017,3121,2547,4603,2385,6915,6103,5669,7833,2001,4287,6619, + 955,2761,5711,6291,3415,3909,2841,5627,4939,7671,6059,6275, + 6517,1931,4583,7301,1267,7509,1435,2169,6939,3515,2985,2787, + 2123,1969,3307,353,4359,7059,5273,5873,6657,6765,6229,3179, + 1583,6237,2155,371,273,7491,3309,6805,3015,6831,7819,713, + 4747,3935,4109,1311,709,3089,7059,4247,2989,1509,4919,1841, + 3045,3821,6929,4655,1333,6429,6649,2131,5265,1051,261,8057, + 3379,2179,1993,5655,3063,6381, + 3587,7417,1579,1541,2107,5085,2873, + 6141,955,3537,2157,841,1999,1465,5171,5651,1535,7235,4349, + 1263,1453,1005,6893,2919,1947,1635,3963,397,969,4569,655, + 6737,2995,7235,7713,973,4821,2377,1673,1,6541} + }; + + return sobol_minit[degree][dim]; + } + +}; + +} // namespace sbl + + +// sobol_lattice sets up the random-number generator to produce a Sobol +// sequence of at most max dims-dimensional quasi-random vectors. +// Adapted from ACM TOMS algorithm 659, see + +// http://doi.acm.org/10.1145/42288.214372 + +template +struct sobol_lattice +{ + typedef IntType value_type; + + BOOST_STATIC_CONSTANT(int, bit_count = std::numeric_limits::digits); + + // default copy c-tor is fine + + explicit sobol_lattice(std::size_t dimension) + { + resize(dimension); + } + + void resize(std::size_t dimension) + { + if (dimension > sbl::sobol_tables::max_dimension) + { + throw std::invalid_argument("The Sobol quasi-random number generator only supports up to " + BOOST_PP_STRINGIZE(BOOST_RANDOM_SOBOL_MAX_DIMENSION) " dimensions."); + } + + // Initialize the bit array + bits.resize(boost::extents[bit_count][dimension]); + + // Initialize direction table in dimension 0 + for (int k = 0; k < bit_count; ++k) + bits[k][0] = static_cast(1); + + // Initialize in remaining dimensions. + for (std::size_t dim = 1; dim < dimension; ++dim) + { + const int poly = sbl::sobol_tables::polynomial(dim-1); + if (static_cast(poly) > + static_cast(std::numeric_limits::max())) { + boost::throw_exception( std::range_error("sobol: polynomial value outside the given IntType range") ); + } + const int degree = multiprecision::detail::find_msb(poly); // integer log2(poly) + + // set initial values of m from table + for (int k = 0; k < degree; ++k) + bits[k][dim] = sbl::sobol_tables::vinit(k, dim-1); + + // Calculate remaining elements for this dimension, + // as explained in Bratley+Fox, section 2. + for (int j = degree; j < bit_count; ++j) + { + int p_i = poly; + bits[j][dim] = bits[j - degree][dim]; + for (int k = 0; k < degree; ++k) + { + int rem = degree - k; + bits[j][dim] ^= ((p_i & 1) * bits[j-rem][dim]) << rem; + p_i >>= 1; + } + } + } + + // Multiply columns by appropriate power of 2. + IntType p = static_cast(2); + for (int j = bit_count-1-1; j >= 0; --j, p <<= 1) + for (std::size_t dim = 0; dim != dimension; ++dim) + bits[j][dim] *= p; + } + + value_type operator()(int i, int j) const + { + return bits[i][j]; + } + +private: + boost::multi_array bits; +}; + +} // namespace detail +/** @endcond */ + +//!class template sobol implements a quasi-random number generator as described in +//! \blockquote +//![Bratley+Fox, TOMS 14, 88 (1988)] +//!and [Antonov+Saleev, USSR Comput. Maths. Math. Phys. 19, 252 (1980)] +//! \endblockquote +//! +//!\attention \b Important: This implementation supports up to 40 dimensions. +//! +//!In the following documentation @c X denotes the concrete class of the template +//!sobol returning objects of type @c IntType, u and v are the values of @c X. +//! +//!Some member functions may throw exceptions of type @c std::overflow_error. This +//!happens when the quasi-random domain is exhausted and the generator cannot produce +//!any more values. The length of the low discrepancy sequence is given by +//! \f$L=Dimension \times 2^{digits}\f$, where digits = std::numeric_limits::digits. +//! +//! \copydoc friendfunctions +template +class sobol : public detail::gray_coded_qrng_base< + sobol + , detail::sobol_lattice + > +{ + typedef sobol self_t; + typedef detail::sobol_lattice lattice_t; + typedef detail::gray_coded_qrng_base base_t; + +public: + typedef IntType result_type; + + /** @copydoc boost::random::niederreiter_base2::min() */ + static result_type min /** @cond */ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ () { return 0u; } + + /** @copydoc boost::random::niederreiter_base2::max() */ + static result_type max /** @cond */ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ () { return std::numeric_limits::max(); } + + //!Effects: Constructs the default s-dimensional Sobol quasi-random number generator. + //! + //!Throws: bad_alloc, invalid_argument, range_error. + explicit sobol(std::size_t s) + : base_t(s) + {} + + // default copy c-tor is fine + + /** @copydoc boost::random::niederreiter_base2::seed() */ + void seed() + { + base_t::reset_state(); + } + + /** @copydoc boost::random::niederreiter_base2::seed(std::size_t) */ + void seed(std::size_t init) + { + base_t::seed(init, "sobol::seed"); + } + + //=========================Doxygen needs this!============================== + + //!Requirements: *this is mutable. + //! + //!Returns: Returns a successive element of an s-dimensional + //!(s = X::dimension()) vector at each invocation. When all elements are + //!exhausted, X::operator() begins anew with the starting element of a + //!subsequent s-dimensional vector. + //! + //!Throws: overflow_error. + + // Fixed in Doxygen 1.7.0 -- id 612458: Fixed problem handling @copydoc for function operators. + result_type operator()() + { + return base_t::operator()(); + } + + /** @copydoc boost::random::niederreiter_base2::discard(std::size_t) */ + void discard(std::size_t z) + { + base_t::discard(z); + } +}; + +} // namespace random + +typedef random::sobol sobol; + +} // namespace boost + +#endif // BOOST_RANDOM_SOBOL_HPP diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 25424bc..13a7643 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -55,6 +55,10 @@ run test_lagged_fibonacci23209.cpp /boost//unit_test_framework ; run test_lagged_fibonacci44497.cpp /boost//unit_test_framework ; run test_zero_seed.cpp /boost//unit_test_framework ; +run niederreiter_base2_validate.cpp /boost//unit_test_framework ; +run sobol_validate.cpp /boost//unit_test_framework ; +run faure_validate.cpp /boost//unit_test_framework ; + # Disable by default. These don't add much and the larger # ones can overflow the stack. explicit test_lagged_fibonacci1279 test_lagged_fibonacci2281 diff --git a/test/faure_validate.cpp b/test/faure_validate.cpp new file mode 100644 index 0000000..0e87539 --- /dev/null +++ b/test/faure_validate.cpp @@ -0,0 +1,375 @@ +// Copyright Justinas Vygintas Daugmaudis, 2010. +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) + +#include + +#include + +#define BOOST_TEST_MAIN +#include + +#include "test_qrng_functions.hpp" + +// +// DESCRIPTION: +// ~~~~~~~~~~~~ +// +// This file tests the faure quasi-random number generator. +// These tests compare our results with values produced by the original +// version of ACM TOMS Algorithm 647, which is available in the +// TOMS subdirectory in http://www.netlib.org +// +// For independently generated datasets look at http://people.sc.fsu.edu/~jburkardt/datasets/faure/ + + +// Spatial dimension: 2 +// N: 100 +// Base: 2 +// Vectors skipped: 15 +static const double faure_02_100[100][2] = +{ + { 0.9375000000, 0.0625000000 }, + { 0.0312500000, 0.5312500000 }, + { 0.5312500000, 0.0312500000 }, + { 0.2812500000, 0.2812500000 }, + { 0.7812500000, 0.7812500000 }, + { 0.1562500000, 0.1562500000 }, + { 0.6562500000, 0.6562500000 }, + { 0.4062500000, 0.9062500000 }, + { 0.9062500000, 0.4062500000 }, + { 0.0937500000, 0.4687500000 }, + { 0.5937500000, 0.9687500000 }, + { 0.3437500000, 0.7187500000 }, + { 0.8437500000, 0.2187500000 }, + { 0.2187500000, 0.8437500000 }, + { 0.7187500000, 0.3437500000 }, + { 0.4687500000, 0.0937500000 }, + { 0.9687500000, 0.5937500000 }, + { 0.0156250000, 0.7968750000 }, + { 0.5156250000, 0.2968750000 }, + { 0.2656250000, 0.0468750000 }, + { 0.7656250000, 0.5468750000 }, + { 0.1406250000, 0.4218750000 }, + { 0.6406250000, 0.9218750000 }, + { 0.3906250000, 0.6718750000 }, + { 0.8906250000, 0.1718750000 }, + { 0.0781250000, 0.2343750000 }, + { 0.5781250000, 0.7343750000 }, + { 0.3281250000, 0.9843750000 }, + { 0.8281250000, 0.4843750000 }, + { 0.2031250000, 0.6093750000 }, + { 0.7031250000, 0.1093750000 }, + { 0.4531250000, 0.3593750000 }, + { 0.9531250000, 0.8593750000 }, + { 0.0468750000, 0.2656250000 }, + { 0.5468750000, 0.7656250000 }, + { 0.2968750000, 0.5156250000 }, + { 0.7968750000, 0.0156250000 }, + { 0.1718750000, 0.8906250000 }, + { 0.6718750000, 0.3906250000 }, + { 0.4218750000, 0.1406250000 }, + { 0.9218750000, 0.6406250000 }, + { 0.1093750000, 0.7031250000 }, + { 0.6093750000, 0.2031250000 }, + { 0.3593750000, 0.4531250000 }, + { 0.8593750000, 0.9531250000 }, + { 0.2343750000, 0.0781250000 }, + { 0.7343750000, 0.5781250000 }, + { 0.4843750000, 0.8281250000 }, + { 0.9843750000, 0.3281250000 }, + { 0.0078125000, 0.6640625000 }, + { 0.5078125000, 0.1640625000 }, + { 0.2578125000, 0.4140625000 }, + { 0.7578125000, 0.9140625000 }, + { 0.1328125000, 0.0390625000 }, + { 0.6328125000, 0.5390625000 }, + { 0.3828125000, 0.7890625000 }, + { 0.8828125000, 0.2890625000 }, + { 0.0703125000, 0.3515625000 }, + { 0.5703125000, 0.8515625000 }, + { 0.3203125000, 0.6015625000 }, + { 0.8203125000, 0.1015625000 }, + { 0.1953125000, 0.9765625000 }, + { 0.6953125000, 0.4765625000 }, + { 0.4453125000, 0.2265625000 }, + { 0.9453125000, 0.7265625000 }, + { 0.0390625000, 0.1328125000 }, + { 0.5390625000, 0.6328125000 }, + { 0.2890625000, 0.8828125000 }, + { 0.7890625000, 0.3828125000 }, + { 0.1640625000, 0.5078125000 }, + { 0.6640625000, 0.0078125000 }, + { 0.4140625000, 0.2578125000 }, + { 0.9140625000, 0.7578125000 }, + { 0.1015625000, 0.8203125000 }, + { 0.6015625000, 0.3203125000 }, + { 0.3515625000, 0.0703125000 }, + { 0.8515625000, 0.5703125000 }, + { 0.2265625000, 0.4453125000 }, + { 0.7265625000, 0.9453125000 }, + { 0.4765625000, 0.6953125000 }, + { 0.9765625000, 0.1953125000 }, + { 0.0234375000, 0.3984375000 }, + { 0.5234375000, 0.8984375000 }, + { 0.2734375000, 0.6484375000 }, + { 0.7734375000, 0.1484375000 }, + { 0.1484375000, 0.7734375000 }, + { 0.6484375000, 0.2734375000 }, + { 0.3984375000, 0.0234375000 }, + { 0.8984375000, 0.5234375000 }, + { 0.0859375000, 0.5859375000 }, + { 0.5859375000, 0.0859375000 }, + { 0.3359375000, 0.3359375000 }, + { 0.8359375000, 0.8359375000 }, + { 0.2109375000, 0.2109375000 }, + { 0.7109375000, 0.7109375000 }, + { 0.4609375000, 0.9609375000 }, + { 0.9609375000, 0.4609375000 }, + { 0.0546875000, 0.9296875000 }, + { 0.5546875000, 0.4296875000 }, + { 0.3046875000, 0.1796875000 } +}; + +// Spatial dimension: 7 +// N: 100 +// Base: 7 +// Vectors skipped: 2400 +static const double faure_07_100[100][7] = +{ + { 0.9995835069, 0.4602249063, 0.9412744690, 0.3202832153, 0.9850062474, 0.8334027489, 0.1103706789 }, + { 0.0000594990, 0.2437079788, 0.3765692866, 0.6493722854, 0.6685309692, 0.3582435890, 0.2228833224 }, + { 0.1429166419, 0.3865651217, 0.5194264295, 0.7922294282, 0.8113881121, 0.5011007318, 0.3657404653 }, + { 0.2857737847, 0.5294222645, 0.6622835723, 0.9350865711, 0.9542452550, 0.6439578747, 0.5085976081 }, + { 0.4286309276, 0.6722794074, 0.8051407152, 0.0779437139, 0.0971023978, 0.7868150176, 0.6514547510 }, + { 0.5714880704, 0.8151365502, 0.9479978580, 0.2208008568, 0.2399595407, 0.9296721604, 0.7943118939 }, + { 0.7143452133, 0.9579936931, 0.0908550009, 0.3636579996, 0.3828166835, 0.0725293033, 0.9371690367 }, + { 0.8572023562, 0.1008508360, 0.2337121437, 0.5065151425, 0.5256738264, 0.2153864461, 0.0800261796 }, + { 0.0204676623, 0.4069732849, 0.6826917356, 0.0983518772, 0.2603677039, 0.0929374665, 0.1004343428 }, + { 0.1633248051, 0.5498304278, 0.8255488784, 0.2412090201, 0.4032248468, 0.2357946094, 0.2432914857 }, + { 0.3061819480, 0.6926875707, 0.9684060213, 0.3840661629, 0.5460819896, 0.3786517522, 0.3861486285 }, + { 0.4490390909, 0.8355447135, 0.1112631642, 0.5269233058, 0.6889391325, 0.5215088951, 0.5290057714 }, + { 0.5918962337, 0.9784018564, 0.2541203070, 0.6697804486, 0.8317962754, 0.6643660380, 0.6718629143 }, + { 0.7347533766, 0.1212589992, 0.3969774499, 0.8126375915, 0.9746534182, 0.8072231808, 0.8147200571 }, + { 0.8776105194, 0.2641161421, 0.5398345927, 0.9554947343, 0.1175105611, 0.9500803237, 0.9575772000 }, + { 0.0408758255, 0.5702385911, 0.9888141846, 0.5473314690, 0.8522044386, 0.8276313441, 0.9779853632 }, + { 0.1837329684, 0.7130957339, 0.1316713274, 0.6901886119, 0.9950615815, 0.9704884869, 0.1208425061 }, + { 0.3265901113, 0.8559528768, 0.2745284703, 0.8330457547, 0.1379187243, 0.1133456298, 0.2636996490 }, + { 0.4694472541, 0.9988100196, 0.4173856131, 0.9759028976, 0.2807758672, 0.2562027727, 0.4065567918 }, + { 0.6123043970, 0.1416671625, 0.5602427560, 0.1187600405, 0.4236330101, 0.3990599155, 0.5494139347 }, + { 0.7551615398, 0.2845243053, 0.7030998989, 0.2616171833, 0.5664901529, 0.5419170584, 0.6922710775 }, + { 0.8980186827, 0.4273814482, 0.8459570417, 0.4044743262, 0.7093472958, 0.6847742012, 0.8351282204 }, + { 0.0612839888, 0.5906467543, 0.1520794907, 0.9963110609, 0.3011840305, 0.5623252216, 0.8555363836 }, + { 0.2041411317, 0.7335038972, 0.2949366335, 0.1391682037, 0.4440411733, 0.7051823645, 0.9983935265 }, + { 0.3469982745, 0.8763610400, 0.4377937764, 0.2820253466, 0.5868983162, 0.8480395073, 0.1412506694 }, + { 0.4898554174, 0.0192181829, 0.5806509193, 0.4248824894, 0.7297554590, 0.9908966502, 0.2841078122 }, + { 0.6327125602, 0.1620753258, 0.7235080621, 0.5677396323, 0.8726126019, 0.1337537931, 0.4269649551 }, + { 0.7755697031, 0.3049324686, 0.8663652050, 0.7105967752, 0.0154697447, 0.2766109359, 0.5698220979 }, + { 0.9184268460, 0.4477896115, 0.0092223478, 0.8534539180, 0.1583268876, 0.4194680788, 0.7126792408 }, + { 0.0816921521, 0.7539120605, 0.4582019397, 0.3024335098, 0.8930207652, 0.1541619563, 0.5902302612 }, + { 0.2245492949, 0.8967692033, 0.6010590825, 0.4452906527, 0.0358779080, 0.2970190992, 0.7330874041 }, + { 0.3674064378, 0.0396263462, 0.7439162254, 0.5881477956, 0.1787350509, 0.4398762420, 0.8759445469 }, + { 0.5102635807, 0.1824834890, 0.8867733682, 0.7310049384, 0.3215921937, 0.5827333849, 0.0188016898 }, + { 0.6531207235, 0.3253406319, 0.0296305111, 0.8738620813, 0.4644493366, 0.7255905278, 0.1616588326 }, + { 0.7959778664, 0.4681977747, 0.1724876540, 0.0167192241, 0.6073064794, 0.8684476706, 0.3045159755 }, + { 0.9388350092, 0.6110549176, 0.3153447968, 0.1595763670, 0.7501636223, 0.0113048135, 0.4473731183 }, + { 0.1021003153, 0.9171773666, 0.7643243886, 0.7514131017, 0.4848574999, 0.8888558339, 0.4677812816 }, + { 0.2449574582, 0.0600345094, 0.9071815315, 0.8942702445, 0.6277146427, 0.0317129767, 0.6106384245 }, + { 0.3878146011, 0.2028916523, 0.0500386744, 0.0371273874, 0.7705717856, 0.1745701196, 0.7534955673 }, + { 0.5306717439, 0.3457487951, 0.1928958172, 0.1799845303, 0.9134289284, 0.3174272625, 0.8963527102 }, + { 0.6735288868, 0.4886059380, 0.3357529601, 0.3228416731, 0.0562860713, 0.4602844053, 0.0392098530 }, + { 0.8163860296, 0.6314630809, 0.4786101029, 0.4656988160, 0.1991432141, 0.6031415482, 0.1820669959 }, + { 0.9592431725, 0.7743202237, 0.6214672458, 0.6085559588, 0.3420003570, 0.7459986910, 0.3249241388 }, + { 0.1225084786, 0.0804426727, 0.0704468376, 0.2003926935, 0.0766942345, 0.6235497114, 0.3453323020 }, + { 0.2653656215, 0.2232998156, 0.2133039805, 0.3432498364, 0.2195513774, 0.7664068543, 0.4881894449 }, + { 0.4082227643, 0.3661569584, 0.3561611233, 0.4861069792, 0.3624085203, 0.9092639971, 0.6310465877 }, + { 0.5510799072, 0.5090141013, 0.4990182662, 0.6289641221, 0.5052656631, 0.0521211400, 0.7739037306 }, + { 0.6939370500, 0.6518712441, 0.6418754091, 0.7718212649, 0.6481228060, 0.1949782829, 0.9167608734 }, + { 0.8367941929, 0.7947283870, 0.7847325519, 0.9146784078, 0.7909799488, 0.3378354257, 0.0596180163 }, + { 0.9796513358, 0.9375855298, 0.9275896948, 0.0575355507, 0.9338370917, 0.4806925686, 0.2024751592 }, + { 0.0029749509, 0.4098887368, 0.8896888201, 0.9175938597, 0.9775688701, 0.9938121021, 0.3074314274 }, + { 0.1458320938, 0.5527458797, 0.0325459630, 0.0604510026, 0.1204260130, 0.1366692450, 0.4502885702 }, + { 0.2886892366, 0.6956030226, 0.1754031058, 0.2033081454, 0.2632831558, 0.2795263878, 0.5931457131 }, + { 0.4315463795, 0.8384601654, 0.3182602487, 0.3461652883, 0.4061402987, 0.4223835307, 0.7360028560 }, + { 0.5744035223, 0.9813173083, 0.4611173916, 0.4890224311, 0.5489974415, 0.5652406735, 0.8788599988 }, + { 0.7172606652, 0.1241744511, 0.6039745344, 0.6318795740, 0.6918545844, 0.7080978164, 0.0217171417 }, + { 0.8601178081, 0.2670315940, 0.7468316773, 0.7747367168, 0.8347117273, 0.8509549592, 0.1645742845 }, + { 0.0233831142, 0.4302969001, 0.1958112691, 0.3665734515, 0.5694056048, 0.5856488368, 0.1849824478 }, + { 0.1662402570, 0.5731540430, 0.3386684120, 0.5094305944, 0.7122627477, 0.7285059797, 0.3278395906 }, + { 0.3090973999, 0.7160111858, 0.4815255548, 0.6522877373, 0.8551198905, 0.8713631225, 0.4706967335 }, + { 0.4519545428, 0.8588683287, 0.6243826977, 0.7951448801, 0.9979770334, 0.0142202654, 0.6135538764 }, + { 0.5948116856, 0.0017254715, 0.7672398405, 0.9380020230, 0.1408341762, 0.1570774082, 0.7564110192 }, + { 0.7376688285, 0.1445826144, 0.9100969834, 0.0808591658, 0.2836913191, 0.2999345511, 0.8992681621 }, + { 0.8805259713, 0.2874397572, 0.0529541263, 0.2237163087, 0.4265484620, 0.4427916939, 0.0421253049 }, + { 0.0437912774, 0.5935622062, 0.5019337181, 0.8155530434, 0.0183851966, 0.3203427143, 0.0625334682 }, + { 0.1866484203, 0.7364193491, 0.6447908610, 0.9584101862, 0.1612423395, 0.4631998572, 0.2053906111 }, + { 0.3295055632, 0.8792764919, 0.7876480038, 0.1012673291, 0.3040994824, 0.6060570001, 0.3482477539 }, + { 0.4723627060, 0.0221336348, 0.9305051467, 0.2441244719, 0.4469566252, 0.7489141429, 0.4911048968 }, + { 0.6152198489, 0.1649907777, 0.0733622895, 0.3869816148, 0.5898137681, 0.8917712858, 0.6339620396 }, + { 0.7580769917, 0.3078479205, 0.2162194324, 0.5298387577, 0.7326709109, 0.0346284286, 0.7768191825 }, + { 0.9009341346, 0.4507050634, 0.3590765752, 0.6726959005, 0.8755280538, 0.1774855715, 0.9196763253 }, + { 0.0641994407, 0.7568275123, 0.8080561671, 0.2645326352, 0.6102219313, 0.0550365919, 0.9400844886 }, + { 0.2070565836, 0.8996846552, 0.9509133099, 0.4073897781, 0.7530790742, 0.1978937348, 0.0829416315 }, + { 0.3499137264, 0.0425417981, 0.0937704528, 0.5502469209, 0.8959362171, 0.3407508776, 0.2257987743 }, + { 0.4927708693, 0.1853989409, 0.2366275956, 0.6931040638, 0.0387933599, 0.4836080205, 0.3686559172 }, + { 0.6356280121, 0.3282560838, 0.3794847385, 0.8359612066, 0.1816505028, 0.6264651633, 0.5115130600 }, + { 0.7784851550, 0.4711132266, 0.5223418814, 0.9788183495, 0.3245076456, 0.7693223062, 0.6543702029 }, + { 0.9213422979, 0.6139703695, 0.6651990242, 0.1216754924, 0.4673647885, 0.9121794490, 0.7972273457 }, + { 0.0846076040, 0.9200928185, 0.1141786161, 0.7135122270, 0.2020586660, 0.7897304694, 0.8176355090 }, + { 0.2274647468, 0.0629499613, 0.2570357589, 0.8563693699, 0.3449158089, 0.9325876123, 0.9604926519 }, + { 0.3703218897, 0.2058071042, 0.3998929018, 0.9992265128, 0.4877729517, 0.0754447552, 0.1033497947 }, + { 0.5131790325, 0.3486642470, 0.5427500446, 0.1420836556, 0.6306300946, 0.2183018980, 0.2462069376 }, + { 0.6560361754, 0.4915213899, 0.6856071875, 0.2849407985, 0.7734872375, 0.3611590409, 0.3890640804 }, + { 0.7988933183, 0.6343785328, 0.8284643303, 0.4277979413, 0.9163443803, 0.5040161837, 0.5319212233 }, + { 0.9417504611, 0.7772356756, 0.9713214732, 0.5706550842, 0.0592015232, 0.6468733266, 0.6747783662 }, + { 0.1050157672, 0.0833581246, 0.4203010650, 0.0196346760, 0.7938954007, 0.5244243470, 0.6951865294 }, + { 0.2478729101, 0.2262152674, 0.5631582079, 0.1624918189, 0.9367525436, 0.6672814899, 0.8380436723 }, + { 0.3907300530, 0.3690724103, 0.7060153507, 0.3053489617, 0.0796096864, 0.8101386327, 0.9809008151 }, + { 0.5335871958, 0.5119295532, 0.8488724936, 0.4482061046, 0.2224668293, 0.9529957756, 0.1237579580 }, + { 0.6764443387, 0.6547866960, 0.9917296365, 0.5910632475, 0.3653239722, 0.0958529184, 0.2666151009 }, + { 0.8193014815, 0.7976438389, 0.1345867793, 0.7339203903, 0.5081811150, 0.2387100613, 0.4094722437 }, + { 0.9621586244, 0.9405009817, 0.2774439222, 0.8767775332, 0.6510382579, 0.3815672041, 0.5523293866 }, + { 0.1254239305, 0.2466234307, 0.5835663712, 0.4686142679, 0.3857321354, 0.2591182245, 0.4298804070 }, + { 0.2682810734, 0.3894805736, 0.7264235140, 0.6114714107, 0.5285892783, 0.4019753674, 0.5727375498 }, + { 0.4111382162, 0.5323377164, 0.8692806569, 0.7543285536, 0.6714464211, 0.5448325103, 0.7155946927 }, + { 0.5539953591, 0.6751948593, 0.0121377997, 0.8971856964, 0.8143035640, 0.6876896531, 0.8584518355 }, + { 0.6968525019, 0.8180520021, 0.1549949426, 0.0400428393, 0.9571607068, 0.8305467960, 0.0013089784 }, + { 0.8397096448, 0.9609091450, 0.2978520854, 0.1828999822, 0.1000178497, 0.9734039388, 0.1441661213 }, + { 0.9825667876, 0.1037662879, 0.4407092283, 0.3257571250, 0.2428749926, 0.1162610817, 0.2870232641 }, + { 0.0058904028, 0.4536205153, 0.5456654965, 0.1654072708, 0.2661986077, 0.4865234724, 0.5552448385 } +}; + + +// Spatial dimension: 16 +// N: 100 +// Base: 17 +// Vectors skipped: 83520 +static const double faure_16_100[100][16] = +{ + { 0.9999880270, 0.8056057758, 0.1198740437, 0.6486751835, 0.0390680188, 0.8792878438, 0.8198536895, 0.5009039643, 0.6317812287, 0.8007207768, 0.6547814322, 0.8998455478, 0.1276086254, 0.0370326026, 0.2198129812, 0.3230085847 }, + { 0.0000007043, 0.0739342061, 0.9946008647, 0.7862221336, 0.0647149678, 0.7918135418, 0.2862640393, 0.2779667248, 0.9710738476, 0.9743784057, 0.2536854063, 0.2482376746, 0.8023258680, 0.1164384864, 0.8034393604, 0.9496301388 }, + { 0.0588242337, 0.1327577355, 0.0534243941, 0.8450456630, 0.1235384972, 0.8506370712, 0.3450875687, 0.3367902542, 0.0298973770, 0.0332019351, 0.3125089358, 0.3070612041, 0.8611493974, 0.1752620158, 0.8622628899, 0.0084536682 }, + { 0.1176477631, 0.1915812649, 0.1122479236, 0.9038691925, 0.1823620266, 0.9094606006, 0.4039110981, 0.3956137836, 0.0887209064, 0.0920254645, 0.3713324652, 0.3658847335, 0.9199729269, 0.2340855452, 0.9210864193, 0.0672771976 }, + { 0.1764712925, 0.2504047943, 0.1710714530, 0.9626927219, 0.2411855560, 0.9682841300, 0.4627346275, 0.4544373131, 0.1475444358, 0.1508489939, 0.4301559946, 0.4247082629, 0.9787964563, 0.2929090746, 0.9799099487, 0.1261007270 }, + { 0.2352948219, 0.3092283237, 0.2298949824, 0.0215162513, 0.3000090854, 0.0271076594, 0.5215581569, 0.5132608425, 0.2063679652, 0.2096725234, 0.4889795240, 0.4835317923, 0.0376199857, 0.3517326041, 0.0387334781, 0.1849242565 }, + { 0.2941183514, 0.3680518531, 0.2887185118, 0.0803397807, 0.3588326148, 0.0859311888, 0.5803816863, 0.5720843719, 0.2651914946, 0.2684960528, 0.5478030534, 0.5423553217, 0.0964435151, 0.4105561335, 0.0975570075, 0.2437477859 }, + { 0.3529418808, 0.4268753825, 0.3475420412, 0.1391633101, 0.4176561442, 0.1447547183, 0.6392052157, 0.6309079013, 0.3240150240, 0.3273195822, 0.6066265828, 0.6011788511, 0.1552670445, 0.4693796629, 0.1563805369, 0.3025713153 }, + { 0.4117654102, 0.4856989119, 0.4063655706, 0.1979868395, 0.4764796737, 0.2035782477, 0.6980287451, 0.6897314307, 0.3828385535, 0.3861431116, 0.6654501122, 0.6600023805, 0.2140905739, 0.5282031923, 0.2152040663, 0.3613948447 }, + { 0.4705889396, 0.5445224413, 0.4651891000, 0.2568103689, 0.5353032031, 0.2624017771, 0.7568522746, 0.7485549601, 0.4416620829, 0.4449666410, 0.7242736416, 0.7188259099, 0.2729141033, 0.5870267217, 0.2740275957, 0.4202183741 }, + { 0.5294124690, 0.6033459708, 0.5240126294, 0.3156338983, 0.5941267325, 0.3212253065, 0.8156758040, 0.8073784895, 0.5004856123, 0.5037901704, 0.7830971711, 0.7776494393, 0.3317376327, 0.6458502511, 0.3328511251, 0.4790419035 }, + { 0.5882359984, 0.6621695002, 0.5828361589, 0.3744574278, 0.6529502619, 0.3800488359, 0.8744993334, 0.8662020189, 0.5593091417, 0.5626136998, 0.8419207005, 0.8364729688, 0.3905611621, 0.7046737805, 0.3916746546, 0.5378654329 }, + { 0.6470595278, 0.7209930296, 0.6416596883, 0.4332809572, 0.7117737913, 0.4388723653, 0.9333228628, 0.9250255483, 0.6181326711, 0.6214372292, 0.9007442299, 0.8952964982, 0.4493846916, 0.7634973099, 0.4504981840, 0.5966889623 }, + { 0.7058830572, 0.7798165590, 0.7004832177, 0.4921044866, 0.7705973207, 0.4976958947, 0.9921463922, 0.9838490778, 0.6769562005, 0.6802607587, 0.9595677593, 0.9541200276, 0.5082082210, 0.8223208394, 0.5093217134, 0.6555124918 }, + { 0.7647065866, 0.8386400884, 0.7593067471, 0.5509280160, 0.8294208501, 0.5565194241, 0.0509699216, 0.0426726072, 0.7357797299, 0.7390842881, 0.0183912887, 0.0129435570, 0.5670317504, 0.8811443688, 0.5681452428, 0.7143360212 }, + { 0.8235301161, 0.8974636178, 0.8181302765, 0.6097515454, 0.8882443795, 0.6153429536, 0.1097934510, 0.1014961366, 0.7946032593, 0.7979078175, 0.0772148181, 0.0717670864, 0.6258552798, 0.9399678982, 0.6269687722, 0.7731595506 }, + { 0.8823536455, 0.9562871472, 0.8769538059, 0.6685750748, 0.9470679090, 0.6741664830, 0.1686169804, 0.1603196660, 0.8534267888, 0.8567313469, 0.1360383475, 0.1305906158, 0.6846788092, 0.9987914276, 0.6857923016, 0.8319830800 }, + { 0.9411771749, 0.0151106766, 0.9357773353, 0.7273986042, 0.0058914384, 0.7329900124, 0.2274405099, 0.2191431954, 0.9122503182, 0.9155548763, 0.1948618769, 0.1894141452, 0.7435023386, 0.0576149570, 0.7446158310, 0.8908066094 }, + { 0.0034609119, 0.1362179431, 0.1157081312, 0.9661529295, 0.3034692930, 0.0893913965, 0.6426654233, 0.6931916383, 0.4451222905, 0.5072503780, 0.8453809081, 0.8987567058, 0.5116684286, 0.8257810470, 0.6304289798, 0.8354432876 }, + { 0.0622844413, 0.1950414725, 0.1745316606, 0.0249764589, 0.3622928224, 0.1482149259, 0.7014889528, 0.7520151677, 0.5039458199, 0.5660739074, 0.9042044375, 0.9575802352, 0.5704919580, 0.8846045764, 0.6892525092, 0.8942668170 }, + { 0.1211079707, 0.2538650019, 0.2333551900, 0.0837999883, 0.4211163519, 0.2070384553, 0.7603124822, 0.8108386971, 0.5627693493, 0.6248974369, 0.9630279669, 0.0164037646, 0.6293154874, 0.9434281058, 0.7480760386, 0.9530903464 }, + { 0.1799315001, 0.3126885313, 0.2921787194, 0.1426235177, 0.4799398813, 0.2658619847, 0.8191360116, 0.8696622265, 0.6215928787, 0.6837209663, 0.0218514963, 0.0752272940, 0.6881390168, 0.0022516352, 0.8068995681, 0.0119138758 }, + { 0.2387550296, 0.3715120607, 0.3510022488, 0.2014470471, 0.5387634107, 0.3246855141, 0.8779595410, 0.9284857560, 0.6804164081, 0.7425444957, 0.0806750257, 0.1340508234, 0.7469625462, 0.0610751646, 0.8657230975, 0.0707374052 }, + { 0.2975785590, 0.4303355901, 0.4098257782, 0.2602705765, 0.5975869401, 0.3835090435, 0.9367830704, 0.9873092854, 0.7392399375, 0.8013680251, 0.1394985551, 0.1928743528, 0.8057860756, 0.1198986940, 0.9245466269, 0.1295609347 }, + { 0.3564020884, 0.4891591195, 0.4686493076, 0.3190941060, 0.6564104695, 0.4423325729, 0.9956065998, 0.0461328148, 0.7980634670, 0.8601915545, 0.1983220845, 0.2516978823, 0.8646096051, 0.1787222234, 0.9833701563, 0.1883844641 }, + { 0.4152256178, 0.5479826490, 0.5274728371, 0.3779176354, 0.7152339989, 0.5011561023, 0.0544301292, 0.1049563442, 0.8568869964, 0.9190150839, 0.2571456140, 0.3105214117, 0.9234331345, 0.2375457528, 0.0421936857, 0.2472079935 }, + { 0.4740491472, 0.6068061784, 0.5862963665, 0.4367411648, 0.7740575283, 0.5599796318, 0.1132536586, 0.1637798736, 0.9157105258, 0.9778386133, 0.3159691434, 0.3693449411, 0.9822566639, 0.2963692823, 0.1010172151, 0.3060315229 }, + { 0.5328726766, 0.6656297078, 0.6451198959, 0.4955646942, 0.8328810577, 0.6188031612, 0.1720771881, 0.2226034030, 0.9745340552, 0.0366621427, 0.3747926728, 0.4281684705, 0.0410801933, 0.3551928117, 0.1598407445, 0.3648550523 }, + { 0.5916962060, 0.7244532372, 0.7039434253, 0.5543882236, 0.8917045872, 0.6776266906, 0.2309007175, 0.2814269324, 0.0333575846, 0.0954856721, 0.4336162022, 0.4869919999, 0.0999037227, 0.4140163411, 0.2186642739, 0.4236785817 }, + { 0.6505197354, 0.7832767666, 0.7627669547, 0.6132117530, 0.9505281166, 0.7364502200, 0.2897242469, 0.3402504618, 0.0921811140, 0.1543092016, 0.4924397316, 0.5458155293, 0.1587272521, 0.4728398705, 0.2774878033, 0.4825021111 }, + { 0.7093432648, 0.8421002960, 0.8215904841, 0.6720352824, 0.0093516460, 0.7952737494, 0.3485477763, 0.3990739913, 0.1510046434, 0.2131327310, 0.5512632610, 0.6046390587, 0.2175507815, 0.5316633999, 0.3363113328, 0.5413256405 }, + { 0.7681667943, 0.9009238254, 0.8804140135, 0.7308588118, 0.0681751754, 0.8540972788, 0.4073713057, 0.4578975207, 0.2098281728, 0.2719562604, 0.6100867904, 0.6634625881, 0.2763743109, 0.5904869293, 0.3951348622, 0.6001491700 }, + { 0.8269903237, 0.9597473548, 0.9392375429, 0.7896823412, 0.1269987048, 0.9129208082, 0.4661948351, 0.5167210501, 0.2686517022, 0.3307797898, 0.6689103198, 0.7222861175, 0.3351978403, 0.6493104587, 0.4539583916, 0.6589726994 }, + { 0.8858138531, 0.0185708843, 0.9980610723, 0.8485058707, 0.1858222342, 0.9717443376, 0.5250183645, 0.5755445795, 0.3274752317, 0.3896033192, 0.7277338493, 0.7811096470, 0.3940213698, 0.7081339881, 0.5127819210, 0.7177962288 }, + { 0.9446373825, 0.0773944137, 0.0568846018, 0.9073294001, 0.2446457636, 0.0305678670, 0.5838418939, 0.6343681089, 0.3862987611, 0.4484268486, 0.7865573787, 0.8399331764, 0.4528448992, 0.7669575176, 0.5716054504, 0.7766197582 }, + { 0.0069211195, 0.1985016801, 0.1779918682, 0.1460837253, 0.5422236183, 0.3869692511, 0.9990668074, 0.1084165518, 0.9191707334, 0.0401223503, 0.4370764098, 0.5492757369, 0.2210109891, 0.5939471369, 0.4574185992, 0.7212564364 }, + { 0.0657446489, 0.2573252095, 0.2368153976, 0.2049072547, 0.6010471477, 0.4457927805, 0.0578903368, 0.1672400812, 0.9779942628, 0.0989458798, 0.4958999392, 0.6080992663, 0.2798345185, 0.6527706663, 0.5162421286, 0.7800799658 }, + { 0.1245681783, 0.3161487389, 0.2956389270, 0.2637307842, 0.6598706771, 0.5046163100, 0.1167138663, 0.2260636106, 0.0368177922, 0.1577694092, 0.5547234686, 0.6669227957, 0.3386580480, 0.7115941958, 0.5750656580, 0.8389034952 }, + { 0.1833917078, 0.3749722683, 0.3544624564, 0.3225543136, 0.7186942065, 0.5634398394, 0.1755373957, 0.2848871400, 0.0956413216, 0.2165929386, 0.6135469980, 0.7257463252, 0.3974815774, 0.7704177252, 0.6338891874, 0.8977270246 }, + { 0.2422152372, 0.4337957977, 0.4132859858, 0.3813778430, 0.7775177359, 0.6222633688, 0.2343609251, 0.3437106695, 0.1544648510, 0.2754164680, 0.6723705275, 0.7845698546, 0.4563051068, 0.8292412546, 0.6927127168, 0.9565505540 }, + { 0.3010387666, 0.4926193272, 0.4721095153, 0.4402013724, 0.8363412654, 0.6810868982, 0.2931844545, 0.4025341989, 0.2132883804, 0.3342399974, 0.7311940569, 0.8433933840, 0.5151286362, 0.8880647840, 0.7515362463, 0.0153740834 }, + { 0.3598622960, 0.5514428566, 0.5309330447, 0.4990249018, 0.8951647948, 0.7399104276, 0.3520079839, 0.4613577283, 0.2721119099, 0.3930635268, 0.7900175863, 0.9022169134, 0.5739521656, 0.9468883134, 0.8103597757, 0.0741976129 }, + { 0.4186858254, 0.6102663860, 0.5897565741, 0.5578484312, 0.9539883242, 0.7987339570, 0.4108315133, 0.5201812577, 0.3309354393, 0.4518870562, 0.8488411157, 0.9610404428, 0.6327756950, 0.0057118428, 0.8691833051, 0.1330211423 }, + { 0.4775093548, 0.6690899154, 0.6485801035, 0.6166719606, 0.0128118536, 0.8575574864, 0.4696550427, 0.5790047871, 0.3897589687, 0.5107105856, 0.9076646451, 0.0198639722, 0.6915992244, 0.0645353722, 0.9280068345, 0.1918446717 }, + { 0.5363328842, 0.7279134448, 0.7074036329, 0.6754954900, 0.0716353830, 0.9163810158, 0.5284785721, 0.6378283165, 0.4485824981, 0.5695341151, 0.9664881745, 0.0786875016, 0.7504227538, 0.1233589016, 0.9868303639, 0.2506682011 }, + { 0.5951564136, 0.7867369742, 0.7662271623, 0.7343190195, 0.1304589124, 0.9752045452, 0.5873021015, 0.6966518459, 0.5074060275, 0.6283576445, 0.0253117039, 0.1375110310, 0.8092462833, 0.1821824310, 0.0456538933, 0.3094917305 }, + { 0.6539799431, 0.8455605036, 0.8250506917, 0.7931425489, 0.1892824418, 0.0340280747, 0.6461256310, 0.7554753753, 0.5662295569, 0.6871811739, 0.0841352333, 0.1963345605, 0.8680698127, 0.2410059605, 0.1044774227, 0.3683152599 }, + { 0.7128034725, 0.9043840330, 0.8838742211, 0.8519660783, 0.2481059712, 0.0928516041, 0.7049491604, 0.8142989047, 0.6250530863, 0.7460047033, 0.1429587627, 0.2551580899, 0.9268933421, 0.2998294899, 0.1633009521, 0.4271387893 }, + { 0.7716270019, 0.9632075625, 0.9426977505, 0.9107896077, 0.3069295006, 0.1516751335, 0.7637726898, 0.8731224342, 0.6838766157, 0.8048282327, 0.2017822922, 0.3139816193, 0.9857168715, 0.3586530193, 0.2221244815, 0.4859623187 }, + { 0.8304505313, 0.0220310919, 0.0015212800, 0.9696131371, 0.3657530301, 0.2104986629, 0.8225962192, 0.9319459636, 0.7427001452, 0.8636517621, 0.2606058216, 0.3728051487, 0.0445404009, 0.4174765487, 0.2809480110, 0.5447858482 }, + { 0.8892740607, 0.0808546213, 0.0603448094, 0.0284366665, 0.4245765595, 0.2693221923, 0.8814197486, 0.9907694930, 0.8015236746, 0.9224752915, 0.3194293510, 0.4316286781, 0.1033639303, 0.4763000781, 0.3397715404, 0.6036093776 }, + { 0.9480975901, 0.1396781507, 0.1191683388, 0.0872601959, 0.4834000889, 0.3281457217, 0.9402432780, 0.0495930224, 0.8603472040, 0.9812988209, 0.3782528804, 0.4904522075, 0.1621874597, 0.5351236075, 0.3985950698, 0.6624329070 }, + { 0.0103813271, 0.2607854171, 0.2990991346, 0.3260145212, 0.7809779436, 0.6845471058, 0.2966446621, 0.5236414653, 0.3932191763, 0.5729943227, 0.0287719115, 0.1997947681, 0.9303535497, 0.3621132269, 0.2844082186, 0.6070695852 }, + { 0.0692048565, 0.3196089465, 0.3579226640, 0.3848380506, 0.8398014730, 0.7433706352, 0.3554681915, 0.5824649947, 0.4520427057, 0.6318178521, 0.0875954409, 0.2586182975, 0.9891770791, 0.4209367563, 0.3432317480, 0.6658931146 }, + { 0.1280283860, 0.3784324759, 0.4167461935, 0.4436615800, 0.8986250024, 0.8021941646, 0.4142917209, 0.6412885241, 0.5108662351, 0.6906413815, 0.1464189704, 0.3174418269, 0.0480006085, 0.4797602857, 0.4020552774, 0.7247166440 }, + { 0.1868519154, 0.4372560054, 0.4755697229, 0.5024851094, 0.9574485318, 0.8610176940, 0.4731152503, 0.7001120535, 0.5696897645, 0.7494649109, 0.2052424998, 0.3762653563, 0.1068241379, 0.5385838151, 0.4608788068, 0.7835401734 }, + { 0.2456754448, 0.4960795348, 0.5343932523, 0.5613086388, 0.0162720612, 0.9198412234, 0.5319387798, 0.7589355829, 0.6285132939, 0.8082884403, 0.2640660292, 0.4350888857, 0.1656476673, 0.5974073445, 0.5197023362, 0.8423637028 }, + { 0.3044989742, 0.5549030642, 0.5932167817, 0.6201321682, 0.0750955906, 0.9786647529, 0.5907623092, 0.8177591124, 0.6873368234, 0.8671119697, 0.3228895586, 0.4939124151, 0.2244711967, 0.6562308740, 0.5785258656, 0.9011872322 }, + { 0.3633225036, 0.6137265936, 0.6520403111, 0.6789556977, 0.1339191200, 0.0374882823, 0.6495858386, 0.8765826418, 0.7461603528, 0.9259354991, 0.3817130880, 0.5527359445, 0.2832947262, 0.7150544034, 0.6373493950, 0.9600107616 }, + { 0.4221460330, 0.6725501230, 0.7108638405, 0.7377792271, 0.1927426494, 0.0963118117, 0.7084093680, 0.9354061712, 0.8049838822, 0.9847590286, 0.4405366174, 0.6115594739, 0.3421182556, 0.7738779328, 0.6961729245, 0.0188342911 }, + { 0.4809695624, 0.7313736524, 0.7696873699, 0.7966027565, 0.2515661788, 0.1551353411, 0.7672328974, 0.9942297006, 0.8638074116, 0.0435825580, 0.4993601468, 0.6703830034, 0.4009417850, 0.8327014622, 0.7549964539, 0.0776578205 }, + { 0.5397930918, 0.7901971818, 0.8285108993, 0.8554262859, 0.3103897083, 0.2139588705, 0.8260564268, 0.0530532300, 0.9226309410, 0.1024060874, 0.5581836762, 0.7292065328, 0.4597653144, 0.8915249916, 0.8138199833, 0.1364813499 }, + { 0.5986166213, 0.8490207112, 0.8873344287, 0.9142498153, 0.3692132377, 0.2727823999, 0.8848799562, 0.1118767594, 0.9814544704, 0.1612296168, 0.6170072057, 0.7880300622, 0.5185888438, 0.9503485210, 0.8726435127, 0.1953048793 }, + { 0.6574401507, 0.9078442407, 0.9461579582, 0.9730733447, 0.4280367671, 0.3316059293, 0.9437034856, 0.1707002888, 0.0402779998, 0.2200531462, 0.6758307351, 0.8468535916, 0.5774123732, 0.0091720504, 0.9314670421, 0.2541284087 }, + { 0.7162636801, 0.9666677701, 0.0049814876, 0.0318968741, 0.4868602965, 0.3904294587, 0.0025270150, 0.2295238182, 0.0991015292, 0.2788766756, 0.7346542645, 0.9056771210, 0.6362359026, 0.0679955798, 0.9902905715, 0.3129519381 }, + { 0.7750872095, 0.0254912995, 0.0638050170, 0.0907204035, 0.5456838259, 0.4492529882, 0.0613505445, 0.2883473477, 0.1579250587, 0.3377002050, 0.7934777939, 0.9645006504, 0.6950594320, 0.1268191092, 0.0491141009, 0.3717754675 }, + { 0.8339107389, 0.0843148289, 0.1226285464, 0.1495439329, 0.6045073553, 0.5080765176, 0.1201740739, 0.3471708771, 0.2167485881, 0.3965237344, 0.8523013233, 0.0233241798, 0.7538829615, 0.1856426387, 0.1079376303, 0.4305989969 }, + { 0.8927342683, 0.1431383583, 0.1814520758, 0.2083674624, 0.6633308847, 0.5669000470, 0.1789976033, 0.4059944065, 0.2755721175, 0.4553472638, 0.9111248527, 0.0821477092, 0.8127064909, 0.2444661681, 0.1667611598, 0.4894225264 }, + { 0.9515577977, 0.2019618877, 0.2402756052, 0.2671909918, 0.7221544141, 0.6257235764, 0.2378211327, 0.4648179359, 0.3343956469, 0.5141707933, 0.9699483821, 0.1409712387, 0.8715300203, 0.3032896975, 0.2255846892, 0.5482460558 }, + { 0.0138415347, 0.3230691541, 0.4202064011, 0.5059453170, 0.0197322688, 0.9821249605, 0.6530460462, 0.9388663788, 0.8672676192, 0.1058662950, 0.6204674133, 0.8503137992, 0.6396961102, 0.1302793169, 0.1113978380, 0.4928827340 }, + { 0.0726650642, 0.3818926836, 0.4790299305, 0.5647688464, 0.0785557982, 0.0409484899, 0.7118695756, 0.9976899082, 0.9260911486, 0.1646898244, 0.6792909427, 0.9091373286, 0.6985196397, 0.1891028463, 0.1702213674, 0.5517062634 }, + { 0.1314885936, 0.4407162130, 0.5378534599, 0.6235923759, 0.1373793276, 0.0997720193, 0.7706931050, 0.0565134376, 0.9849146780, 0.2235133538, 0.7381144721, 0.9679608580, 0.7573431691, 0.2479263757, 0.2290448968, 0.6105297928 }, + { 0.1903121230, 0.4995397424, 0.5966769893, 0.6824159053, 0.1962028570, 0.1585955487, 0.8295166344, 0.1153369670, 0.0437382074, 0.2823368832, 0.7969380015, 0.0267843874, 0.8161666985, 0.3067499051, 0.2878684262, 0.6693533222 }, + { 0.2491356524, 0.5583632718, 0.6555005187, 0.7412394347, 0.2550263865, 0.2174190781, 0.8883401638, 0.1741604964, 0.1025617369, 0.3411604126, 0.8557615309, 0.0856079169, 0.8749902279, 0.3655734345, 0.3466919556, 0.7281768516 }, + { 0.3079591818, 0.6171868012, 0.7143240481, 0.8000629641, 0.3138499159, 0.2762426075, 0.9471636932, 0.2329840259, 0.1613852663, 0.3999839420, 0.9145850603, 0.1444314463, 0.9338137573, 0.4243969639, 0.4055154850, 0.7870003810 }, + { 0.3667827112, 0.6760103306, 0.7731475775, 0.8588864935, 0.3726734453, 0.3350661369, 0.0059872227, 0.2918075553, 0.2202087957, 0.4588074715, 0.9734085897, 0.2032549757, 0.9926372867, 0.4832204933, 0.4643390144, 0.8458239104 }, + { 0.4256062406, 0.7348338600, 0.8319711069, 0.9177100229, 0.4314969747, 0.3938896664, 0.0648107521, 0.3506310847, 0.2790323251, 0.5176310009, 0.0322321192, 0.2620785051, 0.0514608161, 0.5420440227, 0.5231625438, 0.9046474398 }, + { 0.4844297700, 0.7936573894, 0.8907946364, 0.9765335523, 0.4903205041, 0.4527131958, 0.1236342815, 0.4094546141, 0.3378558545, 0.5764545303, 0.0910556486, 0.3209020345, 0.1102843455, 0.6008675522, 0.5819860732, 0.9634709693 }, + { 0.5432532995, 0.8524809189, 0.9496181658, 0.0353570817, 0.5491440335, 0.5115367252, 0.1824578109, 0.4682781435, 0.3966793839, 0.6352780597, 0.1498791780, 0.3797255639, 0.1691078749, 0.6596910816, 0.6408096027, 0.0222944987 }, + { 0.6020768289, 0.9113044483, 0.0084416952, 0.0941806111, 0.6079675629, 0.5703602546, 0.2412813403, 0.5271016729, 0.4555029133, 0.6941015891, 0.2087027074, 0.4385490933, 0.2279314044, 0.7185146110, 0.6996331321, 0.0811180281 }, + { 0.6609003583, 0.9701279777, 0.0672652246, 0.1530041406, 0.6667910923, 0.6291837840, 0.3001048697, 0.5859252023, 0.5143264427, 0.7529251185, 0.2675262368, 0.4973726227, 0.2867549338, 0.7773381404, 0.7584566615, 0.1399415575 }, + { 0.7197238877, 0.0289515071, 0.1260887540, 0.2118276700, 0.7256146218, 0.6880073134, 0.3589283991, 0.6447487317, 0.5731499721, 0.8117486479, 0.3263497662, 0.5561961521, 0.3455784632, 0.8361616698, 0.8172801909, 0.1987650869 }, + { 0.7785474171, 0.0877750365, 0.1849122834, 0.2706511994, 0.7844381512, 0.7468308428, 0.4177519285, 0.7035722612, 0.6319735016, 0.8705721773, 0.3851732956, 0.6150196816, 0.4044019926, 0.8949851992, 0.8761037203, 0.2575886163 }, + { 0.8373709465, 0.1465985659, 0.2437358128, 0.3294747288, 0.8432616806, 0.8056543722, 0.4765754580, 0.7623957906, 0.6907970310, 0.9293957068, 0.4439968250, 0.6738432110, 0.4632255220, 0.9538087286, 0.9349272497, 0.3164121457 }, + { 0.8961944759, 0.2054220953, 0.3025593422, 0.3882982582, 0.9020852100, 0.8644779016, 0.5353989874, 0.8212193200, 0.7496205604, 0.9882192362, 0.5028203544, 0.7326667404, 0.5220490514, 0.0126322580, 0.9937507791, 0.3752356751 }, + { 0.9550180053, 0.2642456247, 0.3613828717, 0.4471217876, 0.9609087394, 0.9233014311, 0.5942225168, 0.8800428494, 0.8084440898, 0.0470427656, 0.5616438839, 0.7914902698, 0.5808725808, 0.0714557874, 0.0525743085, 0.4340592046 }, + { 0.0173017424, 0.3853528912, 0.5413136675, 0.6858761129, 0.2584865941, 0.2797028151, 0.0094474303, 0.2952677629, 0.3413160621, 0.6387382673, 0.2121629150, 0.5008328303, 0.3490386708, 0.8984454068, 0.9383874573, 0.3786958828 }, + { 0.0761252718, 0.4441764206, 0.6001371969, 0.7446996423, 0.3173101235, 0.3385263446, 0.0682709597, 0.3540912923, 0.4001395915, 0.6975617967, 0.2709864444, 0.5596563598, 0.4078622002, 0.9572689362, 0.9972109867, 0.4375194122 }, + { 0.1349488012, 0.5029999500, 0.6589607263, 0.8035231717, 0.3761336529, 0.3973498740, 0.1270944891, 0.4129148217, 0.4589631209, 0.7563853261, 0.3298099738, 0.6184798892, 0.4666857296, 0.0160924656, 0.0560345162, 0.4963429416 }, + { 0.1937723306, 0.5618234794, 0.7177842557, 0.8623467011, 0.4349571823, 0.4561734034, 0.1859180185, 0.4717383511, 0.5177866503, 0.8152088555, 0.3886335032, 0.6773034186, 0.5255092590, 0.0749159951, 0.1148580456, 0.5551664710 }, + { 0.2525958600, 0.6206470088, 0.7766077852, 0.9211702305, 0.4937807117, 0.5149969328, 0.2447415479, 0.5305618805, 0.5766101798, 0.8740323850, 0.4474570326, 0.7361269480, 0.5843327884, 0.1337395245, 0.1736815750, 0.6139900004 }, + { 0.3114193894, 0.6794705382, 0.8354313146, 0.9799937599, 0.5526042411, 0.5738204622, 0.3035650773, 0.5893854099, 0.6354337092, 0.9328559144, 0.5062805621, 0.7949504774, 0.6431563179, 0.1925630539, 0.2325051044, 0.6728135298 }, + { 0.3702429188, 0.7382940676, 0.8942548440, 0.0388172893, 0.6114277705, 0.6326439916, 0.3623886067, 0.6482089394, 0.6942572386, 0.9916794438, 0.5651040915, 0.8537740068, 0.7019798473, 0.2513865833, 0.2913286338, 0.7316370592 }, + { 0.4290664482, 0.7971175971, 0.9530783734, 0.0976408188, 0.6702513000, 0.6914675210, 0.4212121362, 0.7070324688, 0.7530807680, 0.0505029732, 0.6239276209, 0.9125975362, 0.7608033767, 0.3102101127, 0.3501521632, 0.7904605886 }, + { 0.4878899777, 0.8559411265, 0.0119019028, 0.1564643482, 0.7290748294, 0.7502910504, 0.4800356656, 0.7658559982, 0.8119042974, 0.1093265026, 0.6827511503, 0.9714210656, 0.8196269061, 0.3690336421, 0.4089756926, 0.8492841180 }, + { 0.5467135071, 0.9147646559, 0.0707254322, 0.2152878776, 0.7878983588, 0.8091145798, 0.5388591950, 0.8246795276, 0.8707278268, 0.1681500320, 0.7415746797, 0.0302445951, 0.8784504355, 0.4278571715, 0.4677992220, 0.9081076475 }, + { 0.6055370365, 0.9735881853, 0.1295489616, 0.2741114070, 0.8467218882, 0.8679381093, 0.5976827244, 0.8835030570, 0.9295513562, 0.2269735614, 0.8003982091, 0.0890681245, 0.9372739649, 0.4866807009, 0.5266227514, 0.9669311769 }, + { 0.6643605659, 0.0324117147, 0.1883724910, 0.3329349364, 0.9055454176, 0.9267616387, 0.6565062538, 0.9423265864, 0.9883748856, 0.2857970908, 0.8592217385, 0.1478916539, 0.9960974943, 0.5455042304, 0.5854462809, 0.0257547063 }, + { 0.7231840953, 0.0912352441, 0.2471960204, 0.3917584658, 0.9643689470, 0.9855851681, 0.7153297832, 0.0011501158, 0.0471984151, 0.3446206202, 0.9180452679, 0.2067151833, 0.0549210237, 0.6043277598, 0.6442698103, 0.0845782357 }, + { 0.7820076247, 0.1500587735, 0.3060195499, 0.4505819952, 0.0231924764, 0.0444086975, 0.7741533126, 0.0599736452, 0.1060219445, 0.4034441497, 0.9768687974, 0.2655387127, 0.1137445531, 0.6631512892, 0.7030933397, 0.1434017651 } +}; + + +QRNG_VALIDATION_TEST_FUNCTIONS(faure) + + +BOOST_AUTO_TEST_CASE( validate_faure ) +{ + test_faure_values(faure_02_100, 15); + test_faure_values(faure_07_100, 2400); + test_faure_values(faure_16_100, 83520); +} + +BOOST_AUTO_TEST_CASE( validate_faure_seed ) +{ + test_faure_seed(faure_02_100, 15); + test_faure_seed(faure_07_100, 2400); + test_faure_seed(faure_16_100, 83520); +} + +BOOST_AUTO_TEST_CASE( validate_faure_discard ) +{ + test_faure_discard(faure_02_100, 15); + test_faure_discard(faure_07_100, 2400); + test_faure_discard(faure_16_100, 83520); +} diff --git a/test/niederreiter_base2_validade.cpp b/test/niederreiter_base2_validade.cpp new file mode 100644 index 0000000..7eca8af --- /dev/null +++ b/test/niederreiter_base2_validade.cpp @@ -0,0 +1,372 @@ +// Copyright Justinas Vygintas Daugmaudis, 2010. +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) + +#include + +#include + +#define BOOST_TEST_MAIN +#include + +#include "test_qrng_functions.hpp" + +// +// DESCRIPTION: +// ~~~~~~~~~~~~ +// +// This file tests the faure quasi-random number generator. +// These tests compare our results with values produced by the original +// version of ACM TOMS Algorithm 738, which is available in the +// TOMS subdirectory in http://www.netlib.org +// +// For independently generated datasets look at http://people.sc.fsu.edu/~jburkardt/datasets/niederreiter2/ + + +// Spatial dimension: 2 +// N: 100 +// Vectors skipped: 4096 +static const double niederreiter_base2_02_100[100][2] = +{ + { 0.0003662109, 0.4705810548 }, + { 0.5003662111, 0.9705810549 }, + { 0.7503662111, 0.2205810547 }, + { 0.2503662110, 0.7205810549 }, + { 0.3753662110, 0.0955810547 }, + { 0.8753662111, 0.5955810548 }, + { 0.6253662111, 0.3455810548 }, + { 0.1253662110, 0.8455810549 }, + { 0.1878662110, 0.1580810547 }, + { 0.6878662111, 0.6580810548 }, + { 0.9378662112, 0.4080810548 }, + { 0.4378662110, 0.9080810549 }, + { 0.3128662110, 0.2830810548 }, + { 0.8128662111, 0.7830810549 }, + { 0.5628662111, 0.0330810547 }, + { 0.0628662110, 0.5330810548 }, + { 0.0941162110, 0.0018310547 }, + { 0.5941162111, 0.5018310548 }, + { 0.8441162111, 0.2518310547 }, + { 0.3441162110, 0.7518310549 }, + { 0.4691162110, 0.3768310548 }, + { 0.9691162112, 0.8768310549 }, + { 0.7191162111, 0.1268310547 }, + { 0.2191162110, 0.6268310548 }, + { 0.1566162110, 0.3143310548 }, + { 0.6566162111, 0.8143310549 }, + { 0.9066162111, 0.0643310547 }, + { 0.4066162110, 0.5643310548 }, + { 0.2816162110, 0.1893310547 }, + { 0.7816162111, 0.6893310548 }, + { 0.5316162111, 0.4393310548 }, + { 0.0316162109, 0.9393310549 }, + { 0.0472412109, 0.2362060547 }, + { 0.5472412111, 0.7362060549 }, + { 0.7972412111, 0.4862060548 }, + { 0.2972412110, 0.9862060549 }, + { 0.4222412110, 0.3612060548 }, + { 0.9222412112, 0.8612060549 }, + { 0.6722412111, 0.1112060547 }, + { 0.1722412110, 0.6112060548 }, + { 0.2347412110, 0.4237060548 }, + { 0.7347412111, 0.9237060549 }, + { 0.9847412112, 0.1737060547 }, + { 0.4847412111, 0.6737060548 }, + { 0.3597412110, 0.0487060547 }, + { 0.8597412111, 0.5487060548 }, + { 0.6097412111, 0.2987060548 }, + { 0.1097412110, 0.7987060549 }, + { 0.0784912110, 0.2674560547 }, + { 0.5784912111, 0.7674560549 }, + { 0.8284912111, 0.0174560547 }, + { 0.3284912110, 0.5174560548 }, + { 0.4534912110, 0.1424560547 }, + { 0.9534912112, 0.6424560548 }, + { 0.7034912111, 0.3924560548 }, + { 0.2034912110, 0.8924560549 }, + { 0.1409912110, 0.0799560547 }, + { 0.6409912111, 0.5799560548 }, + { 0.8909912111, 0.3299560548 }, + { 0.3909912110, 0.8299560549 }, + { 0.2659912110, 0.4549560548 }, + { 0.7659912111, 0.9549560549 }, + { 0.5159912111, 0.2049560547 }, + { 0.0159912109, 0.7049560549 }, + { 0.0238037109, 0.1190185547 }, + { 0.5238037111, 0.6190185548 }, + { 0.7738037111, 0.3690185548 }, + { 0.2738037110, 0.8690185549 }, + { 0.3988037110, 0.4940185548 }, + { 0.8988037111, 0.9940185549 }, + { 0.6488037111, 0.2440185547 }, + { 0.1488037110, 0.7440185549 }, + { 0.2113037110, 0.3065185548 }, + { 0.7113037111, 0.8065185549 }, + { 0.9613037112, 0.0565185547 }, + { 0.4613037110, 0.5565185548 }, + { 0.3363037110, 0.1815185547 }, + { 0.8363037111, 0.6815185548 }, + { 0.5863037111, 0.4315185548 }, + { 0.0863037110, 0.9315185549 }, + { 0.1175537110, 0.4002685548 }, + { 0.6175537111, 0.9002685549 }, + { 0.8675537111, 0.1502685547 }, + { 0.3675537110, 0.6502685548 }, + { 0.4925537111, 0.0252685547 }, + { 0.9925537112, 0.5252685548 }, + { 0.7425537111, 0.2752685548 }, + { 0.2425537110, 0.7752685549 }, + { 0.1800537110, 0.2127685547 }, + { 0.6800537111, 0.7127685549 }, + { 0.9300537112, 0.4627685548 }, + { 0.4300537110, 0.9627685549 }, + { 0.3050537110, 0.3377685548 }, + { 0.8050537111, 0.8377685549 }, + { 0.5550537111, 0.0877685547 }, + { 0.0550537110, 0.5877685548 }, + { 0.0394287109, 0.3533935548 }, + { 0.5394287111, 0.8533935549 }, + { 0.7894287111, 0.1033935547 }, + { 0.2894287110, 0.6033935548 } +}; + +// Spatial dimension: 7 +// N: 100 +// Vectors skipped: 4096 +static const double niederreiter_base2_07_100[100][7] = +{ + { 0.0003662109, 0.4705810548, 0.6358642580, 0.9561767580, 0.6715087892, 0.9793701174, 0.6053466798 }, + { 0.5003662111, 0.9705810549, 0.3858642579, 0.0811767578, 0.2965087891, 0.0418701172, 0.4178466798 }, + { 0.7503662111, 0.2205810547, 0.9483642580, 0.8155517580, 0.5621337892, 0.9207763674, 0.5467529298 }, + { 0.2503662110, 0.7205810549, 0.1983642579, 0.1905517579, 0.4371337892, 0.1082763672, 0.4842529298 }, + { 0.3753662110, 0.0955810547, 0.2608642579, 0.7374267580, 0.7652587892, 0.8465576174, 0.6600341798 }, + { 0.8753662111, 0.5955810548, 0.5108642579, 0.3624267579, 0.1402587891, 0.1590576172, 0.3475341798 }, + { 0.6253662111, 0.3455810548, 0.0733642578, 0.5968017580, 0.9058837893, 0.7879638674, 0.7264404299 }, + { 0.1253662110, 0.8455810549, 0.8233642580, 0.4718017579, 0.0308837891, 0.2254638672, 0.2889404298 }, + { 0.1878662110, 0.1580810547, 0.1514892578, 0.2686767579, 0.3590087891, 0.7449951174, 0.9334716799 }, + { 0.6878662111, 0.6580810548, 0.9014892580, 0.6436767580, 0.7340087892, 0.3074951173, 0.1209716797 }, + { 0.9378662112, 0.4080810548, 0.4639892579, 0.3780517579, 0.4996337892, 0.6864013673, 0.9998779299 }, + { 0.4378662110, 0.9080810549, 0.7139892580, 0.5030517579, 0.6246337892, 0.3739013673, 0.0623779297 }, + { 0.3128662110, 0.2830810548, 0.7764892580, 0.0499267578, 0.2027587891, 0.6121826173, 0.8631591799 }, + { 0.8128662111, 0.7830810549, 0.0264892578, 0.9249267580, 0.8277587893, 0.4246826173, 0.1756591797 }, + { 0.5628662111, 0.0330810547, 0.5889892579, 0.1593017578, 0.0933837891, 0.5535888673, 0.8045654299 }, + { 0.0628662110, 0.5330810548, 0.3389892579, 0.7843017580, 0.9683837893, 0.4910888673, 0.2420654297 }, + { 0.0941162110, 0.0018310547, 0.9171142580, 0.5635986329, 0.4195556642, 0.3856201173, 0.3865966798 }, + { 0.5941162111, 0.5018310548, 0.1671142579, 0.4385986329, 0.5445556642, 0.5731201173, 0.5740966798 }, + { 0.8441162111, 0.2518310547, 0.7296142580, 0.7042236330, 0.3101806641, 0.4520263673, 0.4530029298 }, + { 0.3441162110, 0.7518310549, 0.4796142579, 0.3292236329, 0.6851806642, 0.5145263673, 0.5155029298 }, + { 0.4691162110, 0.3768310548, 0.0421142578, 0.8448486330, 0.0133056641, 0.2528076172, 0.3162841798 }, + { 0.9691162112, 0.8768310549, 0.7921142580, 0.2198486329, 0.8883056643, 0.6903076173, 0.6287841798 }, + { 0.7191162111, 0.1268310547, 0.3546142579, 0.9854736330, 0.1539306641, 0.3192138673, 0.2576904297 }, + { 0.2191162110, 0.6268310548, 0.6046142580, 0.1104736328, 0.7789306642, 0.6317138673, 0.6951904298 }, + { 0.1566162110, 0.3143310548, 0.4327392579, 0.1260986328, 0.6070556642, 0.1512451172, 0.0897216797 }, + { 0.6566162111, 0.8143310549, 0.6827392580, 0.7510986330, 0.4820556642, 0.8387451174, 0.9022216799 }, + { 0.9066162111, 0.0643310547, 0.2452392579, 0.0167236328, 0.7476806642, 0.2176513672, 0.0311279297 }, + { 0.4066162110, 0.5643310548, 0.9952392580, 0.8917236330, 0.3726806641, 0.7801513674, 0.9686279299 }, + { 0.2816162110, 0.1893310547, 0.5577392579, 0.4073486329, 0.9508056643, 0.0184326172, 0.1444091797 }, + { 0.7816162111, 0.6893310548, 0.3077392579, 0.5323486329, 0.0758056641, 0.9559326174, 0.8319091799 }, + { 0.5316162111, 0.4393310548, 0.8702392580, 0.2979736329, 0.8414306643, 0.0848388672, 0.2108154297 }, + { 0.0316162109, 0.9393310549, 0.1202392578, 0.6729736330, 0.2164306641, 0.8973388674, 0.7733154299 }, + { 0.0472412109, 0.2362060547, 0.4522705079, 0.1007080078, 0.0426025391, 0.7955322267, 0.4801025392 }, + { 0.5472412111, 0.7362060549, 0.7022705080, 0.9757080080, 0.9176025393, 0.2330322266, 0.5426025392 }, + { 0.7972412111, 0.4862060548, 0.1397705078, 0.2413330079, 0.1832275391, 0.8541259768, 0.4215087892 }, + { 0.2972412110, 0.9862060549, 0.8897705080, 0.8663330080, 0.8082275393, 0.1666259766, 0.6090087892 }, + { 0.4222412110, 0.3612060548, 0.5772705079, 0.3194580079, 0.3863525392, 0.9127197268, 0.2847900391 }, + { 0.9222412112, 0.8612060549, 0.3272705079, 0.6944580080, 0.5113525392, 0.1002197266, 0.7222900392 }, + { 0.6722412111, 0.1112060547, 0.7647705080, 0.4600830079, 0.2769775391, 0.9713134768, 0.3511962891 }, + { 0.1722412110, 0.6112060548, 0.0147705078, 0.5850830079, 0.6519775392, 0.0338134766, 0.6636962892 }, + { 0.2347412110, 0.4237060548, 0.9678955080, 0.6632080080, 0.9801025393, 0.5611572267, 0.0582275391 }, + { 0.7347412111, 0.9237060549, 0.2178955079, 0.2882080079, 0.1051025391, 0.4986572267, 0.9957275393 }, + { 0.9847412112, 0.1737060547, 0.6553955080, 0.5538330079, 0.8707275393, 0.6197509767, 0.1246337891 }, + { 0.4847412111, 0.6737060548, 0.4053955079, 0.4288330079, 0.2457275391, 0.4322509767, 0.9371337893 }, + { 0.3597412110, 0.0487060547, 0.0928955078, 0.8819580080, 0.5738525392, 0.6783447267, 0.2379150391 }, + { 0.8597412111, 0.5487060548, 0.8428955080, 0.0069580078, 0.4488525392, 0.3658447266, 0.8004150392 }, + { 0.6097412111, 0.2987060548, 0.2803955079, 0.7725830080, 0.7144775392, 0.7369384767, 0.1793212891 }, + { 0.1097412110, 0.7987060549, 0.5303955079, 0.1475830078, 0.3394775391, 0.2994384766, 0.8668212893 }, + { 0.0784912110, 0.2674560547, 0.2335205079, 0.4893798829, 0.7906494142, 0.3267822266, 0.5113525392 }, + { 0.5784912111, 0.7674560549, 0.9835205080, 0.6143798830, 0.1656494141, 0.6392822267, 0.4488525392 }, + { 0.8284912111, 0.0174560547, 0.4210205079, 0.3487548829, 0.9312744143, 0.2603759766, 0.5777587892 }, + { 0.3284912110, 0.5174560548, 0.6710205080, 0.7237548830, 0.0562744141, 0.6978759767, 0.3902587892 }, + { 0.4534912110, 0.1424560547, 0.8585205080, 0.2081298829, 0.6343994142, 0.4439697267, 0.6910400392 }, + { 0.9534912112, 0.6424560548, 0.1085205078, 0.8331298830, 0.2593994141, 0.5064697267, 0.2535400391 }, + { 0.7034912111, 0.3924560548, 0.5460205079, 0.0675048828, 0.5250244142, 0.3775634767, 0.6324462892 }, + { 0.2034912110, 0.8924560549, 0.2960205079, 0.9425048830, 0.4000244142, 0.5650634767, 0.3199462891 }, + { 0.1409912110, 0.0799560547, 0.7491455080, 0.8018798830, 0.2281494141, 0.0924072266, 0.9644775393 }, + { 0.6409912111, 0.5799560548, 0.4991455079, 0.1768798829, 0.8531494143, 0.9049072268, 0.0269775391 }, + { 0.8909912111, 0.3299560548, 0.9366455080, 0.9112548830, 0.1187744141, 0.0260009766, 0.9058837893 }, + { 0.3909912110, 0.8299560549, 0.1866455079, 0.0362548828, 0.9937744143, 0.9635009768, 0.0933837891 }, + { 0.2659912110, 0.4549560548, 0.3741455079, 0.5206298829, 0.3218994141, 0.2095947266, 0.7691650392 }, + { 0.7659912111, 0.9549560549, 0.6241455080, 0.3956298829, 0.6968994142, 0.7720947267, 0.2066650391 }, + { 0.5159912111, 0.2049560547, 0.0616455078, 0.6300048830, 0.4625244142, 0.1431884766, 0.8355712893 }, + { 0.0159912109, 0.7049560549, 0.8116455080, 0.2550048829, 0.5875244142, 0.8306884768, 0.1480712891 }, + { 0.0238037109, 0.1190185547, 0.0186767578, 0.1827392579, 0.9136962893, 0.5960693361, 0.2923583985 }, + { 0.5238037111, 0.6190185548, 0.7686767580, 0.8077392580, 0.0386962891, 0.4085693360, 0.7298583986 }, + { 0.7738037111, 0.3690185548, 0.3311767579, 0.0421142578, 0.8043212892, 0.5374755861, 0.3587646485 }, + { 0.2738037110, 0.8690185549, 0.5811767579, 0.9171142580, 0.1793212891, 0.4749755860, 0.6712646486 }, + { 0.3988037110, 0.4940185548, 0.8936767580, 0.4014892579, 0.5074462892, 0.7288818361, 0.4720458985 }, + { 0.8988037111, 0.9940185549, 0.1436767578, 0.5264892579, 0.3824462892, 0.2913818360, 0.5345458986 }, + { 0.6488037111, 0.2440185547, 0.7061767580, 0.2608642579, 0.6480712892, 0.6702880861, 0.4134521485 }, + { 0.1488037110, 0.7440185549, 0.4561767579, 0.6358642580, 0.2730712891, 0.3577880860, 0.6009521486 }, + { 0.2113037110, 0.3065185548, 0.5030517579, 0.6202392580, 0.1011962891, 0.8616943361, 0.2454833985 }, + { 0.7113037111, 0.8065185549, 0.2530517579, 0.4952392579, 0.9761962893, 0.1741943360, 0.8079833986 }, + { 0.9613037112, 0.0565185547, 0.8155517580, 0.7296142580, 0.2418212891, 0.8031005861, 0.1868896485 }, + { 0.4613037110, 0.5565185548, 0.0655517578, 0.3546142579, 0.8668212893, 0.2406005860, 0.8743896486 }, + { 0.3363037110, 0.1815185547, 0.3780517579, 0.8389892580, 0.4449462892, 0.9945068362, 0.0501708984 }, + { 0.8363037111, 0.6815185548, 0.6280517580, 0.2139892579, 0.5699462892, 0.0570068360, 0.9876708987 }, + { 0.5863037111, 0.4315185548, 0.1905517579, 0.9483642580, 0.3355712891, 0.9359130862, 0.1165771485 }, + { 0.0863037110, 0.9315185549, 0.9405517580, 0.0733642578, 0.7105712892, 0.1234130860, 0.9290771487 }, + { 0.1175537110, 0.4002685548, 0.2999267579, 0.2901611329, 0.1617431641, 0.0023193359, 0.6986083986 }, + { 0.6175537111, 0.9002685549, 0.5499267579, 0.6651611330, 0.7867431642, 0.9398193362, 0.2611083985 }, + { 0.8675537111, 0.1502685547, 0.1124267578, 0.4307861329, 0.0523681641, 0.0687255860, 0.6400146486 }, + { 0.3675537110, 0.6502685548, 0.8624267580, 0.5557861329, 0.9273681643, 0.8812255861, 0.3275146485 }, + { 0.4925537111, 0.0252685547, 0.6749267580, 0.0089111328, 0.2554931641, 0.1351318360, 0.5032958986 }, + { 0.9925537112, 0.5252685548, 0.4249267579, 0.8839111330, 0.6304931642, 0.8226318361, 0.4407958985 }, + { 0.7425537111, 0.2752685548, 0.9874267580, 0.1495361328, 0.3961181642, 0.2015380860, 0.5697021486 }, + { 0.2425537110, 0.7752685549, 0.2374267579, 0.7745361330, 0.5211181642, 0.7640380861, 0.3822021485 }, + { 0.1800537110, 0.2127685547, 0.7843017580, 0.9776611330, 0.8492431643, 0.2679443360, 0.7767333986 }, + { 0.6800537111, 0.7127685549, 0.0343017578, 0.1026611328, 0.2242431641, 0.7054443361, 0.2142333985 }, + { 0.9300537112, 0.4627685548, 0.5968017580, 0.8682861330, 0.9898681643, 0.3343505860, 0.8431396486 }, + { 0.4300537110, 0.9627685549, 0.3468017579, 0.2432861329, 0.1148681641, 0.6468505861, 0.1556396485 }, + { 0.3050537110, 0.3377685548, 0.1593017578, 0.6964111330, 0.6929931642, 0.4007568360, 0.9564208987 }, + { 0.8050537111, 0.8377685549, 0.9093017580, 0.3214111329, 0.3179931641, 0.5882568361, 0.0189208984 }, + { 0.5550537111, 0.0877685547, 0.4718017579, 0.5870361329, 0.5836181642, 0.4671630860, 0.8978271486 }, + { 0.0550537110, 0.5877685548, 0.7218017580, 0.4620361329, 0.4586181642, 0.5296630861, 0.0853271485 }, + { 0.0394287109, 0.3533935548, 0.8350830080, 0.7647705080, 0.2847900391, 0.6622314455, 0.6671142580 }, + { 0.5394287111, 0.8533935549, 0.0850830078, 0.1397705078, 0.6597900392, 0.3497314454, 0.3546142579 }, + { 0.7894287111, 0.1033935547, 0.5225830079, 0.9053955080, 0.4254150392, 0.7208251955, 0.7335205080 }, + { 0.2894287110, 0.6033935548, 0.2725830079, 0.0303955078, 0.5504150392, 0.2833251954, 0.2960205079 } +}; + + +// Spatial dimension: 16 +// N: 100 +// Vectors skipped: 4096 +static const double niederreiter_base2_16_100[100][16] = +{ + { 0.0003662109, 0.4705810548, 0.6358642580, 0.9561767580, 0.6715087892, 0.9793701174, 0.6053466798, 0.1983642579, 0.2217731476, 0.3769855500, 0.5390644075, 0.4707050325, 0.2744159699, 0.9942340853, 0.5396728517, 0.0626220703 }, + { 0.5003662111, 0.9705810549, 0.3858642579, 0.0811767578, 0.2965087891, 0.0418701172, 0.4178466798, 0.7608642580, 0.7530231478, 0.5957355501, 0.4453144075, 0.5019550325, 0.7431659700, 0.0254840851, 0.4615478517, 0.9219970705 }, + { 0.7503662111, 0.2205810547, 0.9483642580, 0.8155517580, 0.5621337892, 0.9207763674, 0.5467529298, 0.1397705078, 0.1895465851, 0.4092121125, 0.5087909700, 0.4404315950, 0.3046894074, 0.9639606478, 0.5555419923, 0.0784912110 }, + { 0.2503662110, 0.7205810549, 0.1983642579, 0.1905517579, 0.4371337892, 0.1082763672, 0.4842529298, 0.8272705080, 0.7832965853, 0.5654621126, 0.4775409700, 0.5341815950, 0.7109394075, 0.0577106476, 0.4461669923, 0.9066162111 }, + { 0.3753662110, 0.0955810547, 0.2608642579, 0.7374267580, 0.7652587892, 0.8465576174, 0.6600341798, 0.0030517578, 0.1573200226, 0.4375324250, 0.6035175325, 0.3750019074, 0.3701190949, 0.8985309603, 0.5079345704, 0.0943603516 }, + { 0.8753662111, 0.5955810548, 0.5108642579, 0.3624267579, 0.1402587891, 0.1590576172, 0.3475341798, 0.9405517580, 0.8135700228, 0.5312824251, 0.3847675324, 0.5937519075, 0.6513690950, 0.1172809601, 0.4923095704, 0.8912353518 }, + { 0.6253662111, 0.3455810548, 0.0733642578, 0.5968017580, 0.9058837893, 0.7879638674, 0.7264404299, 0.0694580078, 0.1250934601, 0.4697589875, 0.5732440950, 0.4072284699, 0.3378925324, 0.9307575228, 0.5238037111, 0.1102294922 }, + { 0.1253662110, 0.8455810549, 0.8233642580, 0.4718017579, 0.0308837891, 0.2254638672, 0.2889404298, 0.8819580080, 0.8438434603, 0.5010089875, 0.4169940949, 0.5634784700, 0.6816425325, 0.0870075226, 0.4769287110, 0.8758544924 }, + { 0.1878662110, 0.1580810547, 0.1514892578, 0.2686767579, 0.3590087891, 0.7449951174, 0.9334716799, 0.3389892579, 0.1006793976, 0.2871418000, 0.6367206575, 0.2558612824, 0.4658222200, 0.8106403353, 0.6031494142, 0.0010986328 }, + { 0.6878662111, 0.6580810548, 0.9014892580, 0.6436767580, 0.7340087892, 0.3074951173, 0.1209716797, 0.6514892580, 0.8819293978, 0.6933918001, 0.3554706574, 0.7246112825, 0.5595722200, 0.2168903351, 0.4000244142, 0.9854736330 }, + { 0.9378662112, 0.4080810548, 0.4639892579, 0.3780517579, 0.4996337892, 0.6864013673, 0.9998779299, 0.2803955079, 0.0684528351, 0.2568683625, 0.6689472200, 0.2880878449, 0.4960956575, 0.7803668978, 0.6190185548, 0.0169677734 }, + { 0.4378662110, 0.9080810549, 0.7139892580, 0.5030517579, 0.6246337892, 0.3739013673, 0.0623779297, 0.7178955080, 0.9122028353, 0.7256183626, 0.3251972199, 0.6943378450, 0.5273456575, 0.2491168976, 0.3846435548, 0.9700927737 }, + { 0.3128662110, 0.2830810548, 0.7764892580, 0.0499267578, 0.2027587891, 0.6121826173, 0.8631591799, 0.3936767579, 0.0362262726, 0.3476886750, 0.7011737825, 0.3476581574, 0.4365253450, 0.8399372103, 0.5714111329, 0.0328369141 }, + { 0.8128662111, 0.7830810549, 0.0264892578, 0.9249267580, 0.8277587893, 0.4246826173, 0.1756591797, 0.5811767579, 0.9424762728, 0.6289386751, 0.2949237824, 0.6289081575, 0.5927753450, 0.1836872101, 0.4307861329, 0.9547119143 }, + { 0.5628662111, 0.0330810547, 0.5889892579, 0.1593017578, 0.0933837891, 0.5535888673, 0.8045654299, 0.4600830079, 0.0039997101, 0.3174152375, 0.7334003450, 0.3173847199, 0.4042987824, 0.8721637728, 0.5872802736, 0.0487060547 }, + { 0.0628662110, 0.5330810548, 0.3389892579, 0.7843017580, 0.9683837893, 0.4910888673, 0.2420654297, 0.5225830079, 0.9727497103, 0.6611652376, 0.2646503449, 0.6611347200, 0.6230487825, 0.1534137726, 0.4154052735, 0.9393310549 }, + { 0.0941162110, 0.0018310547, 0.9171142580, 0.5635986329, 0.4195556642, 0.3856201173, 0.3865966798, 0.9796142580, 0.4483356477, 0.1972980500, 0.8125019075, 0.0410175324, 0.1728534699, 0.6114215852, 0.6666259767, 0.2052001954 }, + { 0.5941162111, 0.5018310548, 0.1671142579, 0.4385986329, 0.5445556642, 0.5731201173, 0.5740966798, 0.0421142578, 0.5420856477, 0.7910480501, 0.1562519074, 0.9472675326, 0.8291034700, 0.3926715852, 0.3385009766, 0.7833251955 }, + { 0.8441162111, 0.2518310547, 0.7296142580, 0.7042236330, 0.3101806641, 0.4520263673, 0.4530029298, 0.9210205080, 0.4786090852, 0.2295246125, 0.8447284700, 0.0107440949, 0.1406269074, 0.5811481477, 0.6824951173, 0.1898193360 }, + { 0.3441162110, 0.7518310549, 0.4796142579, 0.3292236329, 0.6851806642, 0.5145263673, 0.5155029298, 0.1085205078, 0.5098590852, 0.7607746126, 0.1259784699, 0.9794940951, 0.8593769075, 0.4248981477, 0.3231201173, 0.7991943361 }, + { 0.4691162110, 0.3768310548, 0.0421142578, 0.8448486330, 0.0133056641, 0.2528076172, 0.3162841798, 0.7843017580, 0.3838825227, 0.1328449250, 0.7519550325, 0.0703144074, 0.2060565949, 0.5157184602, 0.6348876955, 0.2369384766 }, + { 0.9691162112, 0.8768310549, 0.7921142580, 0.2198486329, 0.8883056643, 0.6903076173, 0.6287841798, 0.2218017579, 0.6026325227, 0.8515949251, 0.2207050324, 0.9140644076, 0.7998065950, 0.4844684602, 0.3692626954, 0.7525634767 }, + { 0.7191162111, 0.1268310547, 0.3546142579, 0.9854736330, 0.1539306641, 0.3192138673, 0.2576904297, 0.8507080080, 0.4141559602, 0.1650714875, 0.7841815950, 0.1025409699, 0.2363300324, 0.5479450227, 0.6507568361, 0.2215576172 }, + { 0.2191162110, 0.6268310548, 0.6046142580, 0.1104736328, 0.7789306642, 0.6317138673, 0.6951904298, 0.1632080079, 0.5704059602, 0.8213214876, 0.1904315949, 0.8837909701, 0.7675800325, 0.4541950227, 0.3538818360, 0.7684326174 }, + { 0.1566162110, 0.3143310548, 0.4327392579, 0.1260986328, 0.6070556642, 0.1512451172, 0.0897216797, 0.6202392580, 0.3272418977, 0.1074543000, 0.9726581576, 0.2011737824, 0.1142597199, 0.6778278352, 0.7301025392, 0.1436767578 }, + { 0.6566162111, 0.8143310549, 0.6827392580, 0.7510986330, 0.4820556642, 0.8387451174, 0.9022216799, 0.4327392579, 0.6709918977, 0.8887043001, 0.0039081573, 0.7949237825, 0.8955097201, 0.3340778352, 0.2769775391, 0.8468017580 }, + { 0.9066162111, 0.0643310547, 0.2452392579, 0.0167236328, 0.7476806642, 0.2176513672, 0.0311279297, 0.5616455079, 0.3575153352, 0.0771808624, 0.9423847201, 0.2334003449, 0.0820331574, 0.6475543977, 0.7459716799, 0.1282958985 }, + { 0.4066162110, 0.5643310548, 0.9952392580, 0.8917236330, 0.3726806641, 0.7801513674, 0.9686279299, 0.4991455079, 0.6387653352, 0.9209308626, 0.0361347199, 0.7646503450, 0.9257831576, 0.3663043977, 0.2615966797, 0.8626708986 }, + { 0.2816162110, 0.1893310547, 0.5577392579, 0.4073486329, 0.9508056643, 0.0184326172, 0.1444091797, 0.6749267580, 0.2627887726, 0.0430011749, 0.9121112826, 0.1679706574, 0.0224628449, 0.7071247102, 0.6983642580, 0.1754150391 }, + { 0.7816162111, 0.6893310548, 0.3077392579, 0.5323486329, 0.0758056641, 0.9559326174, 0.8319091799, 0.3624267579, 0.7315387728, 0.9492511751, 0.0683612824, 0.8242206575, 0.9912128451, 0.3008747102, 0.3077392579, 0.8160400393 }, + { 0.5316162111, 0.4393310548, 0.8702392580, 0.2979736329, 0.8414306643, 0.0848388672, 0.2108154297, 0.7413330080, 0.2930622102, 0.0127277374, 0.8818378451, 0.1376972199, 0.0527362824, 0.7393512728, 0.7142333986, 0.1600341797 }, + { 0.0316162109, 0.9393310549, 0.1202392578, 0.6729736330, 0.2164306641, 0.8973388674, 0.7733154299, 0.3038330079, 0.6993122102, 0.9814777377, 0.1005878449, 0.8564472200, 0.9589862826, 0.2706012726, 0.2923583985, 0.8319091799 }, + { 0.0472412109, 0.2362060547, 0.4522705079, 0.1007080078, 0.0426025391, 0.7955322267, 0.4801025392, 0.7025146486, 0.6748981477, 0.7988605501, 0.2421894074, 0.6113300325, 0.5712909700, 0.1973590851, 0.7935791017, 0.3477783204 }, + { 0.5472412111, 0.7362060549, 0.7022705080, 0.9757080080, 0.9176025393, 0.2330322266, 0.5426025392, 0.2650146485, 0.3311481477, 0.2051105500, 0.7734394075, 0.3925800324, 0.4150409699, 0.7911090853, 0.2154541016, 0.6446533205 }, + { 0.7972412111, 0.4862060548, 0.1397705078, 0.2413330079, 0.1832275391, 0.8541259768, 0.4215087892, 0.6361083986, 0.6426715852, 0.7685871126, 0.2119159699, 0.5810565950, 0.6015644075, 0.2295856476, 0.8094482424, 0.3636474610 }, + { 0.2972412110, 0.9862060549, 0.8897705080, 0.8663330080, 0.8082275393, 0.1666259766, 0.6090087892, 0.3236083985, 0.3614215852, 0.2373371125, 0.8056659700, 0.4248065949, 0.3828144074, 0.7608356478, 0.2000732422, 0.6292724611 }, + { 0.4222412110, 0.3612060548, 0.5772705079, 0.3194580079, 0.3863525392, 0.9127197268, 0.2847900391, 0.5072021486, 0.7354450228, 0.8594074251, 0.1816425324, 0.5156269075, 0.5419940950, 0.1641559601, 0.7618408205, 0.3170166016 }, + { 0.9222412112, 0.8612060549, 0.3272705079, 0.6944580080, 0.5113525392, 0.1002197266, 0.7222900392, 0.4447021485, 0.2666950226, 0.1406574250, 0.8378925325, 0.4843769075, 0.4482440950, 0.8204059603, 0.2462158204, 0.6763916017 }, + { 0.6722412111, 0.1112060547, 0.7647705080, 0.4600830079, 0.2769775391, 0.9713134768, 0.3511962891, 0.5657958986, 0.7032184602, 0.8291339876, 0.1513690949, 0.5478534700, 0.5097675325, 0.1338825226, 0.7777099611, 0.3328857423 }, + { 0.1722412110, 0.6112060548, 0.0147705078, 0.5850830079, 0.6519775392, 0.0338134766, 0.6636962892, 0.3782958985, 0.2969684602, 0.1728839875, 0.8701190951, 0.4541034700, 0.4785175325, 0.8526325228, 0.2308349610, 0.6610107423 }, + { 0.2347412110, 0.4237060548, 0.9678955080, 0.6632080080, 0.9801025393, 0.5611572267, 0.0582275391, 0.8431396486, 0.5538043977, 0.8965168001, 0.0898456574, 0.6464862825, 0.6376972200, 0.0137653351, 0.8570556643, 0.2862548829 }, + { 0.7347412111, 0.9237060549, 0.2178955079, 0.2882080079, 0.1051025391, 0.4986572267, 0.9957275393, 0.1556396485, 0.4600543977, 0.1152668000, 0.9335956576, 0.3652362824, 0.3564472199, 0.9825153353, 0.1539306641, 0.7081298830 }, + { 0.9847412112, 0.1737060547, 0.6553955080, 0.5538330079, 0.8707275393, 0.6197509767, 0.1246337891, 0.7767333986, 0.5215778352, 0.9287433626, 0.1220722199, 0.6787128450, 0.6679706575, 0.0459918976, 0.8729248049, 0.3021240235 }, + { 0.4847412111, 0.6737060548, 0.4053955079, 0.4288330079, 0.2457275391, 0.4322509767, 0.9371337893, 0.2142333985, 0.4903278352, 0.0849933624, 0.9033222201, 0.3349628449, 0.3242206574, 0.9522418978, 0.1385498047, 0.6927490236 }, + { 0.3597412110, 0.0487060547, 0.0928955078, 0.8819580080, 0.5738525392, 0.6783447267, 0.2379150391, 0.8978271486, 0.6143512727, 0.9570636751, 0.0292987824, 0.7382831575, 0.7334003450, 0.1055622101, 0.8253173830, 0.2554931641 }, + { 0.8597412111, 0.5487060548, 0.8428955080, 0.0069580078, 0.4488525392, 0.3658447266, 0.8004150392, 0.0853271485, 0.3956012727, 0.0508136749, 0.9980487826, 0.2695331574, 0.2646503449, 0.8868122103, 0.1846923829, 0.7398681642 }, + { 0.6097412111, 0.2987060548, 0.2803955079, 0.7725830080, 0.7144775392, 0.7369384767, 0.1793212891, 0.9564208987, 0.5821247102, 0.9892902377, 0.0615253449, 0.7080097200, 0.7011737825, 0.0752887726, 0.8411865236, 0.2713623048 }, + { 0.1097412110, 0.7987060549, 0.5303955079, 0.1475830078, 0.3394775391, 0.2994384766, 0.8668212893, 0.0189208984, 0.4258747102, 0.0205402374, 0.9677753451, 0.3017597199, 0.2949237824, 0.9190387728, 0.1693115235, 0.7244873049 }, + { 0.0784912110, 0.2674560547, 0.2335205079, 0.4893798829, 0.7906494142, 0.3267822266, 0.5113525392, 0.4837646486, 0.9014606478, 0.6191730501, 0.3906269074, 0.9316425326, 0.9697284701, 0.3145465852, 0.9205322268, 0.4903564454 }, + { 0.5784912111, 0.7674560549, 0.9835205080, 0.6143798830, 0.1656494141, 0.6392822267, 0.4488525392, 0.5462646486, 0.1202106476, 0.4004230500, 0.6093769075, 0.0878925324, 0.0009784698, 0.6582965852, 0.0924072266, 0.5059814454 }, + { 0.8284912111, 0.0174560547, 0.4210205079, 0.3487548829, 0.9312744143, 0.2603759766, 0.5777587892, 0.4173583985, 0.9317340853, 0.5888996126, 0.4228534699, 0.9013690951, 0.9375019076, 0.3467731477, 0.9364013674, 0.4749755860 }, + { 0.3284912110, 0.5174560548, 0.6710205080, 0.7237548830, 0.0562744141, 0.6978759767, 0.3902587892, 0.6048583986, 0.0879840851, 0.4326496125, 0.5791034700, 0.1201190949, 0.0312519074, 0.6280231477, 0.0770263672, 0.5218505861 }, + { 0.4534912110, 0.1424560547, 0.8585205080, 0.2081298829, 0.6343994142, 0.4439697267, 0.6910400392, 0.2884521485, 0.9620075228, 0.5547199251, 0.4550800325, 0.9609394076, 0.8779315951, 0.2813434601, 0.8887939455, 0.4595947267 }, + { 0.9534912112, 0.6424560548, 0.1085205078, 0.8331298830, 0.2593994141, 0.5064697267, 0.2535400391, 0.7259521486, 0.0557575226, 0.4609699250, 0.5488300325, 0.0546894074, 0.0966815949, 0.6875934602, 0.1231689453, 0.5377197267 }, + { 0.7034912111, 0.3924560548, 0.5460205079, 0.0675048828, 0.5250244142, 0.3775634767, 0.6324462892, 0.3470458985, 0.9922809603, 0.5244464875, 0.4873065950, 0.9931659701, 0.9082050326, 0.2510700226, 0.9046630861, 0.4442138673 }, + { 0.2034912110, 0.8924560549, 0.2960205079, 0.9425048830, 0.4000244142, 0.5650634767, 0.3199462891, 0.6595458986, 0.0235309601, 0.4931964875, 0.5185565950, 0.0244159699, 0.0644550324, 0.7198200228, 0.1077880860, 0.5535888673 }, + { 0.1409912110, 0.0799560547, 0.7491455080, 0.8018798830, 0.2281494141, 0.0924072266, 0.9644775393, 0.1243896485, 0.7803668978, 0.7168293001, 0.3007831574, 0.8417987825, 0.7861347200, 0.3809528352, 0.9840087893, 0.4288330079 }, + { 0.6409912111, 0.5799560548, 0.4991455079, 0.1768798829, 0.8531494143, 0.9049072268, 0.0269775391, 0.9368896487, 0.2491168976, 0.3105793000, 0.7070331575, 0.1855487824, 0.1923847199, 0.5997028352, 0.0308837891, 0.5694580079 }, + { 0.8909912111, 0.3299560548, 0.9366455080, 0.9112548830, 0.1187744141, 0.0260009766, 0.9058837893, 0.0579833985, 0.8106403353, 0.7490558626, 0.2705097199, 0.8740253451, 0.7539081575, 0.4131793977, 0.9998779299, 0.4134521485 }, + { 0.3909912110, 0.8299560549, 0.1866455079, 0.0362548828, 0.9937744143, 0.9635009768, 0.0933837891, 0.9954833987, 0.2168903351, 0.2803058625, 0.7392597200, 0.1552753449, 0.2226581574, 0.5694293977, 0.0155029297, 0.5853271486 }, + { 0.2659912110, 0.4549560548, 0.3741455079, 0.5206298829, 0.3218994141, 0.2095947266, 0.7691650392, 0.1790771485, 0.8409137728, 0.6523761751, 0.3652362824, 0.8085956575, 0.8193378450, 0.4727497102, 0.9522705080, 0.3980712892 }, + { 0.7659912111, 0.9549560549, 0.6241455080, 0.3956298829, 0.6968994142, 0.7720947267, 0.2066650391, 0.8665771486, 0.1846637726, 0.3711261750, 0.6464862825, 0.2148456574, 0.1630878449, 0.5039997102, 0.0616455078, 0.6011962892 }, + { 0.5159912111, 0.2049560547, 0.0616455078, 0.6300048830, 0.4625244142, 0.1431884766, 0.8355712893, 0.2376708985, 0.8711872103, 0.6846027376, 0.3349628449, 0.7783222200, 0.8496112825, 0.4424762727, 0.9681396487, 0.3826904298 }, + { 0.0159912109, 0.7049560549, 0.8116455080, 0.2550048829, 0.5875244142, 0.8306884768, 0.1480712891, 0.8001708986, 0.1524372101, 0.3408527375, 0.6787128450, 0.2470722199, 0.1308612824, 0.5362262727, 0.0462646484, 0.6170654298 }, + { 0.0238037109, 0.1190185547, 0.0186767578, 0.1827392579, 0.9136962893, 0.5960693361, 0.2923583985, 0.1285400391, 0.0645160675, 0.2207050324, 0.8828449251, 0.6894855501, 0.9297199251, 0.4326801301, 0.0474853516, 0.5079345704 }, + { 0.5238037111, 0.6190185548, 0.7686767580, 0.8077392580, 0.0386962891, 0.4085693360, 0.7298583986, 0.8160400393, 0.9082660677, 0.7519550325, 0.1015949250, 0.2832355500, 0.0859699249, 0.5889301301, 0.9381103518, 0.4923095704 }, + { 0.7738037111, 0.3690185548, 0.3311767579, 0.0421142578, 0.8043212892, 0.5374755861, 0.3587646485, 0.1949462891, 0.0967426300, 0.1904315949, 0.9150714876, 0.7217121126, 0.8994464876, 0.4004535676, 0.0321044922, 0.5238037111 }, + { 0.2738037110, 0.8690185549, 0.5811767579, 0.9171142580, 0.1793212891, 0.4749755860, 0.6712646486, 0.7574462892, 0.8779926302, 0.7841815950, 0.0713214874, 0.2529621125, 0.1181964875, 0.6192035676, 0.9539794924, 0.4769287110 }, + { 0.3988037110, 0.4940185548, 0.8936767580, 0.4014892579, 0.5074462892, 0.7288818361, 0.4720458985, 0.0738525391, 0.0000629425, 0.1562519074, 0.9472980501, 0.6562824251, 0.9629230502, 0.4619770051, 0.0157470703, 0.5396728517 }, + { 0.8988037111, 0.9940185549, 0.1436767578, 0.5264892579, 0.3824462892, 0.2913818360, 0.5345458986, 0.8863525393, 0.9688129427, 0.8125019075, 0.0410480499, 0.3125324250, 0.0566730499, 0.5557270051, 0.9688720705, 0.4615478517 }, + { 0.6488037111, 0.2440185547, 0.7061767580, 0.2608642579, 0.6480712892, 0.6702880861, 0.4134521485, 0.0152587891, 0.0322895050, 0.1259784699, 0.9795246127, 0.6260089876, 0.9951496127, 0.4922504426, 0.0003662109, 0.5555419923 }, + { 0.1488037110, 0.7440185549, 0.4561767579, 0.6358642580, 0.2730712891, 0.3577880860, 0.6009521486, 0.9527587893, 0.9385395052, 0.8447284700, 0.0107746124, 0.3447589875, 0.0263996124, 0.5235004426, 0.9847412112, 0.4461669923 }, + { 0.2113037110, 0.3065185548, 0.5030517579, 0.6202392580, 0.1011962891, 0.8616943361, 0.2454833985, 0.2691650391, 0.1934223175, 0.0683612824, 0.7930011751, 0.5371418001, 0.8711261751, 0.3740863801, 0.1109619141, 0.5714111329 }, + { 0.7113037111, 0.8065185549, 0.2530517579, 0.4952392579, 0.9761962893, 0.1741943360, 0.8079833986, 0.7066650392, 0.7871723177, 0.9121112826, 0.1992511750, 0.4433918000, 0.1523761750, 0.6553363802, 0.8765869143, 0.4307861329 }, + { 0.9613037112, 0.0565185547, 0.8155517580, 0.7296142580, 0.2418212891, 0.8031005861, 0.1868896485, 0.3355712891, 0.2256488801, 0.1005878449, 0.7627277376, 0.5068683625, 0.8408527376, 0.3418598176, 0.0955810547, 0.5872802736 }, + { 0.4613037110, 0.5565185548, 0.0655517578, 0.3546142579, 0.8668212893, 0.2406005860, 0.8743896486, 0.6480712892, 0.7568988802, 0.8818378451, 0.2314777375, 0.4756183625, 0.1846027375, 0.6856098177, 0.8924560549, 0.4154052735 }, + { 0.3363037110, 0.1815185547, 0.3780517579, 0.8389892580, 0.4449462892, 0.9945068362, 0.0501708984, 0.4644775392, 0.1289691925, 0.0039081573, 0.8574543001, 0.5664386751, 0.7793293001, 0.2783832551, 0.0792236328, 0.6031494142 }, + { 0.8363037111, 0.6815185548, 0.6280517580, 0.2139892579, 0.5699462892, 0.0570068360, 0.9876708987, 0.5269775392, 0.8477191927, 0.9726581576, 0.1387043000, 0.4101886750, 0.2480793000, 0.7471332552, 0.9073486330, 0.4000244142 }, + { 0.5863037111, 0.4315185548, 0.1905517579, 0.9483642580, 0.3355712891, 0.9359130862, 0.1165771485, 0.4058837892, 0.1611957550, 0.0361347199, 0.8271808626, 0.5986652376, 0.8115558626, 0.3086566926, 0.0638427735, 0.6190185548 }, + { 0.0863037110, 0.9315185549, 0.9405517580, 0.0733642578, 0.7105712892, 0.1234130860, 0.9290771487, 0.5933837892, 0.8174457552, 0.9423847201, 0.1709308625, 0.3799152375, 0.2178058625, 0.7149066927, 0.9232177737, 0.3846435548 }, + { 0.1175537110, 0.4002685548, 0.2999267579, 0.2901611329, 0.1617431641, 0.0023193359, 0.6986083986, 0.9097900393, 0.3535785676, 0.4160175324, 0.7187824251, 0.7597980501, 0.5156574250, 0.0498676300, 0.1744384766, 0.6505126955 }, + { 0.6175537111, 0.9002685549, 0.5499267579, 0.6651611330, 0.7867431642, 0.9398193362, 0.2611083985, 0.0972900391, 0.6348285677, 0.5722675325, 0.2500324250, 0.2285480500, 0.4844074250, 0.9561176302, 0.8150634768, 0.3536376954 }, + { 0.8675537111, 0.1502685547, 0.1124267578, 0.4307861329, 0.0523681641, 0.0687255860, 0.6400146486, 0.9761962893, 0.3233051301, 0.3857440949, 0.6885089876, 0.7920246126, 0.5478839876, 0.0176410675, 0.1590576172, 0.6351318361 }, + { 0.3675537110, 0.6502685548, 0.8624267580, 0.5557861329, 0.9273681643, 0.8812255861, 0.3275146485, 0.0386962891, 0.6670551302, 0.6044940950, 0.2822589875, 0.1982746125, 0.4541339875, 0.9863910677, 0.8309326174, 0.3695068360 }, + { 0.4925537111, 0.0252685547, 0.6749267580, 0.0089111328, 0.2554931641, 0.1351318360, 0.5032958986, 0.8551025393, 0.2891254426, 0.4765644075, 0.6582355501, 0.8515949251, 0.6113605501, 0.0791645050, 0.1427001953, 0.6822509767 }, + { 0.9925537112, 0.5252685548, 0.4249267579, 0.8839111330, 0.6304931642, 0.8226318361, 0.4407958985, 0.1676025391, 0.6953754427, 0.5078144075, 0.3144855500, 0.1328449250, 0.3926105500, 0.9229145052, 0.8458251955, 0.3228759766 }, + { 0.7425537111, 0.2752685548, 0.9874267580, 0.1495361328, 0.3961181642, 0.2015380860, 0.5697021486, 0.7965087892, 0.2588520051, 0.4462909700, 0.6279621126, 0.8213214876, 0.5810871126, 0.1094379425, 0.1273193360, 0.6668701173 }, + { 0.2425537110, 0.7752685549, 0.2374267579, 0.7745361330, 0.5211181642, 0.7640380861, 0.3822021485, 0.2340087891, 0.7276020052, 0.5400409700, 0.3467121125, 0.1650714875, 0.4248371125, 0.8906879427, 0.8616943361, 0.3387451173 }, + { 0.1800537110, 0.2127685547, 0.7843017580, 0.9776611330, 0.8492431643, 0.2679443360, 0.7767333986, 0.5504150392, 0.4824848176, 0.2636737824, 0.5664386751, 0.9824543002, 0.7070636751, 0.2412738801, 0.2379150391, 0.7139892580 }, + { 0.6800537111, 0.7127685549, 0.0343017578, 0.1026611328, 0.2242431641, 0.7054443361, 0.2142333985, 0.4879150392, 0.5137348176, 0.7324237825, 0.4101886750, 0.0137042999, 0.3008136750, 0.7725238802, 0.7535400392, 0.2921142579 }, + { 0.9300537112, 0.4627685548, 0.5968017580, 0.8682861330, 0.9898681643, 0.3343505860, 0.8431396486, 0.6168212892, 0.4522113801, 0.2959003449, 0.5986652376, 0.9521808626, 0.7392902376, 0.2090473176, 0.2225341797, 0.6986083986 }, + { 0.4300537110, 0.9627685549, 0.3468017579, 0.2432861329, 0.1148681641, 0.6468505861, 0.1556396485, 0.4293212892, 0.5459613801, 0.7021503450, 0.3799152375, 0.0459308624, 0.2705402375, 0.8027973177, 0.7694091799, 0.3079833985 }, + { 0.3050537110, 0.3377685548, 0.1593017578, 0.6964111330, 0.6929931642, 0.4007568360, 0.9564208987, 0.7457275392, 0.4180316926, 0.3242206574, 0.5058918000, 0.8867511751, 0.6777668001, 0.1455707550, 0.2061767579, 0.7457275392 }, + { 0.8050537111, 0.8377685549, 0.9093017580, 0.3214111329, 0.3179931641, 0.5882568361, 0.0189208984, 0.3082275391, 0.5742816926, 0.6679706575, 0.4746418000, 0.1055011750, 0.3340168000, 0.8643207552, 0.7843017580, 0.2613525391 }, + { 0.5550537111, 0.0877685547, 0.4718017579, 0.5870361329, 0.5836181642, 0.4671630860, 0.8978271486, 0.6871337892, 0.3877582551, 0.3564472199, 0.5381183626, 0.9189777376, 0.6474933626, 0.1758441925, 0.1907958985, 0.7303466799 }, + { 0.0550537110, 0.5877685548, 0.7218017580, 0.4620361329, 0.4586181642, 0.5296630861, 0.0853271485, 0.3746337891, 0.6065082551, 0.6376972200, 0.4443683625, 0.0752277374, 0.3662433625, 0.8320941927, 0.8001708986, 0.2772216798 }, + { 0.0394287109, 0.3533935548, 0.8350830080, 0.7647705080, 0.2847900391, 0.6622314455, 0.6671142580, 0.6326904298, 0.5176410676, 0.5800800325, 0.3359699250, 0.3301105500, 0.2265949250, 0.6358051302, 0.3013916016, 0.7930908205 }, + { 0.5394287111, 0.8533935549, 0.0850830078, 0.1397705078, 0.6597900392, 0.3497314454, 0.3546142579, 0.3201904298, 0.4863910676, 0.4238300324, 0.6797199251, 0.6738605501, 0.7578449251, 0.3545551301, 0.6920166017, 0.2149658204 }, + { 0.7894287111, 0.1033935547, 0.5225830079, 0.9053955080, 0.4254150392, 0.7208251955, 0.7335205080, 0.6912841798, 0.5498676301, 0.6123065950, 0.3681964875, 0.3623371125, 0.1963214875, 0.6660785677, 0.2860107423, 0.8089599611 }, + { 0.2894287110, 0.6033935548, 0.2725830079, 0.0303955078, 0.5504150392, 0.2833251954, 0.2960205079, 0.2537841797, 0.4561176301, 0.3935565949, 0.6494464876, 0.6435871126, 0.7900714876, 0.3223285676, 0.7078857424, 0.1995849610 } +}; + + +QRNG_VALIDATION_TEST_FUNCTIONS(niederreiter_base2) + + +BOOST_AUTO_TEST_CASE( validate_niederreiter_base2 ) +{ + test_niederreiter_base2_values(niederreiter_base2_02_100, 4096); + test_niederreiter_base2_values(niederreiter_base2_07_100, 4096); + test_niederreiter_base2_values(niederreiter_base2_16_100, 4096); +} + +BOOST_AUTO_TEST_CASE( validate_niederreiter_base2_seed ) +{ + test_niederreiter_base2_seed(niederreiter_base2_02_100, 4096); + test_niederreiter_base2_seed(niederreiter_base2_07_100, 4096); + test_niederreiter_base2_seed(niederreiter_base2_16_100, 4096); +} + +BOOST_AUTO_TEST_CASE( validate_niederreiter_base2_discard ) +{ + test_niederreiter_base2_discard(niederreiter_base2_02_100, 4096); + test_niederreiter_base2_discard(niederreiter_base2_07_100, 4096); + test_niederreiter_base2_discard(niederreiter_base2_16_100, 4096); +} diff --git a/test/sobol_validate.cpp b/test/sobol_validate.cpp new file mode 100644 index 0000000..b2c0a4c --- /dev/null +++ b/test/sobol_validate.cpp @@ -0,0 +1,371 @@ +// Copyright Justinas Vygintas Daugmaudis, 2010. +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) + +#include + +#include + +#define BOOST_TEST_MAIN +#include + +#include "test_qrng_functions.hpp" + + +// +// DESCRIPTION: +// ~~~~~~~~~~~~ +// +// This file tests the sobol quasi-random number generator. +// These tests compare our results with values produced by the original +// version of ACM TOMS Algorithm 659, which is available in the +// TOMS subdirectory in http://www.netlib.org +// +// For independently generated datasets look at http://people.sc.fsu.edu/~jburkardt/datasets/sobol/ + + +// Spatial dimension: 2 +// N: 100 +// Vectors skipped: 0 +static const double sobol_02_100[100][2] = +{ + { 0.0000000000, 0.0000000000 }, + { 0.5000000002, 0.5000000002 }, + { 0.7500000003, 0.2500000001 }, + { 0.2500000001, 0.7500000003 }, + { 0.3750000002, 0.3750000002 }, + { 0.8750000004, 0.8750000004 }, + { 0.6250000003, 0.1250000001 }, + { 0.1250000001, 0.6250000003 }, + { 0.1875000001, 0.3125000001 }, + { 0.6875000003, 0.8125000004 }, + { 0.9375000004, 0.0625000000 }, + { 0.4375000002, 0.5625000003 }, + { 0.3125000001, 0.1875000001 }, + { 0.8125000004, 0.6875000003 }, + { 0.5625000003, 0.4375000002 }, + { 0.0625000000, 0.9375000004 }, + { 0.0937500000, 0.4687500002 }, + { 0.5937500003, 0.9687500005 }, + { 0.8437500004, 0.2187500001 }, + { 0.3437500002, 0.7187500003 }, + { 0.4687500002, 0.0937500000 }, + { 0.9687500005, 0.5937500003 }, + { 0.7187500003, 0.3437500002 }, + { 0.2187500001, 0.8437500004 }, + { 0.1562500001, 0.1562500001 }, + { 0.6562500003, 0.6562500003 }, + { 0.9062500004, 0.4062500002 }, + { 0.4062500002, 0.9062500004 }, + { 0.2812500001, 0.2812500001 }, + { 0.7812500004, 0.7812500004 }, + { 0.5312500002, 0.0312500000 }, + { 0.0312500000, 0.5312500002 }, + { 0.0468750000, 0.2656250001 }, + { 0.5468750003, 0.7656250004 }, + { 0.7968750004, 0.0156250000 }, + { 0.2968750001, 0.5156250002 }, + { 0.4218750002, 0.1406250001 }, + { 0.9218750004, 0.6406250003 }, + { 0.6718750003, 0.3906250002 }, + { 0.1718750001, 0.8906250004 }, + { 0.2343750001, 0.0781250000 }, + { 0.7343750003, 0.5781250003 }, + { 0.9843750005, 0.3281250002 }, + { 0.4843750002, 0.8281250004 }, + { 0.3593750002, 0.4531250002 }, + { 0.8593750004, 0.9531250004 }, + { 0.6093750003, 0.2031250001 }, + { 0.1093750001, 0.7031250003 }, + { 0.0781250000, 0.2343750001 }, + { 0.5781250003, 0.7343750003 }, + { 0.8281250004, 0.4843750002 }, + { 0.3281250002, 0.9843750005 }, + { 0.4531250002, 0.3593750002 }, + { 0.9531250004, 0.8593750004 }, + { 0.7031250003, 0.1093750001 }, + { 0.2031250001, 0.6093750003 }, + { 0.1406250001, 0.4218750002 }, + { 0.6406250003, 0.9218750004 }, + { 0.8906250004, 0.1718750001 }, + { 0.3906250002, 0.6718750003 }, + { 0.2656250001, 0.0468750000 }, + { 0.7656250004, 0.5468750003 }, + { 0.5156250002, 0.2968750001 }, + { 0.0156250000, 0.7968750004 }, + { 0.0234375000, 0.3984375002 }, + { 0.5234375002, 0.8984375004 }, + { 0.7734375004, 0.1484375001 }, + { 0.2734375001, 0.6484375003 }, + { 0.3984375002, 0.0234375000 }, + { 0.8984375004, 0.5234375002 }, + { 0.6484375003, 0.2734375001 }, + { 0.1484375001, 0.7734375004 }, + { 0.2109375001, 0.2109375001 }, + { 0.7109375003, 0.7109375003 }, + { 0.9609375004, 0.4609375002 }, + { 0.4609375002, 0.9609375004 }, + { 0.3359375002, 0.3359375002 }, + { 0.8359375004, 0.8359375004 }, + { 0.5859375003, 0.0859375000 }, + { 0.0859375000, 0.5859375003 }, + { 0.1171875001, 0.1171875001 }, + { 0.6171875003, 0.6171875003 }, + { 0.8671875004, 0.3671875002 }, + { 0.3671875002, 0.8671875004 }, + { 0.4921875002, 0.4921875002 }, + { 0.9921875005, 0.9921875005 }, + { 0.7421875003, 0.2421875001 }, + { 0.2421875001, 0.7421875003 }, + { 0.1796875001, 0.3046875001 }, + { 0.6796875003, 0.8046875004 }, + { 0.9296875004, 0.0546875000 }, + { 0.4296875002, 0.5546875003 }, + { 0.3046875001, 0.1796875001 }, + { 0.8046875004, 0.6796875003 }, + { 0.5546875003, 0.4296875002 }, + { 0.0546875000, 0.9296875004 }, + { 0.0390625000, 0.1328125001 }, + { 0.5390625003, 0.6328125003 }, + { 0.7890625004, 0.3828125002 }, + { 0.2890625001, 0.8828125004 } +}; + +// Spatial dimension: 7 +// N: 100 +// Vectors skipped: 128 +static const double sobol_07_100[100][7] = +{ + { 0.0117187500, 0.3320312502, 0.7851562504, 0.9414062504, 0.4648437502, 0.4179687502, 0.4648437502 }, + { 0.5117187502, 0.8320312504, 0.2851562501, 0.4414062502, 0.9648437504, 0.9179687504, 0.9648437504 }, + { 0.7617187504, 0.0820312500, 0.0351562500, 0.6914062503, 0.7148437503, 0.1679687501, 0.7148437503 }, + { 0.2617187501, 0.5820312503, 0.5351562502, 0.1914062501, 0.2148437501, 0.6679687503, 0.2148437501 }, + { 0.3867187502, 0.2070312501, 0.4101562502, 0.8164062504, 0.5898437503, 0.5429687503, 0.3398437502 }, + { 0.8867187504, 0.7070312503, 0.9101562504, 0.3164062501, 0.0898437500, 0.0429687500, 0.8398437504 }, + { 0.6367187503, 0.4570312502, 0.6601562503, 0.5664062503, 0.3398437502, 0.7929687504, 0.5898437503 }, + { 0.1367187501, 0.9570312504, 0.1601562501, 0.0664062500, 0.8398437504, 0.2929687501, 0.0898437500 }, + { 0.1992187501, 0.0195312500, 0.5976562503, 0.2539062501, 0.9023437504, 0.3554687502, 0.4023437502 }, + { 0.6992187503, 0.5195312502, 0.0976562500, 0.7539062504, 0.4023437502, 0.8554687504, 0.9023437504 }, + { 0.9492187504, 0.2695312501, 0.3476562502, 0.0039062500, 0.1523437501, 0.1054687500, 0.6523437503 }, + { 0.4492187502, 0.7695312504, 0.8476562504, 0.5039062502, 0.6523437503, 0.6054687503, 0.1523437501 }, + { 0.3242187502, 0.3945312502, 0.2226562501, 0.3789062502, 0.0273437500, 0.7304687503, 0.2773437501 }, + { 0.8242187504, 0.8945312504, 0.7226562503, 0.8789062504, 0.5273437502, 0.2304687501, 0.7773437504 }, + { 0.5742187503, 0.1445312501, 0.9726562505, 0.1289062501, 0.7773437504, 0.9804687505, 0.5273437502 }, + { 0.0742187500, 0.6445312503, 0.4726562502, 0.6289062503, 0.2773437501, 0.4804687502, 0.0273437500 }, + { 0.1054687500, 0.1757812501, 0.0664062500, 0.5976562503, 0.2460937501, 0.1992187501, 0.9960937505 }, + { 0.6054687503, 0.6757812503, 0.5664062503, 0.0976562500, 0.7460937503, 0.6992187503, 0.4960937502 }, + { 0.8554687504, 0.4257812502, 0.8164062504, 0.8476562504, 0.9960937505, 0.4492187502, 0.2460937501 }, + { 0.3554687502, 0.9257812504, 0.3164062501, 0.3476562502, 0.4960937502, 0.9492187504, 0.7460937503 }, + { 0.4804687502, 0.3007812501, 0.6914062503, 0.7226562503, 0.8710937504, 0.8242187504, 0.8710937504 }, + { 0.9804687505, 0.8007812504, 0.1914062501, 0.2226562501, 0.3710937502, 0.3242187502, 0.3710937502 }, + { 0.7304687503, 0.0507812500, 0.4414062502, 0.9726562505, 0.1210937501, 0.5742187503, 0.1210937501 }, + { 0.2304687501, 0.5507812503, 0.9414062504, 0.4726562502, 0.6210937503, 0.0742187500, 0.6210937503 }, + { 0.1679687501, 0.4882812502, 0.2539062501, 0.1601562501, 0.6835937503, 0.0117187500, 0.9335937504 }, + { 0.6679687503, 0.9882812505, 0.7539062504, 0.6601562503, 0.1835937501, 0.5117187502, 0.4335937502 }, + { 0.9179687504, 0.2382812501, 0.5039062502, 0.4101562502, 0.4335937502, 0.2617187501, 0.1835937501 }, + { 0.4179687502, 0.7382812503, 0.0039062500, 0.9101562504, 0.9335937504, 0.7617187504, 0.6835937503 }, + { 0.2929687501, 0.1132812501, 0.8789062504, 0.0351562500, 0.3085937501, 0.8867187504, 0.8085937504 }, + { 0.7929687504, 0.6132812503, 0.3789062502, 0.5351562502, 0.8085937504, 0.3867187502, 0.3085937501 }, + { 0.5429687503, 0.3632812502, 0.1289062501, 0.2851562501, 0.5585937503, 0.6367187503, 0.0585937500 }, + { 0.0429687500, 0.8632812504, 0.6289062503, 0.7851562504, 0.0585937500, 0.1367187501, 0.5585937503 }, + { 0.0585937500, 0.0664062500, 0.3320312502, 0.3945312502, 0.7617187504, 0.8085937504, 0.1992187501 }, + { 0.5585937503, 0.5664062503, 0.8320312504, 0.8945312504, 0.2617187501, 0.3085937501, 0.6992187503 }, + { 0.8085937504, 0.3164062501, 0.5820312503, 0.1445312501, 0.0117187500, 0.5585937503, 0.9492187504 }, + { 0.3085937501, 0.8164062504, 0.0820312500, 0.6445312503, 0.5117187502, 0.0585937500, 0.4492187502 }, + { 0.4335937502, 0.4414062502, 0.9570312504, 0.2695312501, 0.1367187501, 0.1835937501, 0.0742187500 }, + { 0.9335937504, 0.9414062504, 0.4570312502, 0.7695312504, 0.6367187503, 0.6835937503, 0.5742187503 }, + { 0.6835937503, 0.1914062501, 0.2070312501, 0.0195312500, 0.8867187504, 0.4335937502, 0.8242187504 }, + { 0.1835937501, 0.6914062503, 0.7070312503, 0.5195312502, 0.3867187502, 0.9335937504, 0.3242187502 }, + { 0.2460937501, 0.2539062501, 0.0195312500, 0.8320312504, 0.3242187502, 0.9960937505, 0.1367187501 }, + { 0.7460937503, 0.7539062504, 0.5195312502, 0.3320312502, 0.8242187504, 0.4960937502, 0.6367187503 }, + { 0.9960937505, 0.0039062500, 0.7695312504, 0.5820312503, 0.5742187503, 0.7460937503, 0.8867187504 }, + { 0.4960937502, 0.5039062502, 0.2695312501, 0.0820312500, 0.0742187500, 0.2460937501, 0.3867187502 }, + { 0.3710937502, 0.1289062501, 0.6445312503, 0.9570312504, 0.6992187503, 0.1210937501, 0.0117187500 }, + { 0.8710937504, 0.6289062503, 0.1445312501, 0.4570312502, 0.1992187501, 0.6210937503, 0.5117187502 }, + { 0.6210937503, 0.3789062502, 0.3945312502, 0.7070312503, 0.4492187502, 0.3710937502, 0.7617187504 }, + { 0.1210937501, 0.8789062504, 0.8945312504, 0.2070312501, 0.9492187504, 0.8710937504, 0.2617187501 }, + { 0.0898437500, 0.4101562502, 0.5507812503, 0.0507812500, 0.5429687503, 0.5898437503, 0.7304687503 }, + { 0.5898437503, 0.9101562504, 0.0507812500, 0.5507812503, 0.0429687500, 0.0898437500, 0.2304687501 }, + { 0.8398437504, 0.1601562501, 0.3007812501, 0.3007812501, 0.2929687501, 0.8398437504, 0.4804687502 }, + { 0.3398437502, 0.6601562503, 0.8007812504, 0.8007812504, 0.7929687504, 0.3398437502, 0.9804687505 }, + { 0.4648437502, 0.0351562500, 0.1757812501, 0.1757812501, 0.4179687502, 0.4648437502, 0.6054687503 }, + { 0.9648437504, 0.5351562502, 0.6757812503, 0.6757812503, 0.9179687504, 0.9648437504, 0.1054687500 }, + { 0.7148437503, 0.2851562501, 0.9257812504, 0.4257812502, 0.6679687503, 0.2148437501, 0.3554687502 }, + { 0.2148437501, 0.7851562504, 0.4257812502, 0.9257812504, 0.1679687501, 0.7148437503, 0.8554687504 }, + { 0.1523437501, 0.2226562501, 0.8632812504, 0.7382812503, 0.1054687500, 0.6523437503, 0.6679687503 }, + { 0.6523437503, 0.7226562503, 0.3632812502, 0.2382812501, 0.6054687503, 0.1523437501, 0.1679687501 }, + { 0.9023437504, 0.4726562502, 0.1132812501, 0.9882812505, 0.8554687504, 0.9023437504, 0.4179687502 }, + { 0.4023437502, 0.9726562505, 0.6132812503, 0.4882812502, 0.3554687502, 0.4023437502, 0.9179687504 }, + { 0.2773437501, 0.3476562502, 0.4882812502, 0.6132812503, 0.9804687505, 0.2773437501, 0.5429687503 }, + { 0.7773437504, 0.8476562504, 0.9882812505, 0.1132812501, 0.4804687502, 0.7773437504, 0.0429687500 }, + { 0.5273437502, 0.0976562500, 0.7382812503, 0.8632812504, 0.2304687501, 0.0273437500, 0.2929687501 }, + { 0.0273437500, 0.5976562503, 0.2382812501, 0.3632812502, 0.7304687503, 0.5273437502, 0.7929687504 }, + { 0.0195312500, 0.1992187501, 0.7304687503, 0.2460937501, 0.2539062501, 0.7070312503, 0.0664062500 }, + { 0.5195312502, 0.6992187503, 0.2304687501, 0.7460937503, 0.7539062504, 0.2070312501, 0.5664062503 }, + { 0.7695312504, 0.4492187502, 0.4804687502, 0.4960937502, 0.5039062502, 0.9570312504, 0.8164062504 }, + { 0.2695312501, 0.9492187504, 0.9804687505, 0.9960937505, 0.0039062500, 0.4570312502, 0.3164062501 }, + { 0.3945312502, 0.3242187502, 0.1054687500, 0.1210937501, 0.6289062503, 0.3320312502, 0.1914062501 }, + { 0.8945312504, 0.8242187504, 0.6054687503, 0.6210937503, 0.1289062501, 0.8320312504, 0.6914062503 }, + { 0.6445312503, 0.0742187500, 0.8554687504, 0.3710937502, 0.3789062502, 0.0820312500, 0.9414062504 }, + { 0.1445312501, 0.5742187503, 0.3554687502, 0.8710937504, 0.8789062504, 0.5820312503, 0.4414062502 }, + { 0.2070312501, 0.3867187502, 0.9179687504, 0.5585937503, 0.8164062504, 0.5195312502, 0.0039062500 }, + { 0.7070312503, 0.8867187504, 0.4179687502, 0.0585937500, 0.3164062501, 0.0195312500, 0.5039062502 }, + { 0.9570312504, 0.1367187501, 0.1679687501, 0.8085937504, 0.0664062500, 0.7695312504, 0.7539062504 }, + { 0.4570312502, 0.6367187503, 0.6679687503, 0.3085937501, 0.5664062503, 0.2695312501, 0.2539062501 }, + { 0.3320312502, 0.0117187500, 0.2929687501, 0.6835937503, 0.1914062501, 0.3945312502, 0.1289062501 }, + { 0.8320312504, 0.5117187502, 0.7929687504, 0.1835937501, 0.6914062503, 0.8945312504, 0.6289062503 }, + { 0.5820312503, 0.2617187501, 0.5429687503, 0.9335937504, 0.9414062504, 0.1445312501, 0.8789062504 }, + { 0.0820312500, 0.7617187504, 0.0429687500, 0.4335937502, 0.4414062502, 0.6445312503, 0.3789062502 }, + { 0.1132812501, 0.2929687501, 0.3867187502, 0.3398437502, 0.0351562500, 0.9257812504, 0.5976562503 }, + { 0.6132812503, 0.7929687504, 0.8867187504, 0.8398437504, 0.5351562502, 0.4257812502, 0.0976562500 }, + { 0.8632812504, 0.0429687500, 0.6367187503, 0.0898437500, 0.7851562504, 0.6757812503, 0.3476562502 }, + { 0.3632812502, 0.5429687503, 0.1367187501, 0.5898437503, 0.2851562501, 0.1757812501, 0.8476562504 }, + { 0.4882812502, 0.1679687501, 0.7617187504, 0.4648437502, 0.9101562504, 0.0507812500, 0.7226562503 }, + { 0.9882812505, 0.6679687503, 0.2617187501, 0.9648437504, 0.4101562502, 0.5507812503, 0.2226562501 }, + { 0.7382812503, 0.4179687502, 0.0117187500, 0.2148437501, 0.1601562501, 0.3007812501, 0.4726562502 }, + { 0.2382812501, 0.9179687504, 0.5117187502, 0.7148437503, 0.6601562503, 0.8007812504, 0.9726562505 }, + { 0.1757812501, 0.1054687500, 0.1992187501, 0.9023437504, 0.5976562503, 0.8632812504, 0.5351562502 }, + { 0.6757812503, 0.6054687503, 0.6992187503, 0.4023437502, 0.0976562500, 0.3632812502, 0.0351562500 }, + { 0.9257812504, 0.3554687502, 0.9492187504, 0.6523437503, 0.3476562502, 0.6132812503, 0.2851562501 }, + { 0.4257812502, 0.8554687504, 0.4492187502, 0.1523437501, 0.8476562504, 0.1132812501, 0.7851562504 }, + { 0.3007812501, 0.4804687502, 0.5742187503, 0.7773437504, 0.4726562502, 0.2382812501, 0.6601562503 }, + { 0.8007812504, 0.9804687505, 0.0742187500, 0.2773437501, 0.9726562505, 0.7382812503, 0.1601562501 }, + { 0.5507812503, 0.2304687501, 0.3242187502, 0.5273437502, 0.7226562503, 0.4882812502, 0.4101562502 }, + { 0.0507812500, 0.7304687503, 0.8242187504, 0.0273437500, 0.2226562501, 0.9882812505, 0.9101562504 }, + { 0.0351562500, 0.4648437502, 0.1523437501, 0.6679687503, 0.9570312504, 0.0664062500, 0.3320312502 }, + { 0.5351562502, 0.9648437504, 0.6523437503, 0.1679687501, 0.4570312502, 0.5664062503, 0.8320312504 }, + { 0.7851562504, 0.2148437501, 0.9023437504, 0.9179687504, 0.2070312501, 0.3164062501, 0.5820312503 }, + { 0.2851562501, 0.7148437503, 0.4023437502, 0.4179687502, 0.7070312503, 0.8164062504, 0.0820312500 } +}; + +// Spatial dimension: 16 +// N: 100 +// Vectors skipped: 128 +static const double sobol_16_100[100][16] = +{ + { 0.0117187500, 0.3320312502, 0.7851562504, 0.9414062504, 0.4648437502, 0.4179687502, 0.4648437502, 0.4882812502, 0.7304687503, 0.5742187503, 0.5664062503, 0.2460937501, 0.4882812502, 0.6367187503, 0.7617187504, 0.1835937501 }, + { 0.5117187502, 0.8320312504, 0.2851562501, 0.4414062502, 0.9648437504, 0.9179687504, 0.9648437504, 0.9882812505, 0.2304687501, 0.0742187500, 0.0664062500, 0.7460937503, 0.9882812505, 0.1367187501, 0.2617187501, 0.6835937503 }, + { 0.7617187504, 0.0820312500, 0.0351562500, 0.6914062503, 0.7148437503, 0.1679687501, 0.7148437503, 0.2382812501, 0.9804687505, 0.3242187502, 0.8164062504, 0.9960937505, 0.2382812501, 0.3867187502, 0.5117187502, 0.9335937504 }, + { 0.2617187501, 0.5820312503, 0.5351562502, 0.1914062501, 0.2148437501, 0.6679687503, 0.2148437501, 0.7382812503, 0.4804687502, 0.8242187504, 0.3164062501, 0.4960937502, 0.7382812503, 0.8867187504, 0.0117187500, 0.4335937502 }, + { 0.3867187502, 0.2070312501, 0.4101562502, 0.8164062504, 0.5898437503, 0.5429687503, 0.3398437502, 0.8632812504, 0.6054687503, 0.4492187502, 0.9414062504, 0.6210937503, 0.3632812502, 0.7617187504, 0.3867187502, 0.0585937500 }, + { 0.8867187504, 0.7070312503, 0.9101562504, 0.3164062501, 0.0898437500, 0.0429687500, 0.8398437504, 0.3632812502, 0.1054687500, 0.9492187504, 0.4414062502, 0.1210937501, 0.8632812504, 0.2617187501, 0.8867187504, 0.5585937503 }, + { 0.6367187503, 0.4570312502, 0.6601562503, 0.5664062503, 0.3398437502, 0.7929687504, 0.5898437503, 0.6132812503, 0.8554687504, 0.6992187503, 0.6914062503, 0.3710937502, 0.1132812501, 0.0117187500, 0.1367187501, 0.8085937504 }, + { 0.1367187501, 0.9570312504, 0.1601562501, 0.0664062500, 0.8398437504, 0.2929687501, 0.0898437500, 0.1132812501, 0.3554687502, 0.1992187501, 0.1914062501, 0.8710937504, 0.6132812503, 0.5117187502, 0.6367187503, 0.3085937501 }, + { 0.1992187501, 0.0195312500, 0.5976562503, 0.2539062501, 0.9023437504, 0.3554687502, 0.4023437502, 0.5507812503, 0.5429687503, 0.5117187502, 0.1289062501, 0.9335937504, 0.9257812504, 0.0742187500, 0.9492187504, 0.6210937503 }, + { 0.6992187503, 0.5195312502, 0.0976562500, 0.7539062504, 0.4023437502, 0.8554687504, 0.9023437504, 0.0507812500, 0.0429687500, 0.0117187500, 0.6289062503, 0.4335937502, 0.4257812502, 0.5742187503, 0.4492187502, 0.1210937501 }, + { 0.9492187504, 0.2695312501, 0.3476562502, 0.0039062500, 0.1523437501, 0.1054687500, 0.6523437503, 0.8007812504, 0.7929687504, 0.2617187501, 0.3789062502, 0.1835937501, 0.6757812503, 0.8242187504, 0.6992187503, 0.3710937502 }, + { 0.4492187502, 0.7695312504, 0.8476562504, 0.5039062502, 0.6523437503, 0.6054687503, 0.1523437501, 0.3007812501, 0.2929687501, 0.7617187504, 0.8789062504, 0.6835937503, 0.1757812501, 0.3242187502, 0.1992187501, 0.8710937504 }, + { 0.3242187502, 0.3945312502, 0.2226562501, 0.3789062502, 0.0273437500, 0.7304687503, 0.2773437501, 0.1757812501, 0.6679687503, 0.3867187502, 0.2539062501, 0.3085937501, 0.8007812504, 0.4492187502, 0.3242187502, 0.7460937503 }, + { 0.8242187504, 0.8945312504, 0.7226562503, 0.8789062504, 0.5273437502, 0.2304687501, 0.7773437504, 0.6757812503, 0.1679687501, 0.8867187504, 0.7539062504, 0.8085937504, 0.3007812501, 0.9492187504, 0.8242187504, 0.2460937501 }, + { 0.5742187503, 0.1445312501, 0.9726562505, 0.1289062501, 0.7773437504, 0.9804687505, 0.5273437502, 0.4257812502, 0.9179687504, 0.6367187503, 0.0039062500, 0.5585937503, 0.5507812503, 0.6992187503, 0.0742187500, 0.4960937502 }, + { 0.0742187500, 0.6445312503, 0.4726562502, 0.6289062503, 0.2773437501, 0.4804687502, 0.0273437500, 0.9257812504, 0.4179687502, 0.1367187501, 0.5039062502, 0.0585937500, 0.0507812500, 0.1992187501, 0.5742187503, 0.9960937505 }, + { 0.1054687500, 0.1757812501, 0.0664062500, 0.5976562503, 0.2460937501, 0.1992187501, 0.9960937505, 0.6445312503, 0.4492187502, 0.9804687505, 0.9726562505, 0.9023437504, 0.6445312503, 0.5429687503, 0.0429687500, 0.6523437503 }, + { 0.6054687503, 0.6757812503, 0.5664062503, 0.0976562500, 0.7460937503, 0.6992187503, 0.4960937502, 0.1445312501, 0.9492187504, 0.4804687502, 0.4726562502, 0.4023437502, 0.1445312501, 0.0429687500, 0.5429687503, 0.1523437501 }, + { 0.8554687504, 0.4257812502, 0.8164062504, 0.8476562504, 0.9960937505, 0.4492187502, 0.2460937501, 0.8945312504, 0.1992187501, 0.2304687501, 0.7226562503, 0.1523437501, 0.8945312504, 0.2929687501, 0.2929687501, 0.4023437502 }, + { 0.3554687502, 0.9257812504, 0.3164062501, 0.3476562502, 0.4960937502, 0.9492187504, 0.7460937503, 0.3945312502, 0.6992187503, 0.7304687503, 0.2226562501, 0.6523437503, 0.3945312502, 0.7929687504, 0.7929687504, 0.9023437504 }, + { 0.4804687502, 0.3007812501, 0.6914062503, 0.7226562503, 0.8710937504, 0.8242187504, 0.8710937504, 0.0195312500, 0.3242187502, 0.1054687500, 0.5976562503, 0.2773437501, 0.5195312502, 0.9179687504, 0.6679687503, 0.5273437502 }, + { 0.9804687505, 0.8007812504, 0.1914062501, 0.2226562501, 0.3710937502, 0.3242187502, 0.3710937502, 0.5195312502, 0.8242187504, 0.6054687503, 0.0976562500, 0.7773437504, 0.0195312500, 0.4179687502, 0.1679687501, 0.0273437500 }, + { 0.7304687503, 0.0507812500, 0.4414062502, 0.9726562505, 0.1210937501, 0.5742187503, 0.1210937501, 0.2695312501, 0.0742187500, 0.8554687504, 0.8476562504, 0.5273437502, 0.7695312504, 0.1679687501, 0.9179687504, 0.2773437501 }, + { 0.2304687501, 0.5507812503, 0.9414062504, 0.4726562502, 0.6210937503, 0.0742187500, 0.6210937503, 0.7695312504, 0.5742187503, 0.3554687502, 0.3476562502, 0.0273437500, 0.2695312501, 0.6679687503, 0.4179687502, 0.7773437504 }, + { 0.1679687501, 0.4882812502, 0.2539062501, 0.1601562501, 0.6835937503, 0.0117187500, 0.9335937504, 0.3320312502, 0.2617187501, 0.9179687504, 0.2851562501, 0.2148437501, 0.2070312501, 0.2304687501, 0.2304687501, 0.0898437500 }, + { 0.6679687503, 0.9882812505, 0.7539062504, 0.6601562503, 0.1835937501, 0.5117187502, 0.4335937502, 0.8320312504, 0.7617187504, 0.4179687502, 0.7851562504, 0.7148437503, 0.7070312503, 0.7304687503, 0.7304687503, 0.5898437503 }, + { 0.9179687504, 0.2382812501, 0.5039062502, 0.4101562502, 0.4335937502, 0.2617187501, 0.1835937501, 0.0820312500, 0.0117187500, 0.1679687501, 0.0351562500, 0.9648437504, 0.4570312502, 0.9804687505, 0.4804687502, 0.8398437504 }, + { 0.4179687502, 0.7382812503, 0.0039062500, 0.9101562504, 0.9335937504, 0.7617187504, 0.6835937503, 0.5820312503, 0.5117187502, 0.6679687503, 0.5351562502, 0.4648437502, 0.9570312504, 0.4804687502, 0.9804687505, 0.3398437502 }, + { 0.2929687501, 0.1132812501, 0.8789062504, 0.0351562500, 0.3085937501, 0.8867187504, 0.8085937504, 0.9570312504, 0.3867187502, 0.0429687500, 0.1601562501, 0.5898437503, 0.0820312500, 0.3554687502, 0.6054687503, 0.2148437501 }, + { 0.7929687504, 0.6132812503, 0.3789062502, 0.5351562502, 0.8085937504, 0.3867187502, 0.3085937501, 0.4570312502, 0.8867187504, 0.5429687503, 0.6601562503, 0.0898437500, 0.5820312503, 0.8554687504, 0.1054687500, 0.7148437503 }, + { 0.5429687503, 0.3632812502, 0.1289062501, 0.2851562501, 0.5585937503, 0.6367187503, 0.0585937500, 0.7070312503, 0.1367187501, 0.7929687504, 0.4101562502, 0.3398437502, 0.3320312502, 0.6054687503, 0.8554687504, 0.9648437504 }, + { 0.0429687500, 0.8632812504, 0.6289062503, 0.7851562504, 0.0585937500, 0.1367187501, 0.5585937503, 0.2070312501, 0.6367187503, 0.2929687501, 0.9101562504, 0.8398437504, 0.8320312504, 0.1054687500, 0.3554687502, 0.4648437502 }, + { 0.0585937500, 0.0664062500, 0.3320312502, 0.3945312502, 0.7617187504, 0.8085937504, 0.1992187501, 0.8164062504, 0.1835937501, 0.6210937503, 0.6445312503, 0.1054687500, 0.1289062501, 0.5585937503, 0.8710937504, 0.4179687502 }, + { 0.5585937503, 0.5664062503, 0.8320312504, 0.8945312504, 0.2617187501, 0.3085937501, 0.6992187503, 0.3164062501, 0.6835937503, 0.1210937501, 0.1445312501, 0.6054687503, 0.6289062503, 0.0585937500, 0.3710937502, 0.9179687504 }, + { 0.8085937504, 0.3164062501, 0.5820312503, 0.1445312501, 0.0117187500, 0.5585937503, 0.9492187504, 0.5664062503, 0.4335937502, 0.3710937502, 0.8945312504, 0.8554687504, 0.3789062502, 0.3085937501, 0.6210937503, 0.6679687503 }, + { 0.3085937501, 0.8164062504, 0.0820312500, 0.6445312503, 0.5117187502, 0.0585937500, 0.4492187502, 0.0664062500, 0.9335937504, 0.8710937504, 0.3945312502, 0.3554687502, 0.8789062504, 0.8085937504, 0.1210937501, 0.1679687501 }, + { 0.4335937502, 0.4414062502, 0.9570312504, 0.2695312501, 0.1367187501, 0.1835937501, 0.0742187500, 0.4414062502, 0.0585937500, 0.4960937502, 0.7695312504, 0.7304687503, 0.0039062500, 0.9335937504, 0.4960937502, 0.2929687501 }, + { 0.9335937504, 0.9414062504, 0.4570312502, 0.7695312504, 0.6367187503, 0.6835937503, 0.5742187503, 0.9414062504, 0.5585937503, 0.9960937505, 0.2695312501, 0.2304687501, 0.5039062502, 0.4335937502, 0.9960937505, 0.7929687504 }, + { 0.6835937503, 0.1914062501, 0.2070312501, 0.0195312500, 0.8867187504, 0.4335937502, 0.8242187504, 0.1914062501, 0.3085937501, 0.7460937503, 0.5195312502, 0.4804687502, 0.2539062501, 0.1835937501, 0.2460937501, 0.5429687503 }, + { 0.1835937501, 0.6914062503, 0.7070312503, 0.5195312502, 0.3867187502, 0.9335937504, 0.3242187502, 0.6914062503, 0.8085937504, 0.2460937501, 0.0195312500, 0.9804687505, 0.7539062504, 0.6835937503, 0.7460937503, 0.0429687500 }, + { 0.2460937501, 0.2539062501, 0.0195312500, 0.8320312504, 0.3242187502, 0.9960937505, 0.1367187501, 0.1289062501, 0.1210937501, 0.5585937503, 0.0820312500, 0.7929687504, 0.6914062503, 0.2460937501, 0.9335937504, 0.8554687504 }, + { 0.7460937503, 0.7539062504, 0.5195312502, 0.3320312502, 0.8242187504, 0.4960937502, 0.6367187503, 0.6289062503, 0.6210937503, 0.0585937500, 0.5820312503, 0.2929687501, 0.1914062501, 0.7460937503, 0.4335937502, 0.3554687502 }, + { 0.9960937505, 0.0039062500, 0.7695312504, 0.5820312503, 0.5742187503, 0.7460937503, 0.8867187504, 0.3789062502, 0.3710937502, 0.3085937501, 0.3320312502, 0.0429687500, 0.9414062504, 0.9960937505, 0.6835937503, 0.1054687500 }, + { 0.4960937502, 0.5039062502, 0.2695312501, 0.0820312500, 0.0742187500, 0.2460937501, 0.3867187502, 0.8789062504, 0.8710937504, 0.8085937504, 0.8320312504, 0.5429687503, 0.4414062502, 0.4960937502, 0.1835937501, 0.6054687503 }, + { 0.3710937502, 0.1289062501, 0.6445312503, 0.9570312504, 0.6992187503, 0.1210937501, 0.0117187500, 0.5039062502, 0.2460937501, 0.4335937502, 0.4570312502, 0.4179687502, 0.5664062503, 0.3710937502, 0.3085937501, 0.9804687505 }, + { 0.8710937504, 0.6289062503, 0.1445312501, 0.4570312502, 0.1992187501, 0.6210937503, 0.5117187502, 0.0039062500, 0.7460937503, 0.9335937504, 0.9570312504, 0.9179687504, 0.0664062500, 0.8710937504, 0.8085937504, 0.4804687502 }, + { 0.6210937503, 0.3789062502, 0.3945312502, 0.7070312503, 0.4492187502, 0.3710937502, 0.7617187504, 0.7539062504, 0.4960937502, 0.6835937503, 0.2070312501, 0.6679687503, 0.8164062504, 0.6210937503, 0.0585937500, 0.2304687501 }, + { 0.1210937501, 0.8789062504, 0.8945312504, 0.2070312501, 0.9492187504, 0.8710937504, 0.2617187501, 0.2539062501, 0.9960937505, 0.1835937501, 0.7070312503, 0.1679687501, 0.3164062501, 0.1210937501, 0.5585937503, 0.7304687503 }, + { 0.0898437500, 0.4101562502, 0.5507812503, 0.0507812500, 0.5429687503, 0.5898437503, 0.7304687503, 0.0351562500, 0.9023437504, 0.9648437504, 0.8007812504, 0.7617187504, 0.9726562505, 0.6523437503, 0.0898437500, 0.8867187504 }, + { 0.5898437503, 0.9101562504, 0.0507812500, 0.5507812503, 0.0429687500, 0.0898437500, 0.2304687501, 0.5351562502, 0.4023437502, 0.4648437502, 0.3007812501, 0.2617187501, 0.4726562502, 0.1523437501, 0.5898437503, 0.3867187502 }, + { 0.8398437504, 0.1601562501, 0.3007812501, 0.3007812501, 0.2929687501, 0.8398437504, 0.4804687502, 0.2851562501, 0.6523437503, 0.2148437501, 0.5507812503, 0.0117187500, 0.7226562503, 0.4023437502, 0.3398437502, 0.1367187501 }, + { 0.3398437502, 0.6601562503, 0.8007812504, 0.8007812504, 0.7929687504, 0.3398437502, 0.9804687505, 0.7851562504, 0.1523437501, 0.7148437503, 0.0507812500, 0.5117187502, 0.2226562501, 0.9023437504, 0.8398437504, 0.6367187503 }, + { 0.4648437502, 0.0351562500, 0.1757812501, 0.1757812501, 0.4179687502, 0.4648437502, 0.6054687503, 0.6601562503, 0.7773437504, 0.0898437500, 0.6757812503, 0.3867187502, 0.8476562504, 0.7773437504, 0.7148437503, 0.7617187504 }, + { 0.9648437504, 0.5351562502, 0.6757812503, 0.6757812503, 0.9179687504, 0.9648437504, 0.1054687500, 0.1601562501, 0.2773437501, 0.5898437503, 0.1757812501, 0.8867187504, 0.3476562502, 0.2773437501, 0.2148437501, 0.2617187501 }, + { 0.7148437503, 0.2851562501, 0.9257812504, 0.4257812502, 0.6679687503, 0.2148437501, 0.3554687502, 0.9101562504, 0.5273437502, 0.8398437504, 0.9257812504, 0.6367187503, 0.5976562503, 0.0273437500, 0.9648437504, 0.0117187500 }, + { 0.2148437501, 0.7851562504, 0.4257812502, 0.9257812504, 0.1679687501, 0.7148437503, 0.8554687504, 0.4101562502, 0.0273437500, 0.3398437502, 0.4257812502, 0.1367187501, 0.0976562500, 0.5273437502, 0.4648437502, 0.5117187502 }, + { 0.1523437501, 0.2226562501, 0.8632812504, 0.7382812503, 0.1054687500, 0.6523437503, 0.6679687503, 0.9726562505, 0.8398437504, 0.9023437504, 0.4882812502, 0.0742187500, 0.4101562502, 0.0898437500, 0.1523437501, 0.3242187502 }, + { 0.6523437503, 0.7226562503, 0.3632812502, 0.2382812501, 0.6054687503, 0.1523437501, 0.1679687501, 0.4726562502, 0.3398437502, 0.4023437502, 0.9882812505, 0.5742187503, 0.9101562504, 0.5898437503, 0.6523437503, 0.8242187504 }, + { 0.9023437504, 0.4726562502, 0.1132812501, 0.9882812505, 0.8554687504, 0.9023437504, 0.4179687502, 0.7226562503, 0.5898437503, 0.1523437501, 0.2382812501, 0.8242187504, 0.1601562501, 0.8398437504, 0.4023437502, 0.5742187503 }, + { 0.4023437502, 0.9726562505, 0.6132812503, 0.4882812502, 0.3554687502, 0.4023437502, 0.9179687504, 0.2226562501, 0.0898437500, 0.6523437503, 0.7382812503, 0.3242187502, 0.6601562503, 0.3398437502, 0.9023437504, 0.0742187500 }, + { 0.2773437501, 0.3476562502, 0.4882812502, 0.6132812503, 0.9804687505, 0.2773437501, 0.5429687503, 0.3476562502, 0.9648437504, 0.0273437500, 0.1132812501, 0.6992187503, 0.2851562501, 0.4648437502, 0.5273437502, 0.4492187502 }, + { 0.7773437504, 0.8476562504, 0.9882812505, 0.1132812501, 0.4804687502, 0.7773437504, 0.0429687500, 0.8476562504, 0.4648437502, 0.5273437502, 0.6132812503, 0.1992187501, 0.7851562504, 0.9648437504, 0.0273437500, 0.9492187504 }, + { 0.5273437502, 0.0976562500, 0.7382812503, 0.8632812504, 0.2304687501, 0.0273437500, 0.2929687501, 0.0976562500, 0.7148437503, 0.7773437504, 0.3632812502, 0.4492187502, 0.0351562500, 0.7148437503, 0.7773437504, 0.6992187503 }, + { 0.0273437500, 0.5976562503, 0.2382812501, 0.3632812502, 0.7304687503, 0.5273437502, 0.7929687504, 0.5976562503, 0.2148437501, 0.2773437501, 0.8632812504, 0.9492187504, 0.5351562502, 0.2148437501, 0.2773437501, 0.1992187501 }, + { 0.0195312500, 0.1992187501, 0.7304687503, 0.2460937501, 0.2539062501, 0.7070312503, 0.0664062500, 0.8085937504, 0.5195312502, 0.8007812504, 0.2460937501, 0.6757812503, 0.9023437504, 0.9570312504, 0.2539062501, 0.4726562502 }, + { 0.5195312502, 0.6992187503, 0.2304687501, 0.7460937503, 0.7539062504, 0.2070312501, 0.5664062503, 0.3085937501, 0.0195312500, 0.3007812501, 0.7460937503, 0.1757812501, 0.4023437502, 0.4570312502, 0.7539062504, 0.9726562505 }, + { 0.7695312504, 0.4492187502, 0.4804687502, 0.4960937502, 0.5039062502, 0.9570312504, 0.8164062504, 0.5585937503, 0.7695312504, 0.0507812500, 0.4960937502, 0.4257812502, 0.6523437503, 0.2070312501, 0.0039062500, 0.7226562503 }, + { 0.2695312501, 0.9492187504, 0.9804687505, 0.9960937505, 0.0039062500, 0.4570312502, 0.3164062501, 0.0585937500, 0.2695312501, 0.5507812503, 0.9960937505, 0.9257812504, 0.1523437501, 0.7070312503, 0.5039062502, 0.2226562501 }, + { 0.3945312502, 0.3242187502, 0.1054687500, 0.1210937501, 0.6289062503, 0.3320312502, 0.1914062501, 0.4335937502, 0.6445312503, 0.1757812501, 0.3710937502, 0.0507812500, 0.7773437504, 0.5820312503, 0.8789062504, 0.3476562502 }, + { 0.8945312504, 0.8242187504, 0.6054687503, 0.6210937503, 0.1289062501, 0.8320312504, 0.6914062503, 0.9335937504, 0.1445312501, 0.6757812503, 0.8710937504, 0.5507812503, 0.2773437501, 0.0820312500, 0.3789062502, 0.8476562504 }, + { 0.6445312503, 0.0742187500, 0.8554687504, 0.3710937502, 0.3789062502, 0.0820312500, 0.9414062504, 0.1835937501, 0.8945312504, 0.9257812504, 0.1210937501, 0.8007812504, 0.5273437502, 0.3320312502, 0.6289062503, 0.5976562503 }, + { 0.1445312501, 0.5742187503, 0.3554687502, 0.8710937504, 0.8789062504, 0.5820312503, 0.4414062502, 0.6835937503, 0.3945312502, 0.4257812502, 0.6210937503, 0.3007812501, 0.0273437500, 0.8320312504, 0.1289062501, 0.0976562500 }, + { 0.2070312501, 0.3867187502, 0.9179687504, 0.5585937503, 0.8164062504, 0.5195312502, 0.0039062500, 0.2460937501, 0.7070312503, 0.8632812504, 0.5585937503, 0.4882812502, 0.4648437502, 0.2695312501, 0.4414062502, 0.7851562504 }, + { 0.7070312503, 0.8867187504, 0.4179687502, 0.0585937500, 0.3164062501, 0.0195312500, 0.5039062502, 0.7460937503, 0.2070312501, 0.3632812502, 0.0585937500, 0.9882812505, 0.9648437504, 0.7695312504, 0.9414062504, 0.2851562501 }, + { 0.9570312504, 0.1367187501, 0.1679687501, 0.8085937504, 0.0664062500, 0.7695312504, 0.7539062504, 0.4960937502, 0.9570312504, 0.1132812501, 0.8085937504, 0.7382812503, 0.2148437501, 0.5195312502, 0.1914062501, 0.0351562500 }, + { 0.4570312502, 0.6367187503, 0.6679687503, 0.3085937501, 0.5664062503, 0.2695312501, 0.2539062501, 0.9960937505, 0.4570312502, 0.6132812503, 0.3085937501, 0.2382812501, 0.7148437503, 0.0195312500, 0.6914062503, 0.5351562502 }, + { 0.3320312502, 0.0117187500, 0.2929687501, 0.6835937503, 0.1914062501, 0.3945312502, 0.1289062501, 0.6210937503, 0.5820312503, 0.2382812501, 0.9335937504, 0.8632812504, 0.3398437502, 0.1445312501, 0.8164062504, 0.9101562504 }, + { 0.8320312504, 0.5117187502, 0.7929687504, 0.1835937501, 0.6914062503, 0.8945312504, 0.6289062503, 0.1210937501, 0.0820312500, 0.7382812503, 0.4335937502, 0.3632812502, 0.8398437504, 0.6445312503, 0.3164062501, 0.4101562502 }, + { 0.5820312503, 0.2617187501, 0.5429687503, 0.9335937504, 0.9414062504, 0.1445312501, 0.8789062504, 0.8710937504, 0.8320312504, 0.9882812505, 0.6835937503, 0.1132812501, 0.0898437500, 0.8945312504, 0.5664062503, 0.1601562501 }, + { 0.0820312500, 0.7617187504, 0.0429687500, 0.4335937502, 0.4414062502, 0.6445312503, 0.3789062502, 0.3710937502, 0.3320312502, 0.4882812502, 0.1835937501, 0.6132812503, 0.5898437503, 0.3945312502, 0.0664062500, 0.6601562503 }, + { 0.1132812501, 0.2929687501, 0.3867187502, 0.3398437502, 0.0351562500, 0.9257812504, 0.5976562503, 0.0898437500, 0.3007812501, 0.6445312503, 0.3398437502, 0.4570312502, 0.2460937501, 0.8632812504, 0.5351562502, 0.9414062504 }, + { 0.6132812503, 0.7929687504, 0.8867187504, 0.8398437504, 0.5351562502, 0.4257812502, 0.0976562500, 0.5898437503, 0.8007812504, 0.1445312501, 0.8398437504, 0.9570312504, 0.7460937503, 0.3632812502, 0.0351562500, 0.4414062502 }, + { 0.8632812504, 0.0429687500, 0.6367187503, 0.0898437500, 0.7851562504, 0.6757812503, 0.3476562502, 0.3398437502, 0.0507812500, 0.3945312502, 0.0898437500, 0.7070312503, 0.4960937502, 0.1132812501, 0.7851562504, 0.1914062501 }, + { 0.3632812502, 0.5429687503, 0.1367187501, 0.5898437503, 0.2851562501, 0.1757812501, 0.8476562504, 0.8398437504, 0.5507812503, 0.8945312504, 0.5898437503, 0.2070312501, 0.9960937505, 0.6132812503, 0.2851562501, 0.6914062503 }, + { 0.4882812502, 0.1679687501, 0.7617187504, 0.4648437502, 0.9101562504, 0.0507812500, 0.7226562503, 0.7148437503, 0.4257812502, 0.2695312501, 0.2148437501, 0.8320312504, 0.1210937501, 0.7382812503, 0.1601562501, 0.8164062504 }, + { 0.9882812505, 0.6679687503, 0.2617187501, 0.9648437504, 0.4101562502, 0.5507812503, 0.2226562501, 0.2148437501, 0.9257812504, 0.7695312504, 0.7148437503, 0.3320312502, 0.6210937503, 0.2382812501, 0.6601562503, 0.3164062501 }, + { 0.7382812503, 0.4179687502, 0.0117187500, 0.2148437501, 0.1601562501, 0.3007812501, 0.4726562502, 0.9648437504, 0.1757812501, 0.5195312502, 0.4648437502, 0.0820312500, 0.3710937502, 0.4882812502, 0.4101562502, 0.0664062500 }, + { 0.2382812501, 0.9179687504, 0.5117187502, 0.7148437503, 0.6601562503, 0.8007812504, 0.9726562505, 0.4648437502, 0.6757812503, 0.0195312500, 0.9648437504, 0.5820312503, 0.8710937504, 0.9882812505, 0.9101562504, 0.5664062503 }, + { 0.1757812501, 0.1054687500, 0.1992187501, 0.9023437504, 0.5976562503, 0.8632812504, 0.5351562502, 0.9023437504, 0.4882812502, 0.7070312503, 0.9023437504, 0.6445312503, 0.6835937503, 0.4257812502, 0.7226562503, 0.2539062501 }, + { 0.6757812503, 0.6054687503, 0.6992187503, 0.4023437502, 0.0976562500, 0.3632812502, 0.0351562500, 0.4023437502, 0.9882812505, 0.2070312501, 0.4023437502, 0.1445312501, 0.1835937501, 0.9257812504, 0.2226562501, 0.7539062504 }, + { 0.9257812504, 0.3554687502, 0.9492187504, 0.6523437503, 0.3476562502, 0.6132812503, 0.2851562501, 0.6523437503, 0.2382812501, 0.4570312502, 0.6523437503, 0.3945312502, 0.9335937504, 0.6757812503, 0.9726562505, 0.5039062502 }, + { 0.4257812502, 0.8554687504, 0.4492187502, 0.1523437501, 0.8476562504, 0.1132812501, 0.7851562504, 0.1523437501, 0.7382812503, 0.9570312504, 0.1523437501, 0.8945312504, 0.4335937502, 0.1757812501, 0.4726562502, 0.0039062500 }, + { 0.3007812501, 0.4804687502, 0.5742187503, 0.7773437504, 0.4726562502, 0.2382812501, 0.6601562503, 0.2773437501, 0.3632812502, 0.3320312502, 0.5273437502, 0.0195312500, 0.5585937503, 0.0507812500, 0.0976562500, 0.3789062502 }, + { 0.8007812504, 0.9804687505, 0.0742187500, 0.2773437501, 0.9726562505, 0.7382812503, 0.1601562501, 0.7773437504, 0.8632812504, 0.8320312504, 0.0273437500, 0.5195312502, 0.0585937500, 0.5507812503, 0.5976562503, 0.8789062504 }, + { 0.5507812503, 0.2304687501, 0.3242187502, 0.5273437502, 0.7226562503, 0.4882812502, 0.4101562502, 0.0273437500, 0.1132812501, 0.5820312503, 0.7773437504, 0.7695312504, 0.8085937504, 0.8007812504, 0.3476562502, 0.6289062503 }, + { 0.0507812500, 0.7304687503, 0.8242187504, 0.0273437500, 0.2226562501, 0.9882812505, 0.9101562504, 0.5273437502, 0.6132812503, 0.0820312500, 0.2773437501, 0.2695312501, 0.3085937501, 0.3007812501, 0.8476562504, 0.1289062501 }, + { 0.0351562500, 0.4648437502, 0.1523437501, 0.6679687503, 0.9570312504, 0.0664062500, 0.3320312502, 0.3867187502, 0.0664062500, 0.7539062504, 0.0429687500, 0.5351562502, 0.7304687503, 0.8476562504, 0.3632812502, 0.2382812501 }, + { 0.5351562502, 0.9648437504, 0.6523437503, 0.1679687501, 0.4570312502, 0.5664062503, 0.8320312504, 0.8867187504, 0.5664062503, 0.2539062501, 0.5429687503, 0.0351562500, 0.2304687501, 0.3476562502, 0.8632812504, 0.7382812503 }, + { 0.7851562504, 0.2148437501, 0.9023437504, 0.9179687504, 0.2070312501, 0.3164062501, 0.5820312503, 0.1367187501, 0.3164062501, 0.0039062500, 0.2929687501, 0.2851562501, 0.9804687505, 0.0976562500, 0.1132812501, 0.9882812505 }, + { 0.2851562501, 0.7148437503, 0.4023437502, 0.4179687502, 0.7070312503, 0.8164062504, 0.0820312500, 0.6367187503, 0.8164062504, 0.5039062502, 0.7929687504, 0.7851562504, 0.4804687502, 0.5976562503, 0.6132812503, 0.4882812502 } +}; + + +QRNG_VALIDATION_TEST_FUNCTIONS(sobol) + +BOOST_AUTO_TEST_CASE( validate_sobol ) +{ + test_sobol_values(sobol_02_100, 0); + test_sobol_values(sobol_07_100, 128); + test_sobol_values(sobol_16_100, 128); +} + +BOOST_AUTO_TEST_CASE( validate_sobol_seed ) +{ + test_sobol_seed(sobol_02_100, 0); + test_sobol_seed(sobol_07_100, 128); + test_sobol_seed(sobol_16_100, 128); +} + +BOOST_AUTO_TEST_CASE( validate_sobol_discard ) +{ + test_sobol_discard(sobol_02_100, 0); + test_sobol_discard(sobol_07_100, 128); + test_sobol_discard(sobol_16_100, 128); +} From 9786f4f4815712472187b25f79c1c76af7c89312 Mon Sep 17 00:00:00 2001 From: "Justinas V. Daugmaudis" Date: Sun, 4 Mar 2018 00:02:49 +0200 Subject: [PATCH 2/8] Aggregated review fixes Check discard overflows Check comparison overflows Exception messages Add missing docs and fix typedef ugliness Better template param name --- doc/Jamfile.v2 | 10 +- doc/concepts.qbk | 62 +- .../boost/random/detail/gray_coded_qrng.hpp | 152 + .../random/detail/gray_coded_qrng_base.hpp | 103 - .../detail/niederreiter_base2_table.hpp | 513 ++ include/boost/random/detail/qrng_base.hpp | 181 +- include/boost/random/detail/sobol_table.hpp | 4106 +++++++++++++++++ include/boost/random/faure.hpp | 252 +- include/boost/random/niederreiter_base2.hpp | 377 +- include/boost/random/sobol.hpp | 1129 +---- ...de.cpp => niederreiter_base2_validate.cpp} | 33 +- test/sobol_validate.cpp | 449 +- test/test_qrng_functions.hpp | 282 ++ 13 files changed, 5874 insertions(+), 1775 deletions(-) create mode 100644 include/boost/random/detail/gray_coded_qrng.hpp delete mode 100644 include/boost/random/detail/gray_coded_qrng_base.hpp create mode 100644 include/boost/random/detail/niederreiter_base2_table.hpp create mode 100644 include/boost/random/detail/sobol_table.hpp rename test/{niederreiter_base2_validade.cpp => niederreiter_base2_validate.cpp} (97%) create mode 100644 test/test_qrng_functions.hpp diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 20b4de1..1f75252 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -42,8 +42,8 @@ doxygen_files = lognormal_distribution mersenne_twister negative_binomial_distribution - non_central_chi_squared_distribution niederreiter_base2 + non_central_chi_squared_distribution normal_distribution piecewise_constant_distribution piecewise_linear_distribution @@ -96,6 +96,7 @@ doxygen reference : boost=\"$(BOOST_ROOT)\" \\ random_distribution=\"@xmlonly random distribution @endxmlonly\" \\ pseudo_random_number_generator=\"@xmlonly pseudo-random number generator @endxmlonly\" \\ + quasi_random_number_generator=\"@xmlonly quasi-random number generator @endxmlonly\" \\ uniform_random_number_generator=\"@xmlonly uniform random number generator @endxmlonly\" \\ nondeterministic_random_number_generator=\"@xmlonly non-deterministic random number generator @endxmlonly\" \\ generators=\"@xmlonly generators @endxmlonly\" \\ @@ -110,9 +111,9 @@ doxygen reference : rand48=\"@xmlonly rand48 @endxmlonly\" \\ mt11213b=\"@xmlonly mt11213b @endxmlonly\" \\ mt19937=\"@xmlonly mt19937 @endxmlonly\" \\ - niederreiter_base2=\"@xmlonly niederreiter_base2 @endxmlonly\" \\ - sobol=\"@xmlonly sobol @endxmlonly\" \\ - faure=\"@xmlonly faure @endxmlonly\" \\ + niederreiter_base2_engine=\"@xmlonly niederreiter_base2_engine @endxmlonly\" \\ + sobol_engine=\"@xmlonly sobol_engine @endxmlonly\" \\ + faure_engine=\"@xmlonly faure_engine @endxmlonly\" \\ ecuyer1988=\"@xmlonly ecuyer1988 @endxmlonly\" \\ lagged_fibonacci607=\"@xmlonly lagged_fibonacci607 @endxmlonly\" \\ lagged_fibonacci44497=\"@xmlonly lagged_fibonacci44497 @endxmlonly\" \\ @@ -133,6 +134,7 @@ doxygen reference : \"BOOST_PREVENT_MACRO_SUBSTITUTION=\" \\ \"BOOST_STATIC_ASSERT(x)=\" \\ \"BOOST_STATIC_CONSTANT(type,value)=static const type value\" \\ + \"BOOST_CONSTEXPR=constexpr\" \\ \"UINT64_C(value)=value ## ull\" \\ \"BOOST_RANDOM_DECL=\" \\ \"RealType(x)=x\" \\ diff --git a/doc/concepts.qbk b/doc/concepts.qbk index 84de047..306bf61 100644 --- a/doc/concepts.qbk +++ b/doc/concepts.qbk @@ -10,26 +10,26 @@ Random numbers are required in a number of different problem domains, such as -* numerics (simulation, Monte-Carlo integration) -* games (non-deterministic enemy behavior) -* security (key generation) -* testing (random coverage in white-box tests) +* numerics (simulation, Monte-Carlo integration) +* games (non-deterministic enemy behavior) +* security (key generation) +* testing (random coverage in white-box tests) The Boost Random Number Generator Library provides a framework for random number generators with well-defined properties so that the generators can be used in the demanding numerics and security domains. For a general -introduction to random numbers in numerics, see +introduction to random numbers in numerics, see [:"Numerical Recipes in C: The art of scientific computing", William H. Press, Saul A. Teukolsky, William A. Vetterling, Brian P. Flannery, 2nd ed., 1992, pp. 274-328] - -Depending on the requirements of the problem domain, different variations of -random number generators are appropriate: -* non-deterministic random number generator -* pseudo-random number generator -* quasi-random number generator +Depending on the requirements of the problem domain, different variations of +random number generators are appropriate: + +* non-deterministic random number generator +* pseudo-random number generator +* quasi-random number generator All variations have some properties in common, the concepts (in the STL sense) is called __UniformRandomNumberGenerator. This @@ -38,8 +38,8 @@ concept will be defined in a subsequent section. The goals for this library are the following: * allow easy integration of third-party random-number generators -* provide easy-to-use front-end classes which model popular distributions -* provide maximum efficiency +* provide easy-to-use front-end classes which model popular distributions +* provide maximum efficiency [endsect] @@ -203,40 +203,46 @@ the generator, for example to re-run a test suite at a later time.] A quasi-random number generator is a __UniformRandomNumberGenerator which provides a deterministic sequence of quasi-random numbers, based on some -algorithm and internal state. [classref boost::random::niederreiter_base2 -Niederreiter Base 2] generator is an example of such a [qrng quasi-random +algorithm and internal state. [classref boost::random::niederreiter_base2_engine +Niederreiter base 2] generator is an example of such a [qrng quasi-random number generator]. The "quasi" modifier is used to denote more clearly that the values produced by such a generator are neither random nor pseudo-random, but -they form a low discrepancy sequence. The intuitive idea is that a low discrepancy +they form a low discrepancy sequence. The intuitive idea is that a low discrepancy sequence is more evenly distributed than a pseudo random sequence would be. For example, if we generate a low discrepancy sequence of 2D points on a square, this square would be covered more evenly, and the number of points falling to any part of the square would be proportional to the number of points in the whole square. -Such sequences share some properties of random variables and in certain applications -such as the quasi-Monte Carlo method their lower discrepancy is an important advantage. +Such sequences share some properties of random variables and in certain applications +such as the quasi-Monte Carlo method their lower discrepancy is an important advantage. -[note Quasi-random sequences are known to give efficient numerical integration -rules in many Bayesian statistical problems where the posterior distribution can be -transformed into periodic functions on the n-dimensional hypercube.] +[note Quasi-Monte Carlo method uses a low-discrepancy sequence such as the +Niederreiter base 2 sequence, the Sobol sequence, or the Faure sequence among the others. +The advantage of using low-discrepancy sequences is a probabilistically faster rate of +convergence. Quasi-Monte Carlo has a rate of convergence close to '''O(1/N)''', +whereas the rate of convergence for the Monte Carlo method, which uses a pseudo-random sequence, +is '''O(N-0.5)'''.] Harold Niederreiter gives an extensive overview on random number generation and quasi-Monte Carlo methods in his book "Random number generation and -quasi-Monte Carlo methods, Society for Industrial and Applied Mathematics, 1992". +quasi-Monte Carlo methods, Society for Industrial and Applied Mathematics, 1992". In addition to the __UniformRandomNumberGenerator requirements, a quasi-random number generator has some additional requirements. In the -following table, `X` denotes a quasi-random number generator class, and `v` is -a const value of `X`. +following table, `X` denotes a quasi-random number generator class, `u` is a value of `X`, +`v` is a const value of `X`, and `j` a value of type `unsigned long long`. [table QuasiRandomNumberGenerator requirements [[expression] [return type] [pre/post-condition]] - [[`X::dimension()`] [std::size_t] [the dimension of quasi-random domain. It must be no less than 1. - The return value of this function shall not change during the lifetime of the object.]] + [[`X(s)`] [-] [creates an `s`-dimensional generator with a default seed. Dimension `s` is an integer no less than 1.]] + [[`v.dimension()`] [std::size_t] [the dimension of quasi-random domain.]] + [[`u.seed(i)`] [`void`] [seeds the generator with the integer `i`.]] + [[`u.discard(j)`] [`void`] [Advances the generator by `j` steps as if by + `j` calls to `u()`.]] ] -[note The `operator()` returns a successive element of an n-dimensional (n = `X::dimension()`) vector +[note The `operator()` returns a successive element of an `s`-dimensional (`s` = `v.dimension()`) vector at each invocation. When all elements are exhausted, `operator()` begins anew with the starting -element of a subsequent n-dimensional vector.] +element of a subsequent `s`-dimensional vector.] Classes which model a quasi-random number generator shall also model __EqualityComparable, i.e. implement `operator==`. Two quasi-random number diff --git a/include/boost/random/detail/gray_coded_qrng.hpp b/include/boost/random/detail/gray_coded_qrng.hpp new file mode 100644 index 0000000..4c900fe --- /dev/null +++ b/include/boost/random/detail/gray_coded_qrng.hpp @@ -0,0 +1,152 @@ +/* boost random/detail/gray_coded_qrng.hpp header file + * + * Copyright Justinas Vygintas Daugmaudis 2010-2018 + * 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) + */ + +#ifndef BOOST_RANDOM_DETAIL_GRAY_CODED_QRNG_HPP +#define BOOST_RANDOM_DETAIL_GRAY_CODED_QRNG_HPP + +#include + +#include // lsb + +#include // bit_xor + +#include + +//!\file +//!Describes the gray-coded quasi-random number generator base class template. + +namespace boost { +namespace random { + +namespace detail { + +template +class gray_coded_qrng + : public qrng_base< + gray_coded_qrng + , LatticeT + , typename LatticeT::value_type + > +{ +public: + typedef typename LatticeT::value_type result_type; + typedef result_type size_type; + +private: + typedef gray_coded_qrng self_t; + typedef qrng_base base_t; + + // The base needs to access modifying member f-ns, and we + // don't want these functions to be available for the public use + friend class qrng_base; + + // Respect lattice bit_count here + struct do_nothing { + inline static void check(unsigned) {} + inline static void check_log2(size_type) {} + }; + struct check_bit_range { + inline static void check(unsigned bit_pos) { + if (bit_pos >= LatticeT::bit_count) + boost::throw_exception( std::range_error("gray_coded_qrng: bit_count") ); + } + inline static void check_log2(size_type code) { + check_bit_range::check(multiprecision::msb(code)); + } + }; + + // We only want to check whether bit pos is outside the range if given bit_count + // is narrower than the size_type, otherwise checks compile to nothing. + typedef typename mpl::if_c< + LatticeT::bit_count < std::numeric_limits::digits + , check_bit_range + , do_nothing + >::type bit_range_checker_t; + +public: + //!Returns: Tight lower bound on the set of values returned by operator(). + //! + //!Throws: nothing. + static BOOST_CONSTEXPR result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () + { return 0; } + + //!Returns: Tight upper bound on the set of values returned by operator(). + //! + //!Throws: nothing. + static BOOST_CONSTEXPR result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () + { return (std::numeric_limits::max)(); } + + explicit gray_coded_qrng(std::size_t dimension) + : base_t(dimension) + {} + + // default copy c-tor is fine + + // default assignment operator is fine + + void seed() + { + set_zero_state(); + update_quasi(0); + base_t::reset_seq(0); + } + + void seed(const size_type init) + { + if (init != this->curr_seq()) + { + size_type seq_code = boost::next(init); + if (BOOST_UNLIKELY(!(init < seq_code))) + boost::throw_exception( std::range_error("gray_coded_qrng: seed") ); + + seq_code ^= (seq_code >> 1); + // Fail if we see that seq_code is outside bit range. + // We do that before we even touch engine state. + bit_range_checker_t::check_log2(seq_code); + + set_zero_state(); + for (unsigned r = 0; seq_code != 0; ++r, seq_code >>= 1) + { + if (seq_code & static_cast(1)) + update_quasi(r); + } + } + // Everything went well, set the new seq count + base_t::reset_seq(init); + } + +private: + void compute_seq(size_type seq) + { + // Find the position of the least-significant zero in sequence count. + // This is the bit that changes in the Gray-code representation as + // the count is advanced. + unsigned r = multiprecision::lsb(~seq); + bit_range_checker_t::check(r); + update_quasi(r); + } + + void update_quasi(unsigned r) + { + // Calculate the next state. + std::transform(this->state_begin(), this->state_end(), + this->lattice.iter_at(r * this->dimension()), this->state_begin(), + std::bit_xor()); + } + + void set_zero_state() + { + std::fill(this->state_begin(), this->state_end(), result_type /*zero*/ ()); + } +}; + +}} // namespace detail::random + +} // namespace boost + +#endif // BOOST_RANDOM_DETAIL_GRAY_CODED_QRNG_HPP diff --git a/include/boost/random/detail/gray_coded_qrng_base.hpp b/include/boost/random/detail/gray_coded_qrng_base.hpp deleted file mode 100644 index d568887..0000000 --- a/include/boost/random/detail/gray_coded_qrng_base.hpp +++ /dev/null @@ -1,103 +0,0 @@ -/* boost random/detail/gray_coded_qrng_base.hpp header file - * - * Copyright Justinas Vygintas Daugmaudis 2010-2017 - * 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) - */ - -#ifndef BOOST_RANDOM_DETAIL_GRAY_CODED_QRNG_BASE_HPP -#define BOOST_RANDOM_DETAIL_GRAY_CODED_QRNG_BASE_HPP - -#include - -// Prerequisite headers for bitscan to work -#include -#include -#include -#include // find_lsb - -//!\file -//!Describes the gray-coded quasi-random number generator base class template. - -namespace boost { -namespace random { - -namespace detail { - -template -class gray_coded_qrng_base : public qrng_base -{ -private: - typedef gray_coded_qrng_base self_t; - typedef qrng_base base_t; - - // The base needs to access modifying member f-ns, and we - // don't want these functions to be available for the public use - friend class qrng_base; - -public: - typedef typename LatticeT::value_type result_type; - - explicit gray_coded_qrng_base(std::size_t dimension) - : base_t(dimension) - {} - - // default copy c-tor is fine - - // default assignment operator is fine - -protected: - void seed(std::size_t init, const char *msg) - { - this->curr_elem = 0; - if (init != this->seq_count) - { - base_t::derived().seed(); - - this->seq_count = init; - init ^= (init / 2); - for (int r = 0; init != 0; ++r, init >>= 1) - { - if (init & 1) - update_quasi(r, msg); - } - } - } - -private: - // Compute next state for this QRNG - void compute_next() - { - compute_seq(this->seq_count++); - } - - void compute_seq(std::size_t cnt) - { - // Find the position of the least-significant zero in sequence count. - // This is the bit that changes in the Gray-code representation as - // the count is advanced. - int r = multiprecision::detail::find_lsb(~cnt); - update_quasi(r, "compute_seq"); - } - - void update_quasi(int r, const char* msg) - { - if (r < LatticeT::bit_count) - { - // Calculate the next state. - for (std::size_t i = 0; i != this->dimension(); ++i) - this->quasi_state[i] ^= this->lattice(r, i); - } - else - { - boost::throw_exception( std::overflow_error(msg) ); - } - } -}; - -}} // namespace detail::random - -} // namespace boost - -#endif // BOOST_RANDOM_DETAIL_GRAY_CODED_QRNG_BASE_HPP diff --git a/include/boost/random/detail/niederreiter_base2_table.hpp b/include/boost/random/detail/niederreiter_base2_table.hpp new file mode 100644 index 0000000..68bace3 --- /dev/null +++ b/include/boost/random/detail/niederreiter_base2_table.hpp @@ -0,0 +1,513 @@ +/* boost random/detail/nierderreiter_base2_table.hpp header file + * + * Copyright Justinas Vygintas Daugmaudis 2010-2018 + * 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) + */ + +#ifndef BOOST_RANDOM_DETAIL_NIEDERREITER_BASE2_TABLE_HPP +#define BOOST_RANDOM_DETAIL_NIEDERREITER_BASE2_TABLE_HPP + +#include + +namespace boost { +namespace random { + +namespace detail { +namespace qrng_tables { + +// Maximum allowed space dimension. This number of dimensions has been +// chosen because up to 4720th GF(2) prime the values fit to unsigned short, +// which produces a (still) reasonably small table. +#define BOOST_RANDOM_NIEDERREITER_BASE2_MAX_DIMENSION 4720 + +struct niederreiter_base2 +{ + BOOST_STATIC_CONSTANT(unsigned, max_dimension = BOOST_RANDOM_NIEDERREITER_BASE2_MAX_DIMENSION); + + typedef unsigned short value_type; + + // Binary irreducible polynomials (primes in the ring GF(2)[X]), evaluated at X=2. + // Mathematica code: + // Reap[ + // Do[If[IrreduciblePolynomialQ[ + // IntegerDigits[n, 2].x^Reverse[Range[0, Floor[Log[2, n]]]], + // Modulus -> 2], Sow[n]], {n, 2, 65535}]][[2, 1]] + static value_type polynomial(std::size_t n) + { + static const value_type nb2_a[max_dimension] = { + 2, 3, 7, 11, 13, 19, 25, 31, 37, 41, 47, 55, 59, 61, 67, 73, 87, 91, + 97, 103, 109, 115, 117, 131, 137, 143, 145, 157, 167, 171, 185, 191, + 193, 203, 211, 213, 229, 239, 241, 247, 253, 283, 285, 299, 301, 313, + 319, 333, 351, 355, 357, 361, 369, 375, 379, 391, 395, 397, 415, 419, + 425, 433, 445, 451, 463, 471, 477, 487, 499, 501, 505, 515, 529, 535, + 539, 545, 557, 563, 587, 601, 607, 613, 617, 623, 631, 637, 647, 661, + 665, 675, 677, 687, 695, 701, 719, 721, 731, 757, 761, 769, 787, 789, + 799, 803, 817, 827, 841, 847, 859, 865, 875, 877, 883, 895, 901, 911, + 929, 949, 953, 967, 971, 973, 981, 985, 995, 1001, 1019, 1033, 1039, + 1051, 1053, 1063, 1069, 1077, 1095, 1107, 1123, 1125, 1135, 1153, + 1163, 1177, 1193, 1199, 1221, 1225, 1239, 1255, 1261, 1267, 1279, + 1291, 1293, 1305, 1311, 1315, 1329, 1341, 1347, 1367, 1377, 1383, + 1387, 1413, 1423, 1431, 1435, 1441, 1451, 1465, 1473, 1479, 1509, + 1527, 1531, 1555, 1557, 1571, 1573, 1585, 1591, 1603, 1615, 1617, + 1627, 1657, 1663, 1669, 1673, 1703, 1709, 1717, 1727, 1729, 1741, + 1747, 1759, 1783, 1789, 1807, 1809, 1815, 1821, 1825, 1835, 1845, + 1849, 1863, 1869, 1877, 1881, 1891, 1915, 1917, 1921, 1927, 1933, + 1939, 1961, 1969, 1989, 2011, 2027, 2035, 2041, 2047, 2053, 2071, + 2091, 2093, 2119, 2147, 2149, 2161, 2171, 2189, 2197, 2207, 2217, + 2225, 2243, 2255, 2257, 2273, 2279, 2283, 2293, 2317, 2323, 2341, + 2345, 2359, 2363, 2365, 2373, 2377, 2385, 2395, 2419, 2421, 2431, + 2435, 2447, 2475, 2477, 2489, 2503, 2521, 2533, 2543, 2551, 2561, + 2567, 2579, 2581, 2601, 2633, 2657, 2669, 2681, 2687, 2693, 2705, + 2717, 2727, 2731, 2739, 2741, 2773, 2783, 2787, 2793, 2799, 2801, + 2811, 2819, 2825, 2833, 2867, 2879, 2881, 2891, 2905, 2911, 2917, + 2927, 2941, 2951, 2955, 2963, 2965, 2991, 2999, 3005, 3017, 3035, + 3037, 3047, 3053, 3083, 3085, 3097, 3103, 3121, 3159, 3169, 3179, + 3187, 3189, 3205, 3209, 3223, 3227, 3229, 3251, 3263, 3271, 3277, + 3283, 3285, 3299, 3305, 3319, 3331, 3343, 3357, 3367, 3373, 3393, + 3399, 3413, 3417, 3427, 3439, 3441, 3475, 3487, 3497, 3515, 3517, + 3529, 3543, 3547, 3553, 3559, 3573, 3583, 3589, 3613, 3617, 3623, + 3627, 3635, 3641, 3655, 3659, 3669, 3679, 3697, 3707, 3709, 3713, + 3731, 3743, 3747, 3771, 3785, 3791, 3805, 3827, 3833, 3851, 3865, + 3889, 3895, 3933, 3947, 3949, 3957, 3961, 3971, 3985, 3991, 3995, + 4007, 4013, 4021, 4045, 4051, 4069, 4073, 4091, 4105, 4119, 4129, + 4147, 4149, 4159, 4173, 4179, 4201, 4215, 4219, 4221, 4225, 4235, + 4249, 4259, 4261, 4303, 4305, 4331, 4333, 4351, 4359, 4383, 4387, + 4401, 4407, 4411, 4431, 4439, 4449, 4459, 4461, 4473, 4483, 4485, + 4497, 4523, 4531, 4569, 4575, 4579, 4591, 4593, 4609, 4621, 4627, + 4633, 4645, 4663, 4667, 4669, 4675, 4677, 4711, 4717, 4723, 4735, + 4789, 4793, 4801, 4811, 4873, 4879, 4891, 4893, 4897, 4915, 4921, + 4927, 4941, 4965, 4977, 5017, 5023, 5027, 5033, 5039, 5051, 5059, + 5073, 5079, 5085, 5107, 5109, 5127, 5139, 5169, 5175, 5193, 5199, + 5211, 5213, 5223, 5227, 5237, 5247, 5257, 5281, 5287, 5293, 5301, + 5325, 5331, 5337, 5343, 5349, 5391, 5405, 5451, 5453, 5505, 5523, + 5541, 5545, 5563, 5573, 5591, 5597, 5611, 5625, 5635, 5641, 5659, + 5695, 5697, 5703, 5707, 5717, 5721, 5731, 5733, 5743, 5779, 5797, + 5821, 5827, 5833, 5841, 5857, 5863, 5875, 5887, 5899, 5909, 5913, + 5949, 5955, 5957, 5967, 5975, 5981, 6003, 6005, 6009, 6025, 6031, + 6039, 6045, 6061, 6067, 6079, 6081, 6111, 6139, 6151, 6157, 6175, + 6179, 6193, 6199, 6217, 6231, 6237, 6253, 6265, 6271, 6275, 6289, + 6295, 6305, 6329, 6347, 6349, 6383, 6385, 6395, 6405, 6409, 6427, + 6445, 6453, 6465, 6475, 6495, 6501, 6511, 6523, 6529, 6539, 6553, + 6577, 6583, 6589, 6601, 6607, 6621, 6631, 6637, 6649, 6683, 6685, + 6689, 6699, 6707, 6733, 6739, 6741, 6751, 6755, 6761, 6779, 6795, + 6833, 6853, 6865, 6881, 6887, 6891, 6901, 6923, 6925, 6931, 6937, + 6943, 6959, 6981, 6999, 7049, 7055, 7057, 7079, 7093, 7097, 7103, + 7105, 7115, 7123, 7139, 7165, 7171, 7173, 7183, 7185, 7191, 7207, + 7245, 7263, 7303, 7327, 7333, 7351, 7355, 7365, 7369, 7375, 7383, + 7403, 7405, 7411, 7425, 7431, 7459, 7471, 7485, 7491, 7505, 7515, + 7517, 7527, 7541, 7545, 7555, 7557, 7561, 7569, 7591, 7603, 7617, + 7663, 7687, 7701, 7705, 7727, 7739, 7741, 7749, 7761, 7773, 7777, + 7783, 7795, 7823, 7831, 7835, 7865, 7871, 7885, 7891, 7907, 7921, + 7927, 7939, 7953, 7963, 7975, 7993, 8007, 8011, 8019, 8037, 8049, + 8061, 8065, 8077, 8089, 8111, 8123, 8125, 8131, 8133, 8137, 8161, + 8173, 8191, 8219, 8231, 8245, 8275, 8293, 8303, 8331, 8333, 8351, + 8357, 8367, 8379, 8381, 8387, 8393, 8417, 8435, 8461, 8469, 8489, + 8495, 8507, 8515, 8551, 8555, 8569, 8585, 8599, 8605, 8639, 8641, + 8647, 8653, 8671, 8675, 8689, 8699, 8729, 8741, 8759, 8765, 8771, + 8795, 8797, 8825, 8831, 8841, 8855, 8859, 8883, 8895, 8909, 8943, + 8951, 8955, 8965, 8999, 9003, 9031, 9045, 9049, 9071, 9073, 9085, + 9095, 9101, 9109, 9123, 9129, 9137, 9143, 9147, 9185, 9197, 9209, + 9227, 9235, 9247, 9253, 9257, 9277, 9297, 9303, 9313, 9325, 9343, + 9347, 9371, 9373, 9397, 9407, 9409, 9415, 9419, 9443, 9481, 9495, + 9501, 9505, 9517, 9529, 9555, 9557, 9571, 9585, 9591, 9607, 9611, + 9621, 9625, 9631, 9647, 9661, 9669, 9679, 9687, 9707, 9731, 9733, + 9745, 9773, 9791, 9803, 9811, 9817, 9833, 9847, 9851, 9863, 9875, + 9881, 9905, 9911, 9917, 9923, 9963, 9973, 10003, 10025, 10043, 10063, + 10071, 10077, 10091, 10099, 10105, 10115, 10129, 10145, 10169, 10183, + 10187, 10207, 10223, 10225, 10247, 10265, 10271, 10275, 10289, 10299, + 10301, 10309, 10343, 10357, 10373, 10411, 10413, 10431, 10445, 10453, + 10463, 10467, 10473, 10491, 10505, 10511, 10513, 10523, 10539, 10549, + 10559, 10561, 10571, 10581, 10615, 10621, 10625, 10643, 10655, 10671, + 10679, 10685, 10691, 10711, 10739, 10741, 10755, 10767, 10781, 10785, + 10803, 10805, 10829, 10857, 10863, 10865, 10875, 10877, 10917, 10921, + 10929, 10949, 10967, 10971, 10987, 10995, 11009, 11029, 11043, 11045, + 11055, 11063, 11075, 11081, 11117, 11135, 11141, 11159, 11163, 11181, + 11187, 11225, 11237, 11261, 11279, 11297, 11307, 11309, 11327, 11329, + 11341, 11377, 11403, 11405, 11413, 11427, 11439, 11453, 11461, 11473, + 11479, 11489, 11495, 11499, 11533, 11545, 11561, 11567, 11575, 11579, + 11589, 11611, 11623, 11637, 11657, 11663, 11687, 11691, 11701, 11747, + 11761, 11773, 11783, 11795, 11797, 11817, 11849, 11855, 11867, 11869, + 11873, 11883, 11919, 11921, 11927, 11933, 11947, 11955, 11961, 11999, + 12027, 12029, 12037, 12041, 12049, 12055, 12095, 12097, 12107, 12109, + 12121, 12127, 12133, 12137, 12181, 12197, 12207, 12209, 12239, 12253, + 12263, 12269, 12277, 12287, 12295, 12309, 12313, 12335, 12361, 12367, + 12391, 12409, 12415, 12433, 12449, 12469, 12479, 12481, 12499, 12505, + 12517, 12527, 12549, 12559, 12597, 12615, 12621, 12639, 12643, 12657, + 12667, 12707, 12713, 12727, 12741, 12745, 12763, 12769, 12779, 12781, + 12787, 12799, 12809, 12815, 12829, 12839, 12857, 12875, 12883, 12889, + 12901, 12929, 12947, 12953, 12959, 12969, 12983, 12987, 12995, 13015, + 13019, 13031, 13063, 13077, 13103, 13137, 13149, 13173, 13207, 13211, + 13227, 13241, 13249, 13255, 13269, 13283, 13285, 13303, 13307, 13321, + 13339, 13351, 13377, 13389, 13407, 13417, 13431, 13435, 13447, 13459, + 13465, 13477, 13501, 13513, 13531, 13543, 13561, 13581, 13599, 13605, + 13617, 13623, 13637, 13647, 13661, 13677, 13683, 13695, 13725, 13729, + 13753, 13773, 13781, 13785, 13795, 13801, 13807, 13825, 13835, 13855, + 13861, 13871, 13883, 13897, 13905, 13915, 13939, 13941, 13969, 13979, + 13981, 13997, 14027, 14035, 14037, 14051, 14063, 14085, 14095, 14107, + 14113, 14125, 14137, 14145, 14151, 14163, 14193, 14199, 14219, 14229, + 14233, 14243, 14277, 14287, 14289, 14295, 14301, 14305, 14323, 14339, + 14341, 14359, 14365, 14375, 14387, 14411, 14425, 14441, 14449, 14499, + 14513, 14523, 14537, 14543, 14561, 14579, 14585, 14593, 14599, 14603, + 14611, 14641, 14671, 14695, 14701, 14723, 14725, 14743, 14753, 14759, + 14765, 14795, 14797, 14803, 14831, 14839, 14845, 14855, 14889, 14895, + 14909, 14929, 14941, 14945, 14951, 14963, 14965, 14985, 15033, 15039, + 15053, 15059, 15061, 15071, 15077, 15081, 15099, 15121, 15147, 15149, + 15157, 15167, 15187, 15193, 15203, 15205, 15215, 15217, 15223, 15243, + 15257, 15269, 15273, 15287, 15291, 15313, 15335, 15347, 15359, 15373, + 15379, 15381, 15391, 15395, 15397, 15419, 15439, 15453, 15469, 15491, + 15503, 15517, 15527, 15531, 15545, 15559, 15593, 15611, 15613, 15619, + 15639, 15643, 15649, 15661, 15667, 15669, 15681, 15693, 15717, 15721, + 15741, 15745, 15765, 15793, 15799, 15811, 15825, 15835, 15847, 15851, + 15865, 15877, 15881, 15887, 15899, 15915, 15935, 15937, 15955, 15973, + 15977, 16011, 16035, 16061, 16069, 16087, 16093, 16097, 16121, 16141, + 16153, 16159, 16165, 16183, 16189, 16195, 16197, 16201, 16209, 16215, + 16225, 16259, 16265, 16273, 16299, 16309, 16355, 16375, 16381, 16417, + 16427, 16435, 16441, 16447, 16467, 16479, 16485, 16507, 16519, 16553, + 16559, 16571, 16573, 16591, 16599, 16619, 16627, 16633, 16651, 16653, + 16659, 16699, 16707, 16713, 16727, 16743, 16749, 16785, 16795, 16797, + 16807, 16811, 16813, 16821, 16853, 16857, 16881, 16897, 16909, 16965, + 16969, 16983, 16993, 17011, 17017, 17023, 17027, 17029, 17053, 17057, + 17095, 17099, 17101, 17123, 17129, 17135, 17155, 17161, 17179, 17185, + 17191, 17215, 17257, 17275, 17277, 17287, 17301, 17327, 17353, 17373, + 17387, 17389, 17407, 17419, 17421, 17475, 17501, 17523, 17545, 17601, + 17619, 17621, 17631, 17635, 17649, 17659, 17667, 17673, 17679, 17707, + 17721, 17753, 17775, 17783, 17789, 17805, 17817, 17823, 17829, 17847, + 17861, 17865, 17873, 17879, 17895, 17907, 17919, 17935, 17949, 17959, + 17973, 17991, 18009, 18019, 18033, 18043, 18061, 18067, 18069, 18083, + 18085, 18117, 18127, 18139, 18155, 18175, 18213, 18225, 18243, 18255, + 18303, 18313, 18321, 18331, 18343, 18357, 18369, 18387, 18393, 18405, + 18409, 18415, 18429, 18451, 18457, 18463, 18491, 18499, 18513, 18523, + 18529, 18535, 18559, 18563, 18577, 18623, 18631, 18659, 18673, 18679, + 18685, 18717, 18721, 18733, 18745, 18753, 18771, 18783, 18789, 18793, + 18807, 18823, 18827, 18857, 18895, 18897, 18909, 18913, 18919, 18967, + 18997, 19033, 19045, 19067, 19073, 19079, 19083, 19091, 19107, 19119, + 19133, 19145, 19165, 19181, 19193, 19231, 19255, 19273, 19291, 19297, + 19307, 19309, 19315, 19321, 19333, 19343, 19351, 19361, 19371, 19379, + 19385, 19403, 19405, 19413, 19423, 19441, 19451, 19465, 19483, 19485, + 19495, 19499, 19519, 19527, 19531, 19539, 19541, 19557, 19581, 19597, + 19621, 19645, 19653, 19665, 19671, 19693, 19711, 19733, 19743, 19753, + 19761, 19781, 19791, 19793, 19829, 19845, 19855, 19885, 19891, 19905, + 19923, 19953, 19963, 19969, 19989, 20003, 20023, 20035, 20041, 20049, + 20075, 20077, 20099, 20123, 20147, 20179, 20197, 20201, 20207, 20253, + 20257, 20299, 20309, 20319, 20329, 20335, 20353, 20365, 20383, 20389, + 20393, 20407, 20411, 20439, 20459, 20461, 20473, 20487, 20511, 20517, + 20571, 20573, 20641, 20683, 20693, 20697, 20707, 20713, 20719, 20731, + 20763, 20769, 20781, 20799, 20819, 20825, 20831, 20847, 20861, 20875, + 20889, 20901, 20913, 20919, 20943, 20945, 20955, 20971, 20973, 20981, + 20991, 20997, 21007, 21037, 21093, 21105, 21131, 21145, 21155, 21169, + 21181, 21187, 21189, 21199, 21201, 21223, 21227, 21241, 21249, 21273, + 21285, 21289, 21303, 21321, 21339, 21351, 21365, 21403, 21405, 21415, + 21433, 21439, 21447, 21459, 21477, 21489, 21501, 21507, 21519, 21527, + 21557, 21561, 21575, 21593, 21599, 21627, 21645, 21651, 21653, 21663, + 21681, 21687, 21691, 21725, 21729, 21739, 21779, 21785, 21807, 21815, + 21863, 21867, 21877, 21881, 21887, 21891, 21893, 21905, 21911, 21933, + 21953, 21971, 21983, 21993, 22007, 22023, 22029, 22037, 22051, 22057, + 22063, 22065, 22103, 22109, 22171, 22187, 22189, 22195, 22209, 22215, + 22221, 22257, 22263, 22267, 22315, 22317, 22335, 22347, 22357, 22361, + 22371, 22373, 22397, 22419, 22447, 22461, 22467, 22469, 22487, 22503, + 22515, 22531, 22545, 22561, 22573, 22579, 22581, 22591, 22593, 22653, + 22663, 22667, 22677, 22681, 22691, 22703, 22705, 22737, 22749, 22759, + 22763, 22777, 22783, 22803, 22819, 22843, 22863, 22911, 22927, 22935, + 22941, 22945, 22951, 22955, 22965, 22987, 23007, 23017, 23037, 23053, + 23059, 23071, 23077, 23099, 23101, 23107, 23109, 23113, 23157, 23183, + 23207, 23221, 23233, 23251, 23253, 23257, 23287, 23311, 23319, 23325, + 23339, 23347, 23353, 23361, 23395, 23401, 23415, 23449, 23459, 23465, + 23491, 23493, 23521, 23531, 23545, 23559, 23563, 23577, 23601, 23607, + 23625, 23645, 23661, 23673, 23683, 23713, 23743, 23745, 23755, 23757, + 23781, 23813, 23825, 23837, 23859, 23861, 23879, 23919, 23943, 23949, + 23957, 23967, 23971, 23977, 23995, 24009, 24015, 24027, 24033, 24067, + 24079, 24091, 24109, 24135, 24139, 24163, 24189, 24193, 24217, 24229, + 24233, 24279, 24283, 24295, 24309, 24327, 24333, 24345, 24351, 24355, + 24381, 24387, 24389, 24401, 24417, 24427, 24437, 24457, 24471, 24491, + 24525, 24543, 24547, 24549, 24561, 24587, 24589, 24597, 24623, 24637, + 24655, 24657, 24673, 24679, 24683, 24713, 24727, 24733, 24737, 24747, + 24755, 24761, 24787, 24789, 24823, 24841, 24849, 24877, 24889, 24897, + 24915, 24945, 24957, 24991, 24997, 25007, 25019, 25051, 25069, 25077, + 25087, 25131, 25139, 25141, 25145, 25159, 25165, 25187, 25199, 25213, + 25229, 25247, 25253, 25257, 25265, 25271, 25303, 25307, 25309, 25323, + 25325, 25331, 25343, 25379, 25393, 25399, 25405, 25435, 25453, 25461, + 25477, 25481, 25489, 25505, 25535, 25583, 25597, 25609, 25623, 25645, + 25665, 25671, 25677, 25685, 25739, 25749, 25759, 25769, 25777, 25831, + 25845, 25857, 25867, 25881, 25911, 25915, 25923, 25925, 25929, 25947, + 25987, 26001, 26023, 26029, 26041, 26047, 26067, 26069, 26073, 26085, + 26095, 26097, 26103, 26113, 26119, 26125, 26147, 26171, 26191, 26205, + 26219, 26221, 26227, 26243, 26255, 26263, 26279, 26283, 26293, 26297, + 26329, 26335, 26345, 26385, 26395, 26401, 26419, 26443, 26463, 26473, + 26487, 26497, 26531, 26543, 26551, 26577, 26599, 26603, 26613, 26627, + 26641, 26651, 26653, 26667, 26689, 26707, 26735, 26743, 26763, 26765, + 26771, 26783, 26789, 26793, 26821, 26825, 26879, 26887, 26905, 26927, + 26941, 26967, 26987, 26995, 26997, 27001, 27013, 27023, 27035, 27037, + 27041, 27051, 27079, 27085, 27113, 27137, 27143, 27147, 27161, 27171, + 27183, 27217, 27227, 27239, 27243, 27245, 27253, 27267, 27287, 27315, + 27317, 27327, 27329, 27339, 27341, 27369, 27375, 27387, 27389, 27395, + 27415, 27435, 27443, 27449, 27463, 27467, 27477, 27497, 27517, 27521, + 27533, 27541, 27551, 27555, 27557, 27569, 27575, 27589, 27607, 27617, + 27629, 27635, 27641, 27659, 27673, 27695, 27709, 27717, 27735, 27745, + 27763, 27829, 27833, 27839, 27841, 27847, 27851, 27877, 27889, 27909, + 27913, 27919, 27927, 27947, 27987, 28003, 28005, 28009, 28027, 28067, + 28081, 28091, 28093, 28099, 28101, 28125, 28169, 28199, 28205, 28211, + 28225, 28237, 28243, 28271, 28283, 28289, 28295, 28309, 28335, 28343, + 28355, 28379, 28381, 28409, 28417, 28437, 28457, 28465, 28475, 28495, + 28503, 28507, 28513, 28549, 28561, 28567, 28587, 28597, 28615, 28633, + 28639, 28649, 28677, 28701, 28715, 28723, 28725, 28747, 28797, 28801, + 28813, 28841, 28855, 28859, 28873, 28879, 28893, 28897, 28947, 28949, + 28953, 28963, 28977, 28983, 28989, 29021, 29035, 29065, 29079, 29083, + 29089, 29109, 29119, 29131, 29151, 29157, 29175, 29179, 29209, 29215, + 29231, 29233, 29243, 29263, 29281, 29287, 29327, 29357, 29363, 29377, + 29389, 29395, 29407, 29413, 29425, 29431, 29443, 29449, 29479, 29483, + 29505, 29525, 29541, 29551, 29581, 29587, 29605, 29629, 29641, 29649, + 29671, 29683, 29685, 29695, 29715, 29717, 29737, 29775, 29783, 29787, + 29803, 29805, 29827, 29867, 29875, 29895, 29901, 29909, 29919, 29929, + 29947, 29949, 29975, 29979, 29985, 30005, 30017, 30027, 30071, 30075, + 30081, 30105, 30115, 30141, 30159, 30161, 30187, 30197, 30201, 30207, + 30237, 30265, 30279, 30291, 30293, 30303, 30307, 30309, 30313, 30343, + 30357, 30367, 30371, 30383, 30395, 30405, 30417, 30443, 30451, 30457, + 30475, 30511, 30537, 30545, 30551, 30573, 30579, 30595, 30601, 30631, + 30637, 30645, 30663, 30675, 30677, 30703, 30741, 30757, 30769, 30781, + 30799, 30801, 30811, 30829, 30887, 30893, 30899, 30911, 30923, 30925, + 30937, 30943, 30953, 30959, 30979, 30991, 30999, 31015, 31027, 31053, + 31065, 31087, 31089, 31099, 31105, 31111, 31141, 31153, 31173, 31177, + 31191, 31197, 31235, 31259, 31271, 31275, 31285, 31295, 31307, 31317, + 31351, 31361, 31373, 31401, 31415, 31419, 31427, 31457, 31475, 31477, + 31499, 31523, 31547, 31557, 31567, 31569, 31581, 31591, 31609, 31621, + 31631, 31649, 31659, 31673, 31699, 31715, 31729, 31735, 31749, 31753, + 31783, 31789, 31833, 31849, 31869, 31883, 31891, 31893, 31907, 31927, + 31939, 31953, 31965, 31979, 31993, 31999, 32001, 32021, 32055, 32069, + 32073, 32115, 32121, 32143, 32145, 32151, 32167, 32179, 32199, 32205, + 32213, 32233, 32251, 32253, 32257, 32269, 32281, 32303, 32325, 32353, + 32373, 32383, 32393, 32399, 32411, 32413, 32427, 32447, 32455, 32467, + 32483, 32485, 32521, 32545, 32575, 32589, 32597, 32625, 32651, 32653, + 32665, 32671, 32675, 32689, 32707, 32709, 32721, 32727, 32737, 32743, + 32771, 32785, 32791, 32813, 32821, 32863, 32879, 32887, 32897, 32903, + 32915, 32933, 32945, 32957, 32963, 32975, 32989, 32999, 33013, 33023, + 33025, 33045, 33061, 33111, 33117, 33121, 33133, 33145, 33157, 33185, + 33191, 33209, 33227, 33229, 33237, 33247, 33277, 33299, 33339, 33349, + 33407, 33417, 33423, 33435, 33483, 33497, 33507, 33521, 33559, 33563, + 33579, 33587, 33607, 33613, 33631, 33635, 33641, 33649, 33675, 33685, + 33689, 33711, 33723, 33725, 33733, 33745, 33781, 33817, 33827, 33839, + 33841, 33847, 33865, 33895, 33901, 33913, 33923, 33925, 33943, 33953, + 33973, 34015, 34031, 34039, 34043, 34045, 34077, 34081, 34087, 34099, + 34119, 34123, 34143, 34161, 34171, 34177, 34189, 34211, 34225, 34231, + 34245, 34249, 34267, 34285, 34291, 34313, 34321, 34333, 34347, 34389, + 34393, 34405, 34429, 34433, 34451, 34473, 34479, 34487, 34499, 34523, + 34547, 34559, 34571, 34573, 34581, 34591, 34601, 34609, 34667, 34693, + 34697, 34703, 34717, 34731, 34733, 34739, 34751, 34783, 34793, 34801, + 34807, 34817, 34823, 34853, 34871, 34875, 34889, 34909, 34913, 34931, + 34937, 34947, 34959, 34961, 34995, 34997, 35015, 35033, 35075, 35077, + 35081, 35089, 35095, 35111, 35173, 35197, 35221, 35225, 35247, 35279, + 35281, 35291, 35293, 35309, 35327, 35351, 35385, 35413, 35427, 35429, + 35441, 35451, 35463, 35467, 35487, 35503, 35505, 35549, 35595, 35597, + 35643, 35645, 35651, 35693, 35699, 35729, 35741, 35777, 35787, 35797, + 35801, 35813, 35825, 35873, 35879, 35911, 35925, 35929, 35939, 35945, + 35975, 35987, 36003, 36009, 36027, 36041, 36065, 36075, 36097, 36103, + 36107, 36133, 36143, 36163, 36177, 36187, 36205, 36223, 36229, 36233, + 36251, 36257, 36287, 36299, 36301, 36325, 36329, 36335, 36343, 36363, + 36383, 36411, 36433, 36439, 36467, 36469, 36495, 36503, 36507, 36513, + 36543, 36545, 36563, 36575, 36581, 36603, 36623, 36647, 36651, 36665, + 36673, 36691, 36693, 36709, 36727, 36733, 36773, 36791, 36797, 36809, + 36817, 36833, 36839, 36875, 36889, 36895, 36901, 36919, 36925, 36931, + 36951, 36961, 36973, 36981, 37001, 37009, 37019, 37021, 37037, 37091, + 37125, 37129, 37135, 37143, 37147, 37149, 37185, 37197, 37239, 37243, + 37273, 37283, 37289, 37297, 37309, 37327, 37345, 37379, 37393, 37403, + 37409, 37415, 37427, 37439, 37453, 37459, 37471, 37499, 37511, 37525, + 37539, 37559, 37577, 37597, 37621, 37625, 37651, 37681, 37687, 37701, + 37705, 37719, 37747, 37759, 37763, 37789, 37793, 37813, 37835, 37855, + 37871, 37873, 37883, 37903, 37931, 37933, 37941, 37963, 37971, 38007, + 38013, 38027, 38035, 38041, 38053, 38057, 38075, 38085, 38103, 38107, + 38113, 38119, 38133, 38143, 38151, 38165, 38185, 38193, 38205, 38213, + 38241, 38251, 38281, 38299, 38317, 38349, 38367, 38371, 38377, 38419, + 38421, 38447, 38449, 38455, 38461, 38467, 38493, 38503, 38521, 38551, + 38573, 38593, 38603, 38611, 38623, 38639, 38651, 38661, 38699, 38709, + 38713, 38733, 38755, 38805, 38815, 38819, 38821, 38825, 38833, 38875, + 38877, 38881, 38899, 38911, 38921, 38945, 38957, 38983, 39061, 39065, + 39087, 39099, 39107, 39109, 39127, 39133, 39143, 39155, 39161, 39179, + 39193, 39205, 39209, 39215, 39223, 39235, 39237, 39259, 39277, 39295, + 39305, 39313, 39323, 39353, 39359, 39361, 39371, 39381, 39395, 39397, + 39461, 39473, 39503, 39511, 39515, 39517, 39521, 39533, 39545, 39551, + 39557, 39575, 39581, 39595, 39609, 39623, 39627, 39651, 39675, 39697, + 39707, 39725, 39731, 39745, 39763, 39775, 39791, 39799, 39805, 39815, + 39819, 39827, 39863, 39869, 39889, 39915, 39929, 39935, 39957, 39967, + 39983, 39995, 39997, 40017, 40029, 40039, 40051, 40053, 40057, 40069, + 40127, 40135, 40149, 40165, 40169, 40177, 40183, 40195, 40277, 40281, + 40291, 40311, 40321, 40331, 40345, 40351, 40357, 40381, 40451, 40465, + 40471, 40481, 40487, 40505, 40519, 40533, 40537, 40543, 40547, 40553, + 40577, 40607, 40611, 40685, 40691, 40715, 40723, 40729, 40739, 40751, + 40777, 40783, 40807, 40859, 40877, 40883, 40885, 40909, 40921, 40951, + 40971, 40981, 40995, 40997, 41007, 41027, 41051, 41053, 41063, 41067, + 41069, 41087, 41097, 41105, 41127, 41141, 41165, 41183, 41193, 41211, + 41219, 41231, 41245, 41249, 41255, 41267, 41269, 41273, 41287, 41305, + 41327, 41339, 41345, 41375, 41393, 41413, 41423, 41441, 41487, 41501, + 41517, 41525, 41537, 41543, 41557, 41571, 41583, 41625, 41641, 41659, + 41661, 41669, 41673, 41687, 41691, 41709, 41735, 41739, 41741, 41753, + 41759, 41763, 41769, 41797, 41835, 41843, 41861, 41871, 41879, 41889, + 41907, 41921, 41933, 41941, 41987, 41989, 41993, 42001, 42067, 42073, + 42085, 42113, 42119, 42123, 42133, 42137, 42149, 42159, 42161, 42173, + 42179, 42203, 42219, 42221, 42241, 42275, 42277, 42281, 42319, 42355, + 42371, 42407, 42425, 42439, 42445, 42473, 42481, 42491, 42515, 42533, + 42543, 42551, 42557, 42577, 42593, 42611, 42641, 42651, 42653, 42695, + 42737, 42749, 42779, 42795, 42809, 42847, 42865, 42893, 42905, 42929, + 42939, 42941, 42959, 42961, 42973, 42983, 43013, 43051, 43059, 43065, + 43083, 43085, 43093, 43113, 43119, 43133, 43137, 43155, 43167, 43171, + 43177, 43191, 43215, 43229, 43233, 43243, 43275, 43283, 43289, 43301, + 43337, 43381, 43409, 43431, 43437, 43455, 43457, 43497, 43503, 43511, + 43533, 43541, 43567, 43569, 43587, 43589, 43599, 43601, 43617, 43641, + 43677, 43691, 43693, 43699, 43705, 43731, 43743, 43761, 43779, 43791, + 43805, 43829, 43833, 43847, 43875, 43901, 43905, 43915, 43929, 43963, + 43973, 43985, 43991, 43995, 44007, 44019, 44033, 44039, 44045, 44051, + 44073, 44087, 44091, 44101, 44123, 44141, 44147, 44159, 44165, 44175, + 44183, 44231, 44245, 44255, 44265, 44285, 44293, 44305, 44315, 44321, + 44363, 44365, 44399, 44451, 44463, 44489, 44509, 44519, 44523, 44537, + 44553, 44573, 44589, 44601, 44607, 44621, 44639, 44643, 44657, 44663, + 44667, 44685, 44693, 44707, 44731, 44759, 44765, 44775, 44789, 44801, + 44819, 44831, 44841, 44847, 44859, 44867, 44873, 44903, 44917, 44943, + 44957, 44971, 44993, 45011, 45027, 45047, 45053, 45071, 45083, 45101, + 45109, 45119, 45141, 45175, 45197, 45203, 45231, 45251, 45253, 45265, + 45281, 45299, 45319, 45323, 45325, 45373, 45399, 45405, 45429, 45455, + 45463, 45469, 45473, 45511, 45535, 45541, 45579, 45587, 45589, 45635, + 45641, 45647, 45685, 45695, 45705, 45723, 45749, 45761, 45791, 45801, + 45807, 45815, 45829, 45847, 45863, 45923, 45947, 45953, 45971, 45989, + 45993, 46001, 46007, 46021, 46039, 46043, 46045, 46073, 46081, 46093, + 46105, 46111, 46121, 46147, 46149, 46167, 46189, 46197, 46207, 46247, + 46271, 46297, 46319, 46327, 46345, 46365, 46387, 46399, 46407, 46419, + 46421, 46441, 46455, 46459, 46485, 46505, 46523, 46531, 46551, 46561, + 46567, 46571, 46585, 46597, 46601, 46615, 46619, 46625, 46631, 46637, + 46643, 46645, 46667, 46681, 46715, 46721, 46731, 46745, 46767, 46769, + 46801, 46823, 46827, 46855, 46879, 46885, 46917, 46935, 46939, 46955, + 46969, 46979, 46993, 46999, 47005, 47009, 47027, 47051, 47101, 47135, + 47173, 47183, 47201, 47221, 47237, 47241, 47261, 47265, 47277, 47295, + 47315, 47317, 47355, 47363, 47369, 47389, 47399, 47403, 47431, 47445, + 47449, 47461, 47479, 47501, 47535, 47547, 47555, 47561, 47569, 47585, + 47597, 47603, 47605, 47621, 47631, 47633, 47659, 47673, 47705, 47721, + 47727, 47745, 47751, 47757, 47763, 47799, 47831, 47859, 47871, 47873, + 47879, 47893, 47897, 47907, 47933, 47939, 47945, 47951, 47953, 47963, + 47975, 47989, 48017, 48053, 48063, 48075, 48077, 48101, 48105, 48137, + 48179, 48185, 48227, 48229, 48233, 48251, 48267, 48269, 48287, 48297, + 48323, 48337, 48349, 48385, 48403, 48421, 48431, 48439, 48453, 48487, + 48511, 48515, 48521, 48569, 48577, 48595, 48601, 48613, 48625, 48647, + 48661, 48675, 48681, 48695, 48727, 48731, 48737, 48747, 48767, 48771, + 48785, 48811, 48853, 48857, 48881, 48919, 48929, 48935, 48947, 48949, + 48979, 48997, 49025, 49035, 49059, 49079, 49091, 49115, 49133, 49141, + 49151, 49153, 49159, 49171, 49183, 49189, 49225, 49267, 49273, 49285, + 49297, 49303, 49309, 49319, 49337, 49355, 49365, 49379, 49403, 49425, + 49441, 49459, 49471, 49483, 49503, 49519, 49527, 49531, 49533, 49555, + 49573, 49597, 49603, 49609, 49627, 49639, 49645, 49669, 49673, 49687, + 49709, 49741, 49747, 49749, 49769, 49817, 49841, 49871, 49873, 49885, + 49909, 49921, 49933, 49945, 49957, 49967, 49981, 50007, 50011, 50017, + 50035, 50051, 50075, 50077, 50091, 50093, 50111, 50119, 50147, 50159, + 50173, 50181, 50209, 50227, 50247, 50251, 50271, 50287, 50301, 50323, + 50335, 50341, 50359, 50373, 50391, 50397, 50411, 50425, 50431, 50443, + 50453, 50479, 50481, 50505, 50523, 50549, 50553, 50569, 50587, 50593, + 50611, 50613, 50623, 50635, 50655, 50665, 50671, 50685, 50735, 50737, + 50749, 50757, 50769, 50795, 50805, 50809, 50831, 50839, 50859, 50867, + 50873, 50881, 50887, 50893, 50901, 50915, 50921, 50939, 50947, 50953, + 51009, 51027, 51033, 51043, 51063, 51097, 51103, 51113, 51139, 51159, + 51163, 51189, 51203, 51227, 51253, 51265, 51277, 51295, 51301, 51305, + 51349, 51389, 51401, 51445, 51449, 51455, 51457, 51469, 51477, 51487, + 51491, 51497, 51505, 51511, 51515, 51547, 51549, 51553, 51583, 51587, + 51599, 51627, 51655, 51659, 51661, 51673, 51749, 51753, 51759, 51779, + 51785, 51815, 51855, 51885, 51903, 51929, 51939, 51951, 51953, 51965, + 51991, 51995, 51997, 52011, 52031, 52053, 52073, 52081, 52091, 52103, + 52157, 52183, 52199, 52213, 52231, 52245, 52259, 52285, 52297, 52315, + 52333, 52351, 52355, 52357, 52379, 52385, 52391, 52397, 52403, 52417, + 52441, 52471, 52475, 52477, 52497, 52523, 52531, 52565, 52579, 52591, + 52615, 52639, 52643, 52663, 52677, 52687, 52695, 52705, 52715, 52717, + 52729, 52735, 52739, 52753, 52775, 52789, 52793, 52837, 52847, 52849, + 52895, 52901, 52923, 52931, 52933, 52937, 52945, 52951, 52979, 52991, + 53005, 53017, 53023, 53039, 53085, 53089, 53099, 53107, 53113, 53135, + 53147, 53149, 53153, 53163, 53191, 53205, 53225, 53239, 53253, 53257, + 53311, 53319, 53325, 53361, 53367, 53383, 53387, 53389, 53397, 53401, + 53411, 53425, 53445, 53455, 53457, 53463, 53473, 53497, 53515, 53541, + 53545, 53551, 53565, 53585, 53595, 53613, 53659, 53689, 53695, 53697, + 53717, 53721, 53743, 53757, 53767, 53781, 53791, 53795, 53801, 53815, + 53847, 53867, 53869, 53891, 53903, 53921, 53941, 53963, 54019, 54039, + 54055, 54081, 54091, 54105, 54111, 54121, 54135, 54139, 54145, 54163, + 54169, 54179, 54193, 54217, 54225, 54237, 54247, 54253, 54293, 54313, + 54331, 54365, 54369, 54379, 54423, 54429, 54443, 54451, 54463, 54465, + 54483, 54501, 54505, 54513, 54543, 54555, 54567, 54571, 54599, 54613, + 54617, 54627, 54653, 54675, 54711, 54723, 54753, 54759, 54771, 54773, + 54789, 54823, 54827, 54859, 54879, 54883, 54895, 54909, 54919, 54953, + 54967, 54981, 54999, 55009, 55021, 55027, 55061, 55075, 55077, 55089, + 55143, 55149, 55167, 55213, 55219, 55221, 55231, 55257, 55287, 55291, + 55309, 55315, 55369, 55383, 55405, 55433, 55439, 55451, 55463, 55467, + 55477, 55489, 55495, 55507, 55513, 55525, 55561, 55579, 55603, 55617, + 55623, 55629, 55647, 55653, 55665, 55691, 55705, 55711, 55715, 55721, + 55729, 55747, 55767, 55795, 55801, 55813, 55831, 55847, 55859, 55861, + 55871, 55897, 55933, 55947, 55955, 55961, 55971, 55985, 56003, 56029, + 56045, 56071, 56095, 56101, 56105, 56123, 56133, 56143, 56161, 56195, + 56209, 56225, 56263, 56269, 56277, 56287, 56291, 56297, 56303, 56315, + 56317, 56337, 56363, 56373, 56377, 56385, 56431, 56433, 56467, 56479, + 56495, 56529, 56535, 56539, 56565, 56601, 56617, 56625, 56645, 56663, + 56679, 56691, 56693, 56733, 56749, 56769, 56789, 56805, 56823, 56827, + 56839, 56879, 56893, 56905, 56911, 56913, 56941, 56949, 56963, 56965, + 56969, 56993, 57005, 57035, 57037, 57043, 57091, 57093, 57111, 57117, + 57121, 57139, 57177, 57187, 57193, 57199, 57201, 57253, 57275, 57289, + 57307, 57323, 57347, 57359, 57361, 57395, 57397, 57415, 57419, 57439, + 57467, 57469, 57485, 57503, 57513, 57521, 57527, 57541, 57559, 57563, + 57565, 57581, 57599, 57601, 57611, 57637, 57649, 57673, 57679, 57681, + 57693, 57703, 57707, 57727, 57779, 57811, 57817, 57839, 57863, 57867, + 57881, 57891, 57905, 57925, 57935, 57959, 57977, 57989, 57999, 58011, + 58013, 58017, 58027, 58029, 58047, 58049, 58069, 58127, 58129, 58139, + 58165, 58169, 58201, 58211, 58213, 58231, 58253, 58259, 58271, 58277, + 58287, 58295, 58307, 58331, 58355, 58367, 58399, 58417, 58441, 58459, + 58475, 58477, 58483, 58489, 58501, 58513, 58519, 58525, 58529, 58539, + 58571, 58573, 58591, 58609, 58621, 58627, 58629, 58647, 58651, 58669, + 58675, 58753, 58773, 58789, 58799, 58855, 58885, 58913, 58937, 58943, + 58951, 58963, 58985, 59015, 59067, 59069, 59095, 59101, 59115, 59125, + 59129, 59137, 59161, 59177, 59245, 59253, 59267, 59279, 59303, 59307, + 59309, 59317, 59339, 59347, 59349, 59365, 59377, 59383, 59393, 59439, + 59459, 59471, 59473, 59483, 59501, 59513, 59529, 59537, 59559, 59583, + 59585, 59595, 59597, 59603, 59643, 59645, 59651, 59663, 59681, 59687, + 59691, 59701, 59737, 59743, 59747, 59753, 59761, 59789, 59831, 59845, + 59855, 59863, 59885, 59913, 59931, 59949, 59979, 59993, 60017, 60029, + 60033, 60045, 60091, 60099, 60105, 60119, 60141, 60159, 60167, 60171, + 60185, 60195, 60201, 60219, 60229, 60247, 60253, 60263, 60267, 60275, + 60277, 60311, 60315, 60333, 60339, 60365, 60371, 60373, 60387, 60425, + 60433, 60449, 60469, 60491, 60511, 60517, 60521, 60541, 60563, 60569, + 60591, 60599, 60605, 60617, 60623, 60671, 60679, 60693, 60707, 60727, + 60745, 60765, 60769, 60779, 60823, 60833, 60843, 60851, 60871, 60877, + 60889, 60895, 60911, 60913, 60925, 60929, 60939, 60941, 60959, 60969, + 61045, 61059, 61065, 61085, 61101, 61113, 61127, 61131, 61145, 61155, + 61169, 61175, 61199, 61217, 61229, 61235, 61241, 61261, 61303, 61333, + 61343, 61361, 61371, 61409, 61415, 61419, 61427, 61429, 61433, 61447, + 61453, 61471, 61481, 61487, 61509, 61533, 61573, 61577, 61591, 61611, + 61631, 61639, 61653, 61663, 61681, 61687, 61713, 61723, 61749, 61761, + 61767, 61771, 61779, 61795, 61809, 61837, 61843, 61893, 61921, 61927, + 61939, 61941, 61951, 61975, 61981, 62023, 62029, 62037, 62041, 62063, + 62075, 62087, 62111, 62117, 62171, 62173, 62201, 62207, 62209, 62219, + 62229, 62255, 62263, 62275, 62341, 62345, 62353, 62359, 62387, 62431, + 62437, 62469, 62479, 62487, 62497, 62521, 62547, 62549, 62563, 62565, + 62569, 62587, 62603, 62617, 62627, 62641, 62653, 62659, 62671, 62707, + 62709, 62713, 62733, 62745, 62757, 62775, 62779, 62801, 62817, 62829, + 62865, 62877, 62887, 62901, 62911, 62913, 62919, 62977, 62997, 63007, + 63011, 63035, 63045, 63055, 63069, 63083, 63091, 63107, 63109, 63155, + 63157, 63193, 63215, 63227, 63265, 63277, 63295, 63309, 63315, 63337, + 63343, 63367, 63371, 63381, 63395, 63409, 63415, 63427, 63433, 63451, + 63487, 63491, 63497, 63503, 63517, 63527, 63533, 63545, 63551, 63563, + 63599, 63601, 63607, 63635, 63685, 63707, 63713, 63725, 63731, 63733, + 63751, 63765, 63779, 63803, 63805, 63823, 63825, 63859, 63865, 63877, + 63899, 63923, 63929, 63943, 63971, 63977, 63991, 64001, 64007, 64019, + 64035, 64055, 64073, 64107, 64117, 64121, 64127, 64131, 64151, 64155, + 64161, 64193, 64203, 64217, 64223, 64229, 64261, 64271, 64289, 64295, + 64309, 64333, 64341, 64351, 64361, 64369, 64385, 64397, 64419, 64425, + 64439, 64457, 64463, 64475, 64481, 64523, 64525, 64543, 64585, 64603, + 64615, 64629, 64643, 64685, 64723, 64751, 64783, 64791, 64797, 64811, + 64813, 64825, 64839, 64851, 64881, 64907, 64917, 64921, 64931, 64943, + 64945, 64963, 64989, 64993, 65003, 65029, 65069, 65075, 65077, 65089, + 65101, 65113, 65119, 65149, 65159, 65171, 65177, 65201, 65213, 65225, + 65259, 65279, 65281, 65287, 65299, 65315, 65321, 65335, 65359, 65367, + 65373, 65377, 65395, 65407, 65423, 65425, 65459, 65479, 65497, 65513, + 65519, 65533}; + return nb2_a[n]; + } +}; + +} // namespace qrng_tables +} // namespace detail + +} // namespace random + +} // namespace boost + +#endif // BOOST_RANDOM_DETAIL_NIEDERREITER_BASE2_TABLE_HPP diff --git a/include/boost/random/detail/qrng_base.hpp b/include/boost/random/detail/qrng_base.hpp index cbf5ded..44fc549 100644 --- a/include/boost/random/detail/qrng_base.hpp +++ b/include/boost/random/detail/qrng_base.hpp @@ -1,6 +1,6 @@ -/* boost random/detail/quasi_random_number_generator_base.hpp header file +/* boost random/detail/qrng_base.hpp header file * - * Copyright Justinas Vygintas Daugmaudis 2010-2017 + * Copyright Justinas Vygintas Daugmaudis 2010-2018 * 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) @@ -9,12 +9,15 @@ #ifndef BOOST_RANDOM_DETAIL_QRNG_BASE_HPP #define BOOST_RANDOM_DETAIL_QRNG_BASE_HPP -#include -#include - #include #include +#include +#include +#include +#include + +#include #include #include @@ -27,10 +30,18 @@ namespace random { namespace detail { -template +template +inline bool are_close(T x, T y, T eps) // |x - y| <= eps +{ + if (x < y) std::swap(x, y); + return !(x - y > eps); +} + +template class qrng_base { public: + typedef SizeT size_type; typedef typename LatticeT::value_type result_type; explicit qrng_base(std::size_t dimension) @@ -50,14 +61,12 @@ public: //!Throws: nothing. std::size_t dimension() const { return quasi_state.size(); } - //!Requirements: *this is mutable. - //! //!Returns: Returns a successive element of an s-dimensional //!(s = X::dimension()) vector at each invocation. When all elements are //!exhausted, X::operator() begins anew with the starting element of a //!subsequent s-dimensional vector. //! - //!Throws: overflow_error. + //!Throws: range_error. result_type operator()() { return curr_elem != dimension() ? load_cached(): next_state(); @@ -70,53 +79,64 @@ public: *first = this->operator()(); } - //!Requirements: *this is mutable. - //! //!Effects: Advances *this state as if z consecutive //!X::operator() invocations were executed. //! - //!Throws: overflow_error. - void discard(std::size_t z) + //!Throws: range_error. + void discard(boost::uintmax_t z) { const std::size_t dimension_value = dimension(); - std::size_t vec_n = z / dimension_value; - std::size_t elem_n = z - vec_n * dimension_value; // z % Dimension - std::size_t vec_offset = vec_n + (curr_elem + elem_n) / dimension_value; - // Discards vec_offset consecutive s-dimensional vectors - discard_vector(vec_offset); + // Compiler knows how to optimize subsequent x / y and x % y + // statements. In fact, gcc does this even at -O1, so don't + // be tempted to "optimize" % via subtraction and multiplication. + + boost::uintmax_t vec_n = z / dimension_value; + std::size_t carry = curr_elem + (z % dimension_value); + + vec_n += carry / dimension_value; + carry = carry % dimension_value; + + // Avoid overdiscarding by branchlessly correcting the triple + // (D, S + 1, 0) to (D, S, D) (see equality operator) + const bool corr = (!carry) & static_cast(vec_n); + + // Discards vec_n (with correction) consecutive s-dimensional vectors + discard_vector(vec_n - static_cast(corr)); // Sets up the proper position of the element-to-read - curr_elem += (z - dimension_value * vec_offset); + // curr_elem = carry + corr*dimension_value + curr_elem = carry ^ (-static_cast(corr) & dimension_value); } - //!Writes a @c DerivedT to a @c std::ostream. - BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, DerivedT, s) + //!Writes the textual representation of the generator to a @c std::ostream. + BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, qrng_base, s) { os << s.dimension() << " " << s.seq_count << " " << s.curr_elem; return os; } - //!Reads a @c DerivedT from a @c std::istream. - BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, DerivedT, s) + //!Reads the textual representation of the generator from a @c std::istream. + BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, qrng_base, s) { - std::size_t dim, seed, z; + std::size_t dim; + size_type seed; + boost::uintmax_t z; if (is >> dim >> std::ws >> seed >> std::ws >> z) // initialize iff success! { - if (s.dimension() != dim) + if (s.dimension() != prevent_zero_dimension(dim)) { - prevent_zero_dimension(dim); s.lattice.resize(dim); s.quasi_state.resize(dim); } // Fast-forward to the correct state - s.seed(seed); - s.discard(z); + s.derived().seed(seed); + if (z != 0) s.discard(z); } return is; } - //!Returns true if the two generators will produce identical sequences. - BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(DerivedT, x, y) + //!Returns true if the two generators will produce identical sequences of outputs. + BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(qrng_base, x, y) { const std::size_t dimension_value = x.dimension(); @@ -126,32 +146,38 @@ public: // and the last one is curr_elem. return (dimension_value == y.dimension()) && + are_close(x.seq_count, y.seq_count, static_cast(1)) && + // Potential overflows don't matter here, since we've already ascertained + // that sequence counts differ by no more than 1, so if they overflow, they + // can overflow together. (x.seq_count + (x.curr_elem / dimension_value) == y.seq_count + (y.curr_elem / dimension_value)) && (x.curr_elem % dimension_value == y.curr_elem % dimension_value); } - //!Returns true if the two generators will produce different sequences, - BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(DerivedT) + //!Returns true if the two generators will produce different sequences of outputs. + BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(qrng_base) protected: - DerivedT& derived() throw() - { - return *static_cast(this); - } + typedef std::vector state_type; + typedef typename state_type::iterator state_iterator; - void reset_state() + // Getters + size_type curr_seq() const { return seq_count; } + + state_iterator state_begin() { return quasi_state.begin(); } + state_iterator state_end() { return quasi_state.end(); } + + // Setters + void reset_seq(size_type seq) { - curr_elem = 0; - seq_count = 0; - std::fill(quasi_state.begin(), quasi_state.end(), result_type /*zero*/()); + seq_count = seq; + curr_elem = 0u; } private: - inline static std::size_t prevent_zero_dimension(std::size_t dimension) + DerivedT& derived() throw() { - if (dimension == 0) - boost::throw_exception( std::invalid_argument("qrng_base: zero dimension") ); - return dimension; + return *static_cast(this); } // Load the result from the saved state. @@ -162,40 +188,65 @@ private: result_type next_state() { - derived().compute_next(); - - curr_elem = 0; - return load_cached(); + size_type new_seq = seq_count; + if (BOOST_LIKELY(++new_seq > seq_count)) + { + derived().compute_seq(new_seq); + reset_seq(new_seq); + return load_cached(); + } + boost::throw_exception( std::range_error("qrng_base: next_state") ); } // Discards z consecutive s-dimensional vectors, // and preserves the position of the element-to-read - void discard_vector(std::size_t z) + void discard_vector(boost::uintmax_t z) { - std::size_t inc_seq_count = seq_count + z; - // Here we check that no overflow occurs before we - // begin seeding the new value - if (inc_seq_count > seq_count) - { - std::size_t tmp = curr_elem; + const size_type max_z = std::numeric_limits::max() - seq_count; - derived().seed(inc_seq_count); + // Don't allow seq_count + z overflows here + if (max_z < z) + boost::throw_exception( std::range_error("qrng_base: discard_vector") ); - curr_elem = tmp; - } - else if (inc_seq_count < seq_count) // Increment overflowed? - { - boost::throw_exception( std::overflow_error("discard_vector") ); - } + std::size_t tmp = curr_elem; + derived().seed(seq_count + z); + curr_elem = tmp; } + static std::size_t prevent_zero_dimension(std::size_t dimension) + { + if (dimension == 0) + boost::throw_exception( std::invalid_argument("qrng_base: zero dimension") ); + return dimension; + } + + // Member variables are so ordered with the intention + // that the typical memory access pattern would be + // incremental. Moreover, lattice is put before quasi_state + // because we want to construct lattice first. Lattices + // can do some kind of dimension sanity check (as in + // dimension_assert below), and if that fails then we don't + // need to do any more work. +private: + std::size_t curr_elem; + size_type seq_count; protected: LatticeT lattice; - std::size_t curr_elem; - std::size_t seq_count; - std::vector quasi_state; +private: + state_type quasi_state; }; +inline void dimension_assert(const char* generator, std::size_t dim, std::size_t maxdim) +{ + if (!dim || dim > maxdim) + { + std::ostringstream os; + os << "The " << generator << " quasi-random number generator only supports dimensions in range [1; " + << maxdim << "], but dimension " << dim << " was supplied."; + boost::throw_exception( std::invalid_argument(os.str()) ); + } +} + }} // namespace detail::random } // namespace boost diff --git a/include/boost/random/detail/sobol_table.hpp b/include/boost/random/detail/sobol_table.hpp new file mode 100644 index 0000000..f4b368b --- /dev/null +++ b/include/boost/random/detail/sobol_table.hpp @@ -0,0 +1,4106 @@ +/* boost random/detail/sobol_table.hpp header file + * + * Copyright Justinas Vygintas Daugmaudis 2010-2018 + * 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) + */ + +#ifndef BOOST_RANDOM_DETAIL_SOBOL_TABLE_HPP +#define BOOST_RANDOM_DETAIL_SOBOL_TABLE_HPP + +#include + +namespace boost { +namespace random { + +namespace detail { +namespace qrng_tables { + +// Maximum allowed space dimension +#define BOOST_RANDOM_SOBOL_MAX_DIMENSION 3667 + +// Data on the primitive binary polynomials (a) and the corresponding +// starting values m, for Sobol sequences in up to 21201 dimensions, +// taken from: +// S. Joe and F. Y. Kuo, Constructing Sobol sequences with better two-dimensional projections, +// SIAM J. Sci. Comput. 30, 2635-2654 (2008). +// and were derived from the file new-joe-kuo-6.21201 provided on F. Kuo's website +// https://web.archive.org/web/20170817015227/http://web.maths.unsw.edu.au/~fkuo/sobol/ +// +// The tables were cut-off at 3667 dimensions for practical reasons. Full 21201 dimension +// table would result in a header in 1.7Mb range. Here we cut-off the full table to the +// polynomial that still fits to 2^16-1, i.e., to unsigned short. This gives us respectable 3667 +// dimensions and sizes down the header to around 230Kb. +struct sobol +{ + BOOST_STATIC_CONSTANT(unsigned int, max_dimension = BOOST_RANDOM_SOBOL_MAX_DIMENSION); + BOOST_STATIC_CONSTANT(unsigned int, num_polynomials = max_dimension - 1); + + // log2(polynomial(num_polynomials - 1)), i.e., integer log2 of the last polynomial in the table + BOOST_STATIC_CONSTANT(unsigned int, max_degree = 15); + + typedef unsigned short value_type; + + static value_type polynomial(std::size_t n) + { + // successive primitive binary-coefficient polynomials p(z) + // = a_0 + a_1 z + a_2 z^2 + ... a_31 z^31, where a_i is the + // i-th bit of sobol_a[j] for the j-th polynomial. + static const value_type sobol_a[num_polynomials] = { + 3,7,11,13,19,25,37,41,47,55, + 59,61,67,91,97,103,109,115,131,137, + 143,145,157,167,171,185,191,193,203,211, + 213,229,239,241,247,253,285,299,301,333, + 351,355,357,361,369,391,397,425,451,463, + 487,501,529,539,545,557,563,601,607,617, + 623,631,637,647,661,675,677,687,695,701, + 719,721,731,757,761,787,789,799,803,817, + 827,847,859,865,875,877,883,895,901,911, + 949,953,967,971,973,981,985,995,1001,1019, + 1033,1051,1063,1069,1125,1135,1153,1163,1221,1239, + 1255,1267,1279,1293,1305,1315,1329,1341,1347,1367, + 1387,1413,1423,1431,1441,1479,1509,1527,1531,1555, + 1557,1573,1591,1603,1615,1627,1657,1663,1673,1717, + 1729,1747,1759,1789,1815,1821,1825,1849,1863,1869, + 1877,1881,1891,1917,1933,1939,1969,2011,2035,2041, + 2053,2071,2091,2093,2119,2147,2149,2161,2171,2189, + 2197,2207,2217,2225,2255,2257,2273,2279,2283,2293, + 2317,2323,2341,2345,2363,2365,2373,2377,2385,2395, + 2419,2421,2431,2435,2447,2475,2477,2489,2503,2521, + 2533,2551,2561,2567,2579,2581,2601,2633,2657,2669, + 2681,2687,2693,2705,2717,2727,2731,2739,2741,2773, + 2783,2793,2799,2801,2811,2819,2825,2833,2867,2879, + 2881,2891,2905,2911,2917,2927,2941,2951,2955,2963, + 2965,2991,2999,3005,3017,3035,3037,3047,3053,3083, + 3085,3097,3103,3159,3169,3179,3187,3205,3209,3223, + 3227,3229,3251,3263,3271,3277,3283,3285,3299,3305, + 3319,3331,3343,3357,3367,3373,3393,3399,3413,3417, + 3427,3439,3441,3475,3487,3497,3515,3517,3529,3543, + 3547,3553,3559,3573,3589,3613,3617,3623,3627,3635, + 3641,3655,3659,3669,3679,3697,3707,3709,3713,3731, + 3743,3747,3771,3791,3805,3827,3833,3851,3865,3889, + 3895,3933,3947,3949,3957,3971,3985,3991,3995,4007, + 4013,4021,4045,4051,4069,4073,4179,4201,4219,4221, + 4249,4305,4331,4359,4383,4387,4411,4431,4439,4449, + 4459,4485,4531,4569,4575,4621,4663,4669,4711,4723, + 4735,4793,4801,4811,4879,4893,4897,4921,4927,4941, + 4977,5017,5027,5033,5127,5169,5175,5199,5213,5223, + 5237,5287,5293,5331,5391,5405,5453,5523,5573,5591, + 5597,5611,5641,5703,5717,5721,5797,5821,5909,5913, + 5955,5957,6005,6025,6061,6067,6079,6081,6231,6237, + 6289,6295,6329,6383,6427,6453,6465,6501,6523,6539, + 6577,6589,6601,6607,6631,6683,6699,6707,6761,6795, + 6865,6881,6901,6923,6931,6943,6999,7057,7079,7103, + 7105,7123,7173,7185,7191,7207,7245,7303,7327,7333, + 7355,7365,7369,7375,7411,7431,7459,7491,7505,7515, + 7541,7557,7561,7701,7705,7727,7749,7761,7783,7795, + 7823,7907,7953,7963,7975,8049,8089,8123,8125,8137, + 8219,8231,8245,8275,8293,8303,8331,8333,8351,8357, + 8367,8379,8381,8387,8393,8417,8435,8461,8469,8489, + 8495,8507,8515,8551,8555,8569,8585,8599,8605,8639, + 8641,8647,8653,8671,8675,8689,8699,8729,8741,8759, + 8765,8771,8795,8797,8825,8831,8841,8855,8859,8883, + 8895,8909,8943,8951,8955,8965,8999,9003,9031,9045, + 9049,9071,9073,9085,9095,9101,9109,9123,9129,9137, + 9143,9147,9185,9197,9209,9227,9235,9247,9253,9257, + 9277,9297,9303,9313,9325,9343,9347,9371,9373,9397, + 9407,9409,9415,9419,9443,9481,9495,9501,9505,9517, + 9529,9555,9557,9571,9585,9591,9607,9611,9621,9625, + 9631,9647,9661,9669,9679,9687,9707,9731,9733,9745, + 9773,9791,9803,9811,9817,9833,9847,9851,9863,9875, + 9881,9905,9911,9917,9923,9963,9973,10003,10025,10043, + 10063,10071,10077,10091,10099,10105,10115,10129,10145,10169, + 10183,10187,10207,10223,10225,10247,10265,10271,10275,10289, + 10299,10301,10309,10343,10357,10373,10411,10413,10431,10445, + 10453,10463,10467,10473,10491,10505,10511,10513,10523,10539, + 10549,10559,10561,10571,10581,10615,10621,10625,10643,10655, + 10671,10679,10685,10691,10711,10739,10741,10755,10767,10781, + 10785,10803,10805,10829,10857,10863,10865,10875,10877,10917, + 10921,10929,10949,10967,10971,10987,10995,11009,11029,11043, + 11045,11055,11063,11075,11081,11117,11135,11141,11159,11163, + 11181,11187,11225,11237,11261,11279,11297,11307,11309,11327, + 11329,11341,11377,11403,11405,11413,11427,11439,11453,11461, + 11473,11479,11489,11495,11499,11533,11545,11561,11567,11575, + 11579,11589,11611,11623,11637,11657,11663,11687,11691,11701, + 11747,11761,11773,11783,11795,11797,11817,11849,11855,11867, + 11869,11873,11883,11919,11921,11927,11933,11947,11955,11961, + 11999,12027,12029,12037,12041,12049,12055,12095,12097,12107, + 12109,12121,12127,12133,12137,12181,12197,12207,12209,12239, + 12253,12263,12269,12277,12287,12295,12309,12313,12335,12361, + 12367,12391,12409,12415,12433,12449,12469,12479,12481,12499, + 12505,12517,12527,12549,12559,12597,12615,12621,12639,12643, + 12657,12667,12707,12713,12727,12741,12745,12763,12769,12779, + 12781,12787,12799,12809,12815,12829,12839,12857,12875,12883, + 12889,12901,12929,12947,12953,12959,12969,12983,12987,12995, + 13015,13019,13031,13063,13077,13103,13137,13149,13173,13207, + 13211,13227,13241,13249,13255,13269,13283,13285,13303,13307, + 13321,13339,13351,13377,13389,13407,13417,13431,13435,13447, + 13459,13465,13477,13501,13513,13531,13543,13561,13581,13599, + 13605,13617,13623,13637,13647,13661,13677,13683,13695,13725, + 13729,13753,13773,13781,13785,13795,13801,13807,13825,13835, + 13855,13861,13871,13883,13897,13905,13915,13939,13941,13969, + 13979,13981,13997,14027,14035,14037,14051,14063,14085,14095, + 14107,14113,14125,14137,14145,14151,14163,14193,14199,14219, + 14229,14233,14243,14277,14287,14289,14295,14301,14305,14323, + 14339,14341,14359,14365,14375,14387,14411,14425,14441,14449, + 14499,14513,14523,14537,14543,14561,14579,14585,14593,14599, + 14603,14611,14641,14671,14695,14701,14723,14725,14743,14753, + 14759,14765,14795,14797,14803,14831,14839,14845,14855,14889, + 14895,14909,14929,14941,14945,14951,14963,14965,14985,15033, + 15039,15053,15059,15061,15071,15077,15081,15099,15121,15147, + 15149,15157,15167,15187,15193,15203,15205,15215,15217,15223, + 15243,15257,15269,15273,15287,15291,15313,15335,15347,15359, + 15373,15379,15381,15391,15395,15397,15419,15439,15453,15469, + 15491,15503,15517,15527,15531,15545,15559,15593,15611,15613, + 15619,15639,15643,15649,15661,15667,15669,15681,15693,15717, + 15721,15741,15745,15765,15793,15799,15811,15825,15835,15847, + 15851,15865,15877,15881,15887,15899,15915,15935,15937,15955, + 15973,15977,16011,16035,16061,16069,16087,16093,16097,16121, + 16141,16153,16159,16165,16183,16189,16195,16197,16201,16209, + 16215,16225,16259,16265,16273,16299,16309,16355,16375,16381, + 16427,16441,16467,16479,16507,16553,16559,16571,16573,16591, + 16619,16627,16653,16659,16699,16707,16795,16797,16807,16813, + 16821,16853,16857,16881,16909,16983,16993,17023,17029,17053, + 17095,17099,17101,17123,17129,17135,17161,17185,17215,17277, + 17287,17301,17327,17353,17387,17389,17419,17475,17523,17619, + 17621,17631,17635,17659,17707,17721,17753,17775,17817,17823, + 17829,17847,17861,17879,17895,17907,17919,17935,17949,17959, + 17973,17991,18009,18019,18033,18043,18085,18117,18127,18139, + 18225,18255,18303,18343,18369,18405,18409,18415,18451,18457, + 18491,18499,18523,18529,18535,18559,18563,18659,18717,18733, + 18745,18793,18807,18823,18857,18895,18913,18997,19045,19067, + 19073,19079,19083,19107,19145,19165,19193,19255,19273,19291, + 19307,19309,19315,19321,19333,19351,19361,19371,19385,19403, + 19405,19413,19423,19441,19451,19465,19485,19519,19527,19531, + 19541,19581,19597,19621,19645,19653,19665,19671,19693,19743, + 19761,19781,19791,19793,19829,19855,19885,19891,19905,19963, + 19969,19989,20023,20035,20041,20049,20075,20077,20099,20123, + 20179,20197,20201,20207,20253,20309,20319,20329,20335,20383, + 20393,20407,20411,20459,20487,20511,20517,20573,20641,20693, + 20713,20781,20819,20825,20831,20861,20875,20889,20901,20913, + 20945,20955,20971,20973,20981,20991,20997,21007,21037,21093, + 21131,21145,21155,21169,21187,21189,21201,21223,21285,21289, + 21339,21403,21405,21415,21433,21439,21447,21489,21507,21519, + 21527,21557,21561,21575,21599,21627,21645,21663,21691,21725, + 21729,21785,21807,21815,21881,21887,21891,21893,21905,21933, + 21953,21971,21993,22007,22029,22037,22057,22063,22065,22171, + 22187,22189,22195,22209,22215,22221,22263,22315,22317,22335, + 22361,22371,22397,22419,22447,22461,22467,22469,22487,22531, + 22561,22579,22581,22591,22593,22677,22681,22691,22703,22749, + 22759,22763,22783,22863,22911,22927,22935,22941,22945,22951, + 22965,23007,23017,23071,23077,23099,23101,23107,23109,23113, + 23157,23221,23233,23251,23253,23257,23311,23319,23339,23353, + 23395,23401,23415,23449,23491,23493,23521,23531,23559,23563, + 23577,23601,23625,23645,23673,23683,23713,23743,23745,23755, + 23757,23781,23813,23837,23859,23919,23949,23957,23971,23977, + 23995,24015,24067,24079,24091,24109,24135,24189,24193,24217, + 24279,24283,24295,24309,24327,24345,24355,24381,24387,24389, + 24417,24427,24437,24471,24543,24589,24597,24623,24637,24679, + 24683,24713,24733,24747,24755,24761,24789,24841,24849,24877, + 24889,24897,24957,24991,24997,25007,25019,25069,25077,25139, + 25187,25199,25213,25229,25247,25253,25257,25271,25303,25307, + 25309,25331,25379,25393,25399,25435,25453,25461,25481,25489, + 25505,25535,25583,25609,25623,25665,25671,25739,25759,25831, + 25845,25857,25867,25911,25915,25925,25947,26001,26029,26041, + 26047,26069,26095,26103,26119,26125,26147,26171,26205,26219, + 26243,26263,26279,26283,26293,26329,26335,26385,26395,26443, + 26463,26473,26487,26497,26531,26577,26641,26653,26707,26743, + 26771,26783,26789,26793,26821,26879,26905,26927,26987,26995, + 27023,27037,27041,27051,27113,27137,27183,27217,27227,27239, + 27243,27245,27253,27267,27287,27315,27317,27327,27339,27369, + 27375,27395,27415,27435,27443,27449,27463,27467,27497,27517, + 27521,27533,27575,27589,27607,27617,27629,27641,27695,27709, + 27735,27763,27829,27833,27841,27847,27877,27913,27927,27947, + 27987,28003,28005,28009,28067,28081,28091,28093,28101,28169, + 28199,28205,28211,28225,28243,28283,28289,28295,28309,28335, + 28355,28379,28381,28409,28417,28437,28457,28465,28475,28495, + 28503,28561,28615,28633,28639,28649,28677,28701,28723,28797, + 28841,28859,28873,28879,28897,28947,28949,28953,28977,28983, + 28989,29035,29083,29089,29109,29151,29157,29175,29179,29215, + 29233,29243,29263,29287,29363,29377,29389,29407,29413,29425, + 29431,29443,29449,29479,29483,29581,29587,29605,29629,29649, + 29695,29715,29717,29775,29787,29803,29805,29867,29875,29901, + 29919,29929,29949,29979,29985,30071,30075,30105,30115,30141, + 30159,30161,30187,30197,30265,30279,30291,30293,30303,30307, + 30313,30367,30371,30383,30417,30443,30457,30475,30537,30551, + 30573,30579,30631,30645,30663,30675,30677,30741,30757,30769, + 30781,30829,30923,30925,30937,30959,30999,31015,31053,31065, + 31087,31089,31099,31105,31111,31153,31177,31191,31197,31235, + 31259,31275,31285,31295,31307,31317,31361,31373,31415,31419, + 31427,31457,31477,31523,31567,31569,31581,31609,31631,31649, + 31659,31673,31699,31715,31729,31749,31783,31789,31833,31883, + 31891,31893,31907,31927,31939,31953,31993,31999,32001,32021, + 32055,32069,32115,32121,32145,32151,32167,32179,32199,32205, + 32233,32251,32253,32269,32281,32303,32353,32373,32383,32413, + 32427,32467,32483,32485,32521,32545,32575,32589,32597,32625, + 32651,32653,32671,32709,32721,32743,32771,32785,32791,32813, + 32821,32863,32887,32897,32903,32915,32933,32963,32975,32989, + 32999,33013,33025,33045,33061,33111,33117,33121,33133,33157, + 33185,33191,33209,33227,33229,33247,33277,33299,33339,33349, + 33407,33417,33423,33435,33483,33497,33559,33563,33579,33587, + 33607,33613,33631,33635,33641,33649,33675,33689,33711,33725, + 33733,33745,33817,33827,33839,33841,33847,33895,33901,33913, + 33923,33943,33953,33973,34015,34039,34045,34077,34081,34087, + 34099,34119,34123,34143,34161,34171,34177,34189,34211,34225, + 34245,34249,34267,34285,34291,34313,34321,34333,34347,34389, + 34393,34405,34429,34433,34473,34479,34487,34499,34523,34559, + 34571,34573,34581,34601,34609,34667,34693,34697,34703,34731, + 34733,34739,34751,34783,34801,34817,34871,34889,34909,34913, + 34937,34947,34959,34997,35015,35033,35077,35081,35095,35111, + 35173,35225,35247,35279,35281,35293,35309,35327,35385,35413, + 35427,35429,35441,35451,35463,35467,35487,35503,35505,35549, + 35595,35597,35643,35651,35693,35699,35729,35741,35777,35787, + 35797,35813,35825,35873,35879,35911,35925,35939,35945,35975, + 35987,36003,36009,36027,36041,36065,36103,36107,36133,36163, + 36177,36187,36223,36229,36233,36251,36257,36287,36299,36301, + 36325,36329,36335,36363,36383,36411,36433,36439,36467,36469, + 36495,36503,36507,36513,36543,36545,36563,36581,36603,36623, + 36647,36651,36665,36709,36727,36733,36773,36809,36817,36833, + 36875,36889,36895,36901,36919,36925,36931,36951,36961,36973, + 36981,37001,37009,37019,37037,37125,37129,37143,37147,37149, + 37185,37197,37243,37273,37283,37289,37297,37309,37327,37345, + 37379,37393,37403,37415,37427,37439,37453,37459,37499,37511, + 37525,37539,37559,37577,37597,37621,37625,37651,37681,37701, + 37705,37719,37747,37759,37763,37789,37793,37813,37835,37855, + 37871,37873,37883,37903,37931,37941,37963,37971,38013,38035, + 38041,38053,38057,38075,38103,38107,38113,38119,38133,38143, + 38151,38165,38185,38193,38205,38213,38241,38251,38281,38299, + 38317,38367,38377,38419,38421,38449,38455,38461,38467,38503, + 38521,38551,38573,38593,38603,38623,38651,38699,38709,38733, + 38755,38805,38815,38819,38821,38825,38833,38875,38877,38899, + 38911,38921,38945,38983,39061,39065,39087,39099,39109,39127, + 39133,39179,39193,39205,39209,39215,39223,39235,39237,39277, + 39295,39305,39313,39323,39353,39359,39361,39371,39381,39395, + 39461,39503,39511,39515,39517,39521,39533,39545,39551,39575, + 39581,39595,39609,39623,39651,39675,39697,39707,39731,39745, + 39763,39775,39791,39799,39819,39827,39863,39869,39915,39935, + 39957,39983,39995,40017,40029,40039,40053,40057,40069,40127, + 40149,40165,40177,40183,40195,40277,40281,40291,40321,40331, + 40345,40351,40357,40381,40451,40465,40471,40481,40505,40519, + 40533,40537,40547,40553,40607,40611,40685,40691,40715,40723, + 40739,40751,40777,40783,40807,40859,40877,40883,40885,40909, + 40971,40995,40997,41007,41027,41051,41053,41063,41067,41069, + 41097,41105,41141,41165,41183,41211,41219,41231,41245,41255, + 41267,41269,41273,41287,41327,41339,41345,41375,41393,41413, + 41423,41441,41487,41537,41543,41571,41583,41625,41641,41669, + 41673,41687,41691,41709,41735,41739,41741,41753,41763,41797, + 41835,41843,41861,41871,41879,41889,41907,41921,41933,41941, + 41987,41989,41993,42067,42073,42113,42123,42137,42149,42159, + 42161,42173,42179,42203,42221,42241,42275,42277,42281,42319, + 42371,42407,42425,42445,42473,42481,42515,42543,42551,42577, + 42593,42611,42641,42651,42653,42695,42737,42749,42779,42795, + 42809,42847,42865,42893,42929,42939,42941,42959,42961,42973, + 42983,43051,43059,43065,43083,43085,43093,43113,43133,43137, + 43155,43167,43171,43177,43191,43215,43229,43233,43275,43283, + 43289,43337,43381,43431,43437,43497,43503,43511,43533,43541, + 43567,43569,43587,43599,43601,43617,43641,43677,43693,43705, + 43731,43779,43791,43805,43829,43833,43847,43875,43915,43929, + 43963,43973,43985,43991,43995,44019,44033,44039,44045,44073, + 44087,44123,44141,44147,44165,44175,44183,44231,44245,44255, + 44265,44285,44293,44305,44315,44321,44399,44451,44463,44489, + 44509,44519,44523,44537,44553,44573,44589,44601,44607,44639, + 44643,44657,44663,44685,44693,44707,44731,44759,44765,44775, + 44789,44801,44819,44831,44841,44847,44859,44867,44873,44903, + 44917,44943,44971,45011,45027,45053,45071,45083,45101,45109, + 45119,45141,45175,45203,45231,45251,45253,45265,45281,45299, + 45319,45323,45373,45399,45405,45429,45455,45463,45469,45473, + 45511,45535,45541,45579,45587,45589,45635,45641,45647,45695, + 45705,45723,45761,45791,45801,45807,45815,45829,45847,45863, + 45947,45953,45971,45989,46001,46007,46021,46039,46043,46045, + 46073,46081,46093,46147,46167,46189,46197,46207,46247,46271, + 46319,46327,46345,46365,46399,46407,46419,46421,46441,46455, + 46459,46485,46505,46523,46531,46551,46561,46567,46571,46585, + 46597,46601,46615,46619,46625,46631,46637,46643,46645,46667, + 46681,46715,46721,46731,46745,46767,46801,46823,46827,46879, + 46885,46917,46935,46955,46969,46979,46993,47005,47009,47027, + 47101,47183,47201,47221,47237,47241,47261,47265,47277,47295, + 47315,47317,47355,47363,47389,47399,47403,47431,47445,47449, + 47461,47479,47501,47535,47547,47555,47561,47569,47597,47603, + 47621,47633,47673,47705,47745,47751,47757,47763,47799,47831, + 47873,47893,47897,47907,47933,47939,47945,47953,47963,47975, + 47989,48017,48053,48063,48075,48077,48101,48105,48137,48179, + 48233,48251,48267,48269,48287,48297,48323,48349,48403,48421, + 48431,48487,48511,48515,48521,48569,48577,48595,48601,48613, + 48661,48675,48681,48695,48727,48731,48737,48747,48767,48771, + 48811,48881,48929,48935,48947,48949,48997,49025,49035,49059, + 49079,49091,49133,49141,49151,49153,49159,49171,49183,49189, + 49225,49267,49273,49285,49303,49309,49319,49337,49355,49365, + 49379,49403,49425,49441,49459,49471,49503,49527,49531,49533, + 49555,49573,49597,49603,49609,49627,49639,49645,49669,49673, + 49687,49709,49741,49749,49769,49817,49841,49873,49885,49909, + 49921,49933,49957,49981,50007,50011,50017,50035,50051,50075, + 50077,50093,50119,50147,50159,50173,50181,50209,50227,50247, + 50251,50271,50287,50301,50323,50335,50341,50359,50373,50397, + 50411,50425,50431,50443,50453,50479,50481,50505,50523,50549, + 50553,50569,50587,50593,50611,50613,50623,50655,50665,50671, + 50685,50737,50757,50769,50795,50805,50809,50831,50839,50859, + 50873,50881,50887,50901,50921,50947,51027,51033,51063,51097, + 51103,51139,51159,51163,51189,51203,51227,51265,51277,51295, + 51301,51305,51349,51389,51401,51445,51449,51455,51457,51469, + 51477,51487,51491,51497,51505,51511,51515,51547,51549,51587, + 51655,51659,51661,51673,51749,51753,51759,51785,51815,51855, + 51885,51903,51929,51939,51951,51991,51995,51997,52011,52031, + 52053,52081,52091,52103,52157,52199,52213,52245,52259,52285, + 52297,52333,52351,52355,52357,52379,52385,52391,52403,52417, + 52441,52471,52475,52477,52523,52531,52615,52639,52643,52677, + 52687,52695,52705,52715,52717,52729,52735,52739,52775,52789, + 52837,52849,52895,52923,52931,52933,52937,52945,52951,52979, + 52991,53005,53023,53039,53107,53113,53135,53149,53153,53191, + 53205,53225,53239,53253,53257,53311,53325,53361,53367,53383, + 53387,53389,53397,53401,53411,53425,53445,53455,53457,53463, + 53473,53497,53515,53541,53551,53565,53585,53595,53613,53659, + 53689,53695,53697,53717,53721,53743,53757,53767,53781,53795, + 53801,53815,53847,53867,53869,53903,53921,54019,54039,54055, + 54081,54111,54121,54135,54139,54145,54163,54169,54193,54217, + 54225,54237,54247,54293,54313,54331,54369,54379,54423,54429, + 54443,54451,54463,54465,54483,54501,54505,54513,54543,54567, + 54571,54599,54617,54627,54653,54711,54753,54759,54773,54789, + 54823,54827,54859,54883,54909,54953,54967,54981,54999,55009, + 55021,55075,55149,55167,55213,55219,55221,55231,55257,55287, + 55291,55309,55315,55369,55383,55405,55433,55439,55451,55463, + 55477,55489,55507,55513,55525,55561,55579,55603,55617,55623, + 55629,55647,55653,55665,55691,55705,55711,55715,55721,55729, + 55747,55767,55801,55813,55831,55847,55861,55871,55897,55933, + 55947,55955,55971,55985,56003,56029,56095,56101,56105,56123, + 56133,56143,56161,56195,56225,56263,56269,56277,56287,56291, + 56297,56303,56363,56377,56385,56431,56433,56467,56479,56495, + 56529,56535,56539,56565,56601,56617,56625,56663,56679,56691, + 56693,56733,56749,56789,56805,56823,56827,56839,56879,56893, + 56905,56911,56913,56941,56963,56965,56969,56993,57005,57035, + 57037,57043,57091,57093,57111,57117,57139,57177,57193,57199, + 57201,57275,57289,57323,57347,57359,57397,57415,57419,57439, + 57467,57485,57513,57521,57527,57541,57559,57601,57611,57649, + 57673,57679,57681,57693,57703,57727,57779,57811,57839,57863, + 57881,57891,57905,57925,57935,57959,57977,57989,58011,58013, + 58017,58027,58029,58047,58049,58069,58127,58129,58165,58201, + 58211,58213,58231,58253,58259,58271,58287,58295,58307,58331, + 58355,58367,58399,58417,58441,58459,58475,58477,58483,58501, + 58513,58519,58525,58529,58539,58571,58573,58609,58621,58627, + 58647,58651,58669,58675,58753,58773,58789,58885,58913,58937, + 58943,58951,58963,58985,59015,59067,59069,59095,59101,59125, + 59129,59137,59177,59245,59253,59267,59279,59307,59309,59317, + 59339,59347,59365,59383,59393,59439,59459,59483,59501,59513, + 59529,59537,59559,59583,59585,59595,59597,59603,59643,59651, + 59663,59681,59687,59691,59701,59737,59743,59747,59753,59761, + 59789,59831,59845,59855,59863,59913,59931,59949,59979,59993, + 60017,60029,60033,60045,60091,60099,60105,60141,60167,60171, + 60185,60201,60219,60229,60253,60263,60267,60275,60277,60311, + 60315,60333,60339,60365,60373,60387,60425,60433,60449,60469, + 60491,60517,60521,60541,60563,60569,60599,60623,60671,60679, + 60693,60707,60727,60745,60765,60769,60779,60823,60843,60871, + 60877,60889,60895,60911,60925,60929,60939,60941,60959,61045, + 61059,61085,61101,61127,61131,61145,61155,61169,61175,61199, + 61217,61229,61235,61241,61261,61303,61333,61343,61371,61415, + 61419,61427,61447,61453,61471,61481,61487,61509,61573,61591, + 61611,61631,61639,61653,61663,61681,61687,61713,61723,61749, + 61761,61771,61779,61795,61809,61837,61893,61921,61927,61939, + 61941,61981,62023,62029,62037,62041,62063,62075,62087,62111, + 62117,62171,62201,62207,62209,62219,62229,62255,62263,62341, + 62345,62353,62359,62387,62431,62437,62469,62479,62487,62497, + 62521,62547,62549,62565,62587,62603,62617,62627,62653,62671, + 62707,62709,62713,62733,62745,62757,62779,62801,62817,62829, + 62865,62877,62901,62911,62913,62919,63007,63011,63035,63045, + 63055,63109,63157,63193,63215,63227,63277,63295,63309,63315, + 63343,63367,63371,63381,63395,63409,63415,63427,63433,63451, + 63487,63491,63497,63503,63527,63551,63599,63601,63607,63635, + 63707,63725,63731,63733,63765,63779,63803,63805,63823,63825, + 63859,63865,63877,63899,63923,63929,63943,63971,63977,63991, + 64001,64007,64019,64035,64117,64131,64151,64155,64161,64193, + 64203,64217,64223,64229,64261,64271,64289,64309,64333,64351, + 64361,64385,64397,64419,64425,64439,64457,64463,64475,64481, + 64523,64525,64543,64585,64603,64615,64629,64643,64685,64723, + 64751,64783,64791,64797,64811,64813,64825,64839,64851,64881, + 64907,64921,64931,64943,64945,64989,64993,65003,65069,65075, + 65089,65101,65113,65149,65159,65177,65201,65213,65225,65259, + 65279,65299,65315,65321,65335,65359,65377,65395,65407,65425, + 65459,65479,65497,65513,65519,65533 }; + + return sobol_a[n]; + } + + static value_type minit(std::size_t dim, std::size_t degree) + { + // starting direction #'s m[i] = sobol_minit[i][j] for i=0..d of the + // degree-d primitive polynomial sobol_a[j]. + static const value_type sobol_minit[max_degree * num_polynomials] = { + 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,3,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,3,1,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,3,3,0,0,0,0,0,0,0,0,0,0,0, + 1,3,5,13,0,0,0,0,0,0,0,0,0,0,0, + 1,1,5,5,17,0,0,0,0,0,0,0,0,0,0, + 1,1,5,5,5,0,0,0,0,0,0,0,0,0,0, + 1,1,7,11,19,0,0,0,0,0,0,0,0,0,0, + 1,1,5,1,1,0,0,0,0,0,0,0,0,0,0, + 1,1,1,3,11,0,0,0,0,0,0,0,0,0,0, + 1,3,5,5,31,0,0,0,0,0,0,0,0,0,0, + 1,3,3,9,7,49,0,0,0,0,0,0,0,0,0, + 1,1,1,15,21,21,0,0,0,0,0,0,0,0,0, + 1,3,1,13,27,49,0,0,0,0,0,0,0,0,0, + 1,1,1,15,7,5,0,0,0,0,0,0,0,0,0, + 1,3,1,15,13,25,0,0,0,0,0,0,0,0,0, + 1,1,5,5,19,61,0,0,0,0,0,0,0,0,0, + 1,3,7,11,23,15,103,0,0,0,0,0,0,0,0, + 1,3,7,13,13,15,69,0,0,0,0,0,0,0,0, + 1,1,3,13,7,35,63,0,0,0,0,0,0,0,0, + 1,3,5,9,1,25,53,0,0,0,0,0,0,0,0, + 1,3,1,13,9,35,107,0,0,0,0,0,0,0,0, + 1,3,1,5,27,61,31,0,0,0,0,0,0,0,0, + 1,1,5,11,19,41,61,0,0,0,0,0,0,0,0, + 1,3,5,3,3,13,69,0,0,0,0,0,0,0,0, + 1,1,7,13,1,19,1,0,0,0,0,0,0,0,0, + 1,3,7,5,13,19,59,0,0,0,0,0,0,0,0, + 1,1,3,9,25,29,41,0,0,0,0,0,0,0,0, + 1,3,5,13,23,1,55,0,0,0,0,0,0,0,0, + 1,3,7,3,13,59,17,0,0,0,0,0,0,0,0, + 1,3,1,3,5,53,69,0,0,0,0,0,0,0,0, + 1,1,5,5,23,33,13,0,0,0,0,0,0,0,0, + 1,1,7,7,1,61,123,0,0,0,0,0,0,0,0, + 1,1,7,9,13,61,49,0,0,0,0,0,0,0,0, + 1,3,3,5,3,55,33,0,0,0,0,0,0,0,0, + 1,3,1,15,31,13,49,245,0,0,0,0,0,0,0, + 1,3,5,15,31,59,63,97,0,0,0,0,0,0,0, + 1,3,1,11,11,11,77,249,0,0,0,0,0,0,0, + 1,3,1,11,27,43,71,9,0,0,0,0,0,0,0, + 1,1,7,15,21,11,81,45,0,0,0,0,0,0,0, + 1,3,7,3,25,31,65,79,0,0,0,0,0,0,0, + 1,3,1,1,19,11,3,205,0,0,0,0,0,0,0, + 1,1,5,9,19,21,29,157,0,0,0,0,0,0,0, + 1,3,7,11,1,33,89,185,0,0,0,0,0,0,0, + 1,3,3,3,15,9,79,71,0,0,0,0,0,0,0, + 1,3,7,11,15,39,119,27,0,0,0,0,0,0,0, + 1,1,3,1,11,31,97,225,0,0,0,0,0,0,0, + 1,1,1,3,23,43,57,177,0,0,0,0,0,0,0, + 1,3,7,7,17,17,37,71,0,0,0,0,0,0,0, + 1,3,1,5,27,63,123,213,0,0,0,0,0,0,0, + 1,1,3,5,11,43,53,133,0,0,0,0,0,0,0, + 1,3,5,5,29,17,47,173,479,0,0,0,0,0,0, + 1,3,3,11,3,1,109,9,69,0,0,0,0,0,0, + 1,1,1,5,17,39,23,5,343,0,0,0,0,0,0, + 1,3,1,5,25,15,31,103,499,0,0,0,0,0,0, + 1,1,1,11,11,17,63,105,183,0,0,0,0,0,0, + 1,1,5,11,9,29,97,231,363,0,0,0,0,0,0, + 1,1,5,15,19,45,41,7,383,0,0,0,0,0,0, + 1,3,7,7,31,19,83,137,221,0,0,0,0,0,0, + 1,1,1,3,23,15,111,223,83,0,0,0,0,0,0, + 1,1,5,13,31,15,55,25,161,0,0,0,0,0,0, + 1,1,3,13,25,47,39,87,257,0,0,0,0,0,0, + 1,1,1,11,21,53,125,249,293,0,0,0,0,0,0, + 1,1,7,11,11,7,57,79,323,0,0,0,0,0,0, + 1,1,5,5,17,13,81,3,131,0,0,0,0,0,0, + 1,1,7,13,23,7,65,251,475,0,0,0,0,0,0, + 1,3,5,1,9,43,3,149,11,0,0,0,0,0,0, + 1,1,3,13,31,13,13,255,487,0,0,0,0,0,0, + 1,3,3,1,5,63,89,91,127,0,0,0,0,0,0, + 1,1,3,3,1,19,123,127,237,0,0,0,0,0,0, + 1,1,5,7,23,31,37,243,289,0,0,0,0,0,0, + 1,1,5,11,17,53,117,183,491,0,0,0,0,0,0, + 1,1,1,5,1,13,13,209,345,0,0,0,0,0,0, + 1,1,3,15,1,57,115,7,33,0,0,0,0,0,0, + 1,3,1,11,7,43,81,207,175,0,0,0,0,0,0, + 1,3,1,1,15,27,63,255,49,0,0,0,0,0,0, + 1,3,5,3,27,61,105,171,305,0,0,0,0,0,0, + 1,1,5,3,1,3,57,249,149,0,0,0,0,0,0, + 1,1,3,5,5,57,15,13,159,0,0,0,0,0,0, + 1,1,1,11,7,11,105,141,225,0,0,0,0,0,0, + 1,3,3,5,27,59,121,101,271,0,0,0,0,0,0, + 1,3,5,9,11,49,51,59,115,0,0,0,0,0,0, + 1,1,7,1,23,45,125,71,419,0,0,0,0,0,0, + 1,1,3,5,23,5,105,109,75,0,0,0,0,0,0, + 1,1,7,15,7,11,67,121,453,0,0,0,0,0,0, + 1,3,7,3,9,13,31,27,449,0,0,0,0,0,0, + 1,3,1,15,19,39,39,89,15,0,0,0,0,0,0, + 1,1,1,1,1,33,73,145,379,0,0,0,0,0,0, + 1,3,1,15,15,43,29,13,483,0,0,0,0,0,0, + 1,1,7,3,19,27,85,131,431,0,0,0,0,0,0, + 1,3,3,3,5,35,23,195,349,0,0,0,0,0,0, + 1,3,3,7,9,27,39,59,297,0,0,0,0,0,0, + 1,1,3,9,11,17,13,241,157,0,0,0,0,0,0, + 1,3,7,15,25,57,33,189,213,0,0,0,0,0,0, + 1,1,7,1,9,55,73,83,217,0,0,0,0,0,0, + 1,3,3,13,19,27,23,113,249,0,0,0,0,0,0, + 1,3,5,3,23,43,3,253,479,0,0,0,0,0,0, + 1,1,5,5,11,5,45,117,217,0,0,0,0,0,0, + 1,3,3,7,29,37,33,123,147,0,0,0,0,0,0, + 1,3,1,15,5,5,37,227,223,459,0,0,0,0,0, + 1,1,7,5,5,39,63,255,135,487,0,0,0,0,0, + 1,3,1,7,9,7,87,249,217,599,0,0,0,0,0, + 1,1,3,13,9,47,7,225,363,247,0,0,0,0,0, + 1,3,7,13,19,13,9,67,9,737,0,0,0,0,0, + 1,3,5,5,19,59,7,41,319,677,0,0,0,0,0, + 1,1,5,3,31,63,15,43,207,789,0,0,0,0,0, + 1,1,7,9,13,39,3,47,497,169,0,0,0,0,0, + 1,3,1,7,21,17,97,19,415,905,0,0,0,0,0, + 1,3,7,1,3,31,71,111,165,127,0,0,0,0,0, + 1,1,5,11,1,61,83,119,203,847,0,0,0,0,0, + 1,3,3,13,9,61,19,97,47,35,0,0,0,0,0, + 1,1,7,7,15,29,63,95,417,469,0,0,0,0,0, + 1,3,1,9,25,9,71,57,213,385,0,0,0,0,0, + 1,3,5,13,31,47,101,57,39,341,0,0,0,0,0, + 1,1,3,3,31,57,125,173,365,551,0,0,0,0,0, + 1,3,7,1,13,57,67,157,451,707,0,0,0,0,0, + 1,1,1,7,21,13,105,89,429,965,0,0,0,0,0, + 1,1,5,9,17,51,45,119,157,141,0,0,0,0,0, + 1,3,7,7,13,45,91,9,129,741,0,0,0,0,0, + 1,3,7,1,23,57,67,141,151,571,0,0,0,0,0, + 1,1,3,11,17,47,93,107,375,157,0,0,0,0,0, + 1,3,3,5,11,21,43,51,169,915,0,0,0,0,0, + 1,1,5,3,15,55,101,67,455,625,0,0,0,0,0, + 1,3,5,9,1,23,29,47,345,595,0,0,0,0,0, + 1,3,7,7,5,49,29,155,323,589,0,0,0,0,0, + 1,3,3,7,5,41,127,61,261,717,0,0,0,0,0, + 1,3,7,7,17,23,117,67,129,1009,0,0,0,0,0, + 1,1,3,13,11,39,21,207,123,305,0,0,0,0,0, + 1,1,3,9,29,3,95,47,231,73,0,0,0,0,0, + 1,3,1,9,1,29,117,21,441,259,0,0,0,0,0, + 1,3,1,13,21,39,125,211,439,723,0,0,0,0,0, + 1,1,7,3,17,63,115,89,49,773,0,0,0,0,0, + 1,3,7,13,11,33,101,107,63,73,0,0,0,0,0, + 1,1,5,5,13,57,63,135,437,177,0,0,0,0,0, + 1,1,3,7,27,63,93,47,417,483,0,0,0,0,0, + 1,1,3,1,23,29,1,191,49,23,0,0,0,0,0, + 1,1,3,15,25,55,9,101,219,607,0,0,0,0,0, + 1,3,1,7,7,19,51,251,393,307,0,0,0,0,0, + 1,3,3,3,25,55,17,75,337,3,0,0,0,0,0, + 1,1,1,13,25,17,65,45,479,413,0,0,0,0,0, + 1,1,7,7,27,49,99,161,213,727,0,0,0,0,0, + 1,3,5,1,23,5,43,41,251,857,0,0,0,0,0, + 1,3,3,7,11,61,39,87,383,835,0,0,0,0,0, + 1,1,3,15,13,7,29,7,505,923,0,0,0,0,0, + 1,3,7,1,5,31,47,157,445,501,0,0,0,0,0, + 1,1,3,7,1,43,9,147,115,605,0,0,0,0,0, + 1,3,3,13,5,1,119,211,455,1001,0,0,0,0,0, + 1,1,3,5,13,19,3,243,75,843,0,0,0,0,0, + 1,3,7,7,1,19,91,249,357,589,0,0,0,0,0, + 1,1,1,9,1,25,109,197,279,411,0,0,0,0,0, + 1,3,1,15,23,57,59,135,191,75,0,0,0,0,0, + 1,1,5,15,29,21,39,253,383,349,0,0,0,0,0, + 1,3,3,5,19,45,61,151,199,981,0,0,0,0,0, + 1,3,5,13,9,61,107,141,141,1,0,0,0,0,0, + 1,3,1,11,27,25,85,105,309,979,0,0,0,0,0, + 1,3,3,11,19,7,115,223,349,43,0,0,0,0,0, + 1,1,7,9,21,39,123,21,275,927,0,0,0,0,0, + 1,1,7,13,15,41,47,243,303,437,0,0,0,0,0, + 1,1,1,7,7,3,15,99,409,719,0,0,0,0,0, + 1,3,3,15,27,49,113,123,113,67,469,0,0,0,0, + 1,3,7,11,3,23,87,169,119,483,199,0,0,0,0, + 1,1,5,15,7,17,109,229,179,213,741,0,0,0,0, + 1,1,5,13,11,17,25,135,403,557,1433,0,0,0,0, + 1,3,1,1,1,61,67,215,189,945,1243,0,0,0,0, + 1,1,7,13,17,33,9,221,429,217,1679,0,0,0,0, + 1,1,3,11,27,3,15,93,93,865,1049,0,0,0,0, + 1,3,7,7,25,41,121,35,373,379,1547,0,0,0,0, + 1,3,3,9,11,35,45,205,241,9,59,0,0,0,0, + 1,3,1,7,3,51,7,177,53,975,89,0,0,0,0, + 1,1,3,5,27,1,113,231,299,759,861,0,0,0,0, + 1,3,3,15,25,29,5,255,139,891,2031,0,0,0,0, + 1,3,1,1,13,9,109,193,419,95,17,0,0,0,0, + 1,1,7,9,3,7,29,41,135,839,867,0,0,0,0, + 1,1,7,9,25,49,123,217,113,909,215,0,0,0,0, + 1,1,7,3,23,15,43,133,217,327,901,0,0,0,0, + 1,1,3,3,13,53,63,123,477,711,1387,0,0,0,0, + 1,1,3,15,7,29,75,119,181,957,247,0,0,0,0, + 1,1,1,11,27,25,109,151,267,99,1461,0,0,0,0, + 1,3,7,15,5,5,53,145,11,725,1501,0,0,0,0, + 1,3,7,1,9,43,71,229,157,607,1835,0,0,0,0, + 1,3,3,13,25,1,5,27,471,349,127,0,0,0,0, + 1,1,1,1,23,37,9,221,269,897,1685,0,0,0,0, + 1,1,3,3,31,29,51,19,311,553,1969,0,0,0,0, + 1,3,7,5,5,55,17,39,475,671,1529,0,0,0,0, + 1,1,7,1,1,35,47,27,437,395,1635,0,0,0,0, + 1,1,7,3,13,23,43,135,327,139,389,0,0,0,0, + 1,3,7,3,9,25,91,25,429,219,513,0,0,0,0, + 1,1,3,5,13,29,119,201,277,157,2043,0,0,0,0, + 1,3,5,3,29,57,13,17,167,739,1031,0,0,0,0, + 1,3,3,5,29,21,95,27,255,679,1531,0,0,0,0, + 1,3,7,15,9,5,21,71,61,961,1201,0,0,0,0, + 1,3,5,13,15,57,33,93,459,867,223,0,0,0,0, + 1,1,1,15,17,43,127,191,67,177,1073,0,0,0,0, + 1,1,1,15,23,7,21,199,75,293,1611,0,0,0,0, + 1,3,7,13,15,39,21,149,65,741,319,0,0,0,0, + 1,3,7,11,23,13,101,89,277,519,711,0,0,0,0, + 1,3,7,15,19,27,85,203,441,97,1895,0,0,0,0, + 1,3,1,3,29,25,21,155,11,191,197,0,0,0,0, + 1,1,7,5,27,11,81,101,457,675,1687,0,0,0,0, + 1,3,1,5,25,5,65,193,41,567,781,0,0,0,0, + 1,3,1,5,11,15,113,77,411,695,1111,0,0,0,0, + 1,1,3,9,11,53,119,171,55,297,509,0,0,0,0, + 1,1,1,1,11,39,113,139,165,347,595,0,0,0,0, + 1,3,7,11,9,17,101,13,81,325,1733,0,0,0,0, + 1,3,1,1,21,43,115,9,113,907,645,0,0,0,0, + 1,1,7,3,9,25,117,197,159,471,475,0,0,0,0, + 1,3,1,9,11,21,57,207,485,613,1661,0,0,0,0, + 1,1,7,7,27,55,49,223,89,85,1523,0,0,0,0, + 1,1,5,3,19,41,45,51,447,299,1355,0,0,0,0, + 1,3,1,13,1,33,117,143,313,187,1073,0,0,0,0, + 1,1,7,7,5,11,65,97,377,377,1501,0,0,0,0, + 1,3,1,1,21,35,95,65,99,23,1239,0,0,0,0, + 1,1,5,9,3,37,95,167,115,425,867,0,0,0,0, + 1,3,3,13,1,37,27,189,81,679,773,0,0,0,0, + 1,1,3,11,1,61,99,233,429,969,49,0,0,0,0, + 1,1,1,7,25,63,99,165,245,793,1143,0,0,0,0, + 1,1,5,11,11,43,55,65,71,283,273,0,0,0,0, + 1,1,5,5,9,3,101,251,355,379,1611,0,0,0,0, + 1,1,1,15,21,63,85,99,49,749,1335,0,0,0,0, + 1,1,5,13,27,9,121,43,255,715,289,0,0,0,0, + 1,3,1,5,27,19,17,223,77,571,1415,0,0,0,0, + 1,1,5,3,13,59,125,251,195,551,1737,0,0,0,0, + 1,3,3,15,13,27,49,105,389,971,755,0,0,0,0, + 1,3,5,15,23,43,35,107,447,763,253,0,0,0,0, + 1,3,5,11,21,3,17,39,497,407,611,0,0,0,0, + 1,1,7,13,15,31,113,17,23,507,1995,0,0,0,0, + 1,1,7,15,3,15,31,153,423,79,503,0,0,0,0, + 1,1,7,9,19,25,23,171,505,923,1989,0,0,0,0, + 1,1,5,9,21,27,121,223,133,87,697,0,0,0,0, + 1,1,5,5,9,19,107,99,319,765,1461,0,0,0,0, + 1,1,3,3,19,25,3,101,171,729,187,0,0,0,0, + 1,1,3,1,13,23,85,93,291,209,37,0,0,0,0, + 1,1,1,15,25,25,77,253,333,947,1073,0,0,0,0, + 1,1,3,9,17,29,55,47,255,305,2037,0,0,0,0, + 1,3,3,9,29,63,9,103,489,939,1523,0,0,0,0, + 1,3,7,15,7,31,89,175,369,339,595,0,0,0,0, + 1,3,7,13,25,5,71,207,251,367,665,0,0,0,0, + 1,3,3,3,21,25,75,35,31,321,1603,0,0,0,0, + 1,1,1,9,11,1,65,5,11,329,535,0,0,0,0, + 1,1,5,3,19,13,17,43,379,485,383,0,0,0,0, + 1,3,5,13,13,9,85,147,489,787,1133,0,0,0,0, + 1,3,1,1,5,51,37,129,195,297,1783,0,0,0,0, + 1,1,3,15,19,57,59,181,455,697,2033,0,0,0,0, + 1,3,7,1,27,9,65,145,325,189,201,0,0,0,0, + 1,3,1,15,31,23,19,5,485,581,539,0,0,0,0, + 1,1,7,13,11,15,65,83,185,847,831,0,0,0,0, + 1,3,5,7,7,55,73,15,303,511,1905,0,0,0,0, + 1,3,5,9,7,21,45,15,397,385,597,0,0,0,0, + 1,3,7,3,23,13,73,221,511,883,1265,0,0,0,0, + 1,1,3,11,1,51,73,185,33,975,1441,0,0,0,0, + 1,3,3,9,19,59,21,39,339,37,143,0,0,0,0, + 1,1,7,1,31,33,19,167,117,635,639,0,0,0,0, + 1,1,1,3,5,13,59,83,355,349,1967,0,0,0,0, + 1,1,1,5,19,3,53,133,97,863,983,0,0,0,0, + 1,3,1,13,9,41,91,105,173,97,625,0,0,0,0, + 1,1,5,3,7,49,115,133,71,231,1063,0,0,0,0, + 1,1,7,5,17,43,47,45,497,547,757,0,0,0,0, + 1,3,5,15,21,61,123,191,249,31,631,0,0,0,0, + 1,3,7,9,17,7,11,185,127,169,1951,0,0,0,0, + 1,1,5,13,11,11,9,49,29,125,791,0,0,0,0, + 1,1,1,15,31,41,13,167,273,429,57,0,0,0,0, + 1,3,5,3,27,7,35,209,65,265,1393,0,0,0,0, + 1,3,1,13,31,19,53,143,135,9,1021,0,0,0,0, + 1,1,7,13,31,5,115,153,143,957,623,0,0,0,0, + 1,1,5,11,25,19,29,31,297,943,443,0,0,0,0, + 1,3,3,5,21,11,127,81,479,25,699,0,0,0,0, + 1,1,3,11,25,31,97,19,195,781,705,0,0,0,0, + 1,1,5,5,31,11,75,207,197,885,2037,0,0,0,0, + 1,1,1,11,9,23,29,231,307,17,1497,0,0,0,0, + 1,1,5,11,11,43,111,233,307,523,1259,0,0,0,0, + 1,1,7,5,1,21,107,229,343,933,217,0,0,0,0, + 1,1,1,11,3,21,125,131,405,599,1469,0,0,0,0, + 1,3,5,5,9,39,33,81,389,151,811,0,0,0,0, + 1,1,7,7,7,1,59,223,265,529,2021,0,0,0,0, + 1,3,1,3,9,23,85,181,47,265,49,0,0,0,0, + 1,3,5,11,19,23,9,7,157,299,1983,0,0,0,0, + 1,3,1,5,15,5,21,105,29,339,1041,0,0,0,0, + 1,1,1,1,5,33,65,85,111,705,479,0,0,0,0, + 1,1,1,7,9,35,77,87,151,321,101,0,0,0,0, + 1,1,5,7,17,1,51,197,175,811,1229,0,0,0,0, + 1,3,3,15,23,37,85,185,239,543,731,0,0,0,0, + 1,3,1,7,7,55,111,109,289,439,243,0,0,0,0, + 1,1,7,11,17,53,35,217,259,853,1667,0,0,0,0, + 1,3,1,9,1,63,87,17,73,565,1091,0,0,0,0, + 1,1,3,3,11,41,1,57,295,263,1029,0,0,0,0, + 1,1,5,1,27,45,109,161,411,421,1395,0,0,0,0, + 1,3,5,11,25,35,47,191,339,417,1727,0,0,0,0, + 1,1,5,15,21,1,93,251,351,217,1767,0,0,0,0, + 1,3,3,11,3,7,75,155,313,211,491,0,0,0,0, + 1,3,3,5,11,9,101,161,453,913,1067,0,0,0,0, + 1,1,3,1,15,45,127,141,163,727,1597,0,0,0,0, + 1,3,3,7,1,33,63,73,73,341,1691,0,0,0,0, + 1,3,5,13,15,39,53,235,77,99,949,0,0,0,0, + 1,1,5,13,31,17,97,13,215,301,1927,0,0,0,0, + 1,1,7,1,1,37,91,93,441,251,1131,0,0,0,0, + 1,3,7,9,25,5,105,69,81,943,1459,0,0,0,0, + 1,3,7,11,31,43,13,209,27,1017,501,0,0,0,0, + 1,1,7,15,1,33,31,233,161,507,387,0,0,0,0, + 1,3,3,5,5,53,33,177,503,627,1927,0,0,0,0, + 1,1,7,11,7,61,119,31,457,229,1875,0,0,0,0, + 1,1,5,15,19,5,53,201,157,885,1057,0,0,0,0, + 1,3,7,9,1,35,51,113,249,425,1009,0,0,0,0, + 1,3,5,7,21,53,37,155,119,345,631,0,0,0,0, + 1,3,5,7,15,31,109,69,503,595,1879,0,0,0,0, + 1,3,3,1,25,35,65,131,403,705,503,0,0,0,0, + 1,3,7,7,19,33,11,153,45,633,499,0,0,0,0, + 1,3,3,5,11,3,29,93,487,33,703,0,0,0,0, + 1,1,3,15,21,53,107,179,387,927,1757,0,0,0,0, + 1,1,3,7,21,45,51,147,175,317,361,0,0,0,0, + 1,1,1,7,7,13,15,243,269,795,1965,0,0,0,0, + 1,1,3,5,19,33,57,115,443,537,627,0,0,0,0, + 1,3,3,9,3,39,25,61,185,717,1049,0,0,0,0, + 1,3,7,3,7,37,107,153,7,269,1581,0,0,0,0, + 1,1,7,3,7,41,91,41,145,489,1245,0,0,0,0, + 1,1,5,9,7,7,105,81,403,407,283,0,0,0,0, + 1,1,7,9,27,55,29,77,193,963,949,0,0,0,0, + 1,1,5,3,25,51,107,63,403,917,815,0,0,0,0, + 1,1,7,3,7,61,19,51,457,599,535,0,0,0,0, + 1,3,7,1,23,51,105,153,239,215,1847,0,0,0,0, + 1,1,3,5,27,23,79,49,495,45,1935,0,0,0,0, + 1,1,1,11,11,47,55,133,495,999,1461,0,0,0,0, + 1,1,3,15,27,51,93,17,355,763,1675,0,0,0,0, + 1,3,1,3,1,3,79,119,499,17,995,0,0,0,0, + 1,1,1,1,15,43,45,17,167,973,799,0,0,0,0, + 1,1,1,3,27,49,89,29,483,913,2023,0,0,0,0, + 1,1,3,3,5,11,75,7,41,851,611,0,0,0,0, + 1,3,1,3,7,57,39,123,257,283,507,0,0,0,0, + 1,3,3,11,27,23,113,229,187,299,133,0,0,0,0, + 1,1,3,13,9,63,101,77,451,169,337,0,0,0,0, + 1,3,7,3,3,59,45,195,229,415,409,0,0,0,0, + 1,3,5,3,11,19,71,93,43,857,369,0,0,0,0, + 1,3,7,9,19,33,115,19,241,703,247,0,0,0,0, + 1,3,5,11,5,35,21,155,463,1005,1073,0,0,0,0, + 1,3,7,3,25,15,109,83,93,69,1189,0,0,0,0, + 1,3,5,7,5,21,93,133,135,167,903,0,0,0,0, + 1,1,7,7,3,59,121,161,285,815,1769,3705,0,0,0, + 1,3,1,1,3,47,103,171,381,609,185,373,0,0,0, + 1,3,3,15,23,33,107,131,441,445,689,2059,0,0,0, + 1,3,3,11,7,53,101,167,435,803,1255,3781,0,0,0, + 1,1,5,11,15,59,41,19,135,835,1263,505,0,0,0, + 1,1,7,11,21,49,23,219,127,961,1065,385,0,0,0, + 1,3,5,15,7,47,117,217,45,731,1639,733,0,0,0, + 1,1,7,11,27,57,91,87,81,35,1269,1007,0,0,0, + 1,1,3,11,15,37,53,219,193,937,1899,3733,0,0,0, + 1,3,5,3,13,11,27,19,199,393,965,2195,0,0,0, + 1,3,1,3,5,1,37,173,413,1023,553,409,0,0,0, + 1,3,1,7,15,29,123,95,255,373,1799,3841,0,0,0, + 1,3,5,13,21,57,51,17,511,195,1157,1831,0,0,0, + 1,1,1,15,29,19,7,73,295,519,587,3523,0,0,0, + 1,1,5,13,13,35,115,191,123,535,717,1661,0,0,0, + 1,3,3,5,23,21,47,251,379,921,1119,297,0,0,0, + 1,3,3,9,29,53,121,201,135,193,523,2943,0,0,0, + 1,1,1,7,29,45,125,9,99,867,425,601,0,0,0, + 1,3,1,9,13,15,67,181,109,293,1305,3079,0,0,0, + 1,3,3,9,5,35,15,209,305,87,767,2795,0,0,0, + 1,3,3,11,27,57,113,123,179,643,149,523,0,0,0, + 1,1,3,15,11,17,67,223,63,657,335,3309,0,0,0, + 1,1,1,9,25,29,109,159,39,513,571,1761,0,0,0, + 1,1,3,1,5,63,75,19,455,601,123,691,0,0,0, + 1,1,1,3,21,5,45,169,377,513,1951,2565,0,0,0, + 1,1,3,11,3,33,119,69,253,907,805,1449,0,0,0, + 1,1,5,13,31,15,17,7,499,61,687,1867,0,0,0, + 1,3,7,11,17,33,73,77,299,243,641,2345,0,0,0, + 1,1,7,11,9,35,31,235,359,647,379,1161,0,0,0, + 1,3,3,15,31,25,5,67,33,45,437,4067,0,0,0, + 1,1,3,11,7,17,37,87,333,253,1517,2921,0,0,0, + 1,1,7,15,7,15,107,189,153,769,1521,3427,0,0,0, + 1,3,5,13,5,61,113,37,293,393,113,43,0,0,0, + 1,1,1,15,29,43,107,31,167,147,301,1021,0,0,0, + 1,1,1,13,3,1,35,93,195,181,2027,1491,0,0,0, + 1,3,3,3,13,33,77,199,153,221,1699,3671,0,0,0, + 1,3,5,13,7,49,123,155,495,681,819,809,0,0,0, + 1,3,5,15,27,61,117,189,183,887,617,4053,0,0,0, + 1,1,1,7,31,59,125,235,389,369,447,1039,0,0,0, + 1,3,5,1,5,39,115,89,249,377,431,3747,0,0,0, + 1,1,1,5,7,47,59,157,77,445,699,3439,0,0,0, + 1,1,3,5,11,21,19,75,11,599,1575,735,0,0,0, + 1,3,5,3,19,13,41,69,199,143,1761,3215,0,0,0, + 1,3,5,7,19,43,25,41,41,11,1647,2783,0,0,0, + 1,3,1,9,19,45,111,97,405,399,457,3219,0,0,0, + 1,1,3,1,23,15,65,121,59,985,829,2259,0,0,0, + 1,1,3,7,17,13,107,229,75,551,1299,2363,0,0,0, + 1,1,5,5,21,57,23,199,509,139,2007,3875,0,0,0, + 1,3,1,11,19,53,15,229,215,741,695,823,0,0,0, + 1,3,7,1,29,3,17,163,417,559,549,319,0,0,0, + 1,3,1,13,17,9,47,133,365,7,1937,1071,0,0,0, + 1,3,5,7,19,37,55,163,301,249,689,2327,0,0,0, + 1,3,5,13,11,23,61,205,257,377,615,1457,0,0,0, + 1,3,5,1,23,37,13,75,331,495,579,3367,0,0,0, + 1,1,1,9,1,23,49,129,475,543,883,2531,0,0,0, + 1,3,1,5,23,59,51,35,343,695,219,369,0,0,0, + 1,3,3,1,27,17,63,97,71,507,1929,613,0,0,0, + 1,1,5,1,21,31,11,109,247,409,1817,2173,0,0,0, + 1,1,3,15,23,9,7,209,301,23,147,1691,0,0,0, + 1,1,7,5,5,19,37,229,249,277,1115,2309,0,0,0, + 1,1,1,5,5,63,5,249,285,431,343,2467,0,0,0, + 1,1,1,11,7,45,35,75,505,537,29,2919,0,0,0, + 1,3,5,15,11,39,15,63,263,9,199,445,0,0,0, + 1,3,3,3,27,63,53,171,227,63,1049,827,0,0,0, + 1,1,3,13,7,11,115,183,179,937,1785,381,0,0,0, + 1,3,1,11,13,15,107,81,53,295,1785,3757,0,0,0, + 1,3,3,13,11,5,109,243,3,505,323,1373,0,0,0, + 1,3,3,11,21,51,17,177,381,937,1263,3889,0,0,0, + 1,3,5,9,27,25,85,193,143,573,1189,2995,0,0,0, + 1,3,5,11,13,9,81,21,159,953,91,1751,0,0,0, + 1,1,3,3,27,61,11,253,391,333,1105,635,0,0,0, + 1,3,3,15,9,57,95,81,419,735,251,1141,0,0,0, + 1,1,5,9,31,39,59,13,319,807,1241,2433,0,0,0, + 1,3,3,5,27,13,107,141,423,937,2027,3233,0,0,0, + 1,3,3,9,9,25,125,23,443,835,1245,847,0,0,0, + 1,1,7,15,17,17,83,107,411,285,847,1571,0,0,0, + 1,1,3,13,29,61,37,81,349,727,1453,1957,0,0,0, + 1,3,7,11,31,13,59,77,273,591,1265,1533,0,0,0, + 1,1,7,7,13,17,25,25,187,329,347,1473,0,0,0, + 1,3,7,7,5,51,37,99,221,153,503,2583,0,0,0, + 1,3,1,13,19,27,11,69,181,479,1183,3229,0,0,0, + 1,3,3,13,23,21,103,147,323,909,947,315,0,0,0, + 1,3,1,3,23,1,31,59,93,513,45,2271,0,0,0, + 1,3,5,1,7,43,109,59,231,41,1515,2385,0,0,0, + 1,3,1,5,31,57,49,223,283,1013,11,701,0,0,0, + 1,1,5,1,19,53,55,31,31,299,495,693,0,0,0, + 1,3,3,9,5,33,77,253,427,791,731,1019,0,0,0, + 1,3,7,11,1,9,119,203,53,877,1707,3499,0,0,0, + 1,1,3,7,13,39,55,159,423,113,1653,3455,0,0,0, + 1,1,3,5,21,47,51,59,55,411,931,251,0,0,0, + 1,3,7,3,31,25,81,115,405,239,741,455,0,0,0, + 1,1,5,1,31,3,101,83,479,491,1779,2225,0,0,0, + 1,3,3,3,9,37,107,161,203,503,767,3435,0,0,0, + 1,3,7,9,1,27,61,119,233,39,1375,4089,0,0,0, + 1,1,5,9,1,31,45,51,369,587,383,2813,0,0,0, + 1,3,7,5,31,7,49,119,487,591,1627,53,0,0,0, + 1,1,7,1,9,47,1,223,369,711,1603,1917,0,0,0, + 1,3,5,3,21,37,111,17,483,739,1193,2775,0,0,0, + 1,3,3,7,17,11,51,117,455,191,1493,3821,0,0,0, + 1,1,5,9,23,39,99,181,343,485,99,1931,0,0,0, + 1,3,1,7,29,49,31,71,489,527,1763,2909,0,0,0, + 1,1,5,11,5,5,73,189,321,57,1191,3685,0,0,0, + 1,1,5,15,13,45,125,207,371,415,315,983,0,0,0, + 1,3,3,5,25,59,33,31,239,919,1859,2709,0,0,0, + 1,3,5,13,27,61,23,115,61,413,1275,3559,0,0,0, + 1,3,7,15,5,59,101,81,47,967,809,3189,0,0,0, + 1,1,5,11,31,15,39,25,173,505,809,2677,0,0,0, + 1,1,5,9,19,13,95,89,511,127,1395,2935,0,0,0, + 1,1,5,5,31,45,9,57,91,303,1295,3215,0,0,0, + 1,3,3,3,19,15,113,187,217,489,1285,1803,0,0,0, + 1,1,3,1,13,29,57,139,255,197,537,2183,0,0,0, + 1,3,1,15,11,7,53,255,467,9,757,3167,0,0,0, + 1,3,3,15,21,13,9,189,359,323,49,333,0,0,0, + 1,3,7,11,7,37,21,119,401,157,1659,1069,0,0,0, + 1,1,5,7,17,33,115,229,149,151,2027,279,0,0,0, + 1,1,5,15,5,49,77,155,383,385,1985,945,0,0,0, + 1,3,7,3,7,55,85,41,357,527,1715,1619,0,0,0, + 1,1,3,1,21,45,115,21,199,967,1581,3807,0,0,0, + 1,1,3,7,21,39,117,191,169,73,413,3417,0,0,0, + 1,1,1,13,1,31,57,195,231,321,367,1027,0,0,0, + 1,3,7,3,11,29,47,161,71,419,1721,437,0,0,0, + 1,1,7,3,11,9,43,65,157,1,1851,823,0,0,0, + 1,1,1,5,21,15,31,101,293,299,127,1321,0,0,0, + 1,1,7,1,27,1,11,229,241,705,43,1475,0,0,0, + 1,3,7,1,5,15,73,183,193,55,1345,49,0,0,0, + 1,3,3,3,19,3,55,21,169,663,1675,137,0,0,0, + 1,1,1,13,7,21,69,67,373,965,1273,2279,0,0,0, + 1,1,7,7,21,23,17,43,341,845,465,3355,0,0,0, + 1,3,5,5,25,5,81,101,233,139,359,2057,0,0,0, + 1,1,3,11,15,39,55,3,471,765,1143,3941,0,0,0, + 1,1,7,15,9,57,81,79,215,433,333,3855,0,0,0, + 1,1,5,5,19,45,83,31,209,363,701,1303,0,0,0, + 1,3,7,5,1,13,55,163,435,807,287,2031,0,0,0, + 1,3,3,7,3,3,17,197,39,169,489,1769,0,0,0, + 1,1,3,5,29,43,87,161,289,339,1233,2353,0,0,0, + 1,3,3,9,21,9,77,1,453,167,1643,2227,0,0,0, + 1,1,7,1,15,7,67,33,193,241,1031,2339,0,0,0, + 1,3,1,11,1,63,45,65,265,661,849,1979,0,0,0, + 1,3,1,13,19,49,3,11,159,213,659,2839,0,0,0, + 1,3,5,11,9,29,27,227,253,449,1403,3427,0,0,0, + 1,1,3,1,7,3,77,143,277,779,1499,475,0,0,0, + 1,1,1,5,11,23,87,131,393,849,193,3189,0,0,0, + 1,3,5,11,3,3,89,9,449,243,1501,1739,0,0,0, + 1,3,1,9,29,29,113,15,65,611,135,3687,0,0,0, + 1,1,1,9,21,19,39,151,395,501,1339,959,2725,0,0, + 1,3,7,1,7,35,45,33,119,225,1631,1695,1459,0,0, + 1,1,1,3,25,55,37,79,167,907,1075,271,4059,0,0, + 1,3,5,13,5,13,53,165,437,67,1705,3177,8095,0,0, + 1,3,3,13,27,57,95,55,443,245,1945,1725,1929,0,0, + 1,3,1,9,5,33,109,35,99,827,341,2401,2411,0,0, + 1,1,5,9,7,33,43,39,87,799,635,3481,7159,0,0, + 1,3,1,1,31,15,45,27,337,113,987,2065,2529,0,0, + 1,1,5,9,5,15,105,123,479,289,1609,2177,4629,0,0, + 1,3,5,11,31,47,97,87,385,195,1041,651,3271,0,0, + 1,1,3,7,17,3,101,55,87,629,1687,1387,2745,0,0, + 1,3,5,5,7,21,9,237,313,549,1107,117,6183,0,0, + 1,1,3,9,9,5,55,201,487,851,1103,2993,4055,0,0, + 1,1,5,9,31,19,59,7,363,381,1167,2057,5715,0,0, + 1,3,3,15,23,63,19,227,387,827,487,1049,7471,0,0, + 1,3,1,5,23,25,61,245,363,863,963,3583,6475,0,0, + 1,1,5,1,5,27,81,85,275,49,235,3291,1195,0,0, + 1,1,5,7,23,53,85,107,511,779,1265,1093,7859,0,0, + 1,3,3,1,9,21,75,219,59,485,1739,3845,1109,0,0, + 1,3,5,1,13,41,19,143,293,391,2023,1791,4399,0,0, + 1,3,7,15,21,13,21,195,215,413,523,2099,2341,0,0, + 1,1,1,3,29,51,47,57,135,575,943,1673,541,0,0, + 1,3,5,1,9,13,113,175,447,115,657,4077,5973,0,0, + 1,1,1,11,17,41,37,95,297,579,911,2207,2387,0,0, + 1,3,5,3,23,11,23,231,93,667,711,1563,7961,0,0, + 1,1,7,3,17,59,13,181,141,991,1817,457,1711,0,0, + 1,3,3,5,31,59,81,205,245,537,1049,997,1815,0,0, + 1,3,7,5,17,13,9,79,17,185,5,2211,6263,0,0, + 1,3,7,13,7,53,61,145,13,285,1203,947,2933,0,0, + 1,1,7,3,31,19,69,217,47,441,1893,673,4451,0,0, + 1,1,1,1,25,9,23,225,385,629,603,3747,4241,0,0, + 1,3,1,9,5,37,31,237,431,79,1521,459,2523,0,0, + 1,3,7,3,9,43,105,179,5,225,799,1777,4893,0,0, + 1,1,3,1,29,45,29,159,267,247,455,847,3909,0,0, + 1,1,3,7,25,21,121,57,467,275,719,1521,7319,0,0, + 1,3,1,3,11,35,119,123,81,979,1187,3623,4293,0,0, + 1,1,1,7,15,25,121,235,25,487,873,1787,1977,0,0, + 1,1,1,11,3,7,17,135,345,353,383,4011,2573,0,0, + 1,3,7,15,27,13,97,123,65,675,951,1285,6559,0,0, + 1,3,7,3,7,1,71,19,325,765,337,1197,2697,0,0, + 1,3,5,1,31,37,11,71,169,283,83,3801,7083,0,0, + 1,1,3,15,17,29,83,65,275,679,1749,4007,7749,0,0, + 1,1,3,1,21,11,41,95,237,361,1819,2783,2383,0,0, + 1,3,7,11,29,57,111,187,465,145,605,1987,8109,0,0, + 1,1,3,3,19,15,55,83,357,1001,643,1517,6529,0,0, + 1,3,1,5,29,35,73,23,77,619,1523,1725,8145,0,0, + 1,1,5,5,19,23,7,197,449,337,717,2921,315,0,0, + 1,3,5,9,7,63,117,97,97,813,1925,2817,1579,0,0, + 1,1,1,11,31,7,25,235,231,133,1007,1371,1553,0,0, + 1,1,7,5,19,7,47,171,267,243,1331,567,6033,0,0, + 1,1,5,1,7,49,55,89,109,735,1455,3193,6239,0,0, + 1,1,1,7,1,61,9,103,3,929,1481,2927,2957,0,0, + 1,1,5,13,17,21,75,49,255,1019,1161,2133,1177,0,0, + 1,3,1,3,13,15,41,247,211,409,1163,523,2635,0,0, + 1,3,7,7,21,59,91,149,479,391,681,2311,6249,0,0, + 1,1,5,11,27,53,21,211,197,815,719,1605,255,0,0, + 1,1,3,3,9,33,59,3,323,1,101,1135,8105,0,0, + 1,3,3,1,29,5,17,141,51,991,841,327,3859,0,0, + 1,3,1,5,11,19,23,89,175,173,165,2881,1881,0,0, + 1,1,1,15,13,51,87,39,495,611,1341,1531,7029,0,0, + 1,1,3,11,13,55,75,185,57,61,1917,2051,5965,0,0, + 1,1,5,5,7,53,11,217,213,933,921,3607,5175,0,0, + 1,3,3,5,17,53,103,251,369,781,1319,3717,4439,0,0, + 1,3,5,13,1,39,25,235,321,773,251,3111,6397,0,0, + 1,1,7,3,31,5,25,29,325,385,1313,127,4705,0,0, + 1,1,5,15,15,27,15,85,239,243,1633,3473,2621,0,0, + 1,3,3,3,9,19,113,13,137,165,25,2957,7549,0,0, + 1,3,1,3,11,21,3,97,417,183,1205,1437,247,0,0, + 1,1,7,3,17,21,125,55,67,387,385,2323,887,0,0, + 1,3,5,5,29,11,103,223,233,641,133,415,1297,0,0, + 1,3,3,11,1,9,5,189,235,1007,1363,3985,889,0,0, + 1,3,7,9,23,19,19,183,269,403,1643,3559,5189,0,0, + 1,3,7,3,29,45,17,69,475,149,1291,2689,7625,0,0, + 1,3,7,3,27,37,41,73,253,1001,431,1111,7887,0,0, + 1,1,7,5,3,7,87,143,289,495,631,3011,6151,0,0, + 1,1,1,13,5,45,17,167,23,975,801,1975,6833,0,0, + 1,3,1,11,7,21,39,23,213,429,1301,2059,197,0,0, + 1,3,3,15,3,57,121,133,29,711,1961,2497,189,0,0, + 1,1,3,5,11,55,115,137,233,673,985,2849,5911,0,0, + 1,1,7,15,29,45,1,241,329,323,925,2821,3331,0,0, + 1,1,5,7,13,31,81,105,199,145,195,1365,5119,0,0, + 1,3,7,11,3,55,11,31,117,343,1265,1837,2451,0,0, + 1,1,3,7,29,57,61,179,429,591,177,1945,2159,0,0, + 1,3,5,11,23,49,101,137,339,323,1035,1749,7737,0,0, + 1,3,1,13,21,35,55,79,19,269,1055,2651,7083,0,0, + 1,3,3,11,9,9,95,167,437,361,1185,4083,603,0,0, + 1,1,1,7,31,61,77,65,489,657,691,2423,4147,0,0, + 1,3,5,7,21,37,87,191,311,453,2013,829,2619,0,0, + 1,1,5,9,17,47,35,101,5,813,1157,1279,7365,0,0, + 1,1,5,3,11,35,113,199,369,721,901,1471,7801,0,0, + 1,3,1,5,9,61,83,157,391,739,1957,2123,4341,0,0, + 1,3,5,11,19,19,111,225,383,219,997,717,7505,0,0, + 1,3,1,11,13,63,35,127,209,831,501,3017,3507,0,0, + 1,3,7,9,29,7,11,163,81,563,1445,3215,6377,0,0, + 1,3,7,11,25,3,39,195,491,45,839,4021,4899,0,0, + 1,3,7,15,13,5,67,143,117,505,1281,3679,5695,0,0, + 1,3,7,9,9,19,21,221,147,763,683,2211,589,0,0, + 1,1,3,5,21,47,53,109,299,807,1153,1209,7961,0,0, + 1,3,7,11,9,31,45,43,505,647,1127,2681,4917,0,0, + 1,1,5,15,31,41,63,113,399,727,673,2587,5259,0,0, + 1,1,1,13,17,53,35,99,57,243,1447,1919,2831,0,0, + 1,3,7,11,23,51,13,9,49,449,997,3073,4407,0,0, + 1,3,5,7,23,33,89,41,415,53,697,1113,1489,0,0, + 1,1,3,7,1,13,29,13,255,749,77,3463,1761,0,0, + 1,3,3,7,13,15,93,191,309,869,739,1041,3053,0,0, + 1,3,5,13,5,19,109,211,347,839,893,2947,7735,0,0, + 1,3,1,13,27,3,119,157,485,99,1703,3895,573,0,0, + 1,3,7,11,1,23,123,105,31,359,275,1775,3685,0,0, + 1,3,3,5,27,11,125,3,413,199,2043,2895,2945,0,0, + 1,3,3,3,15,49,121,159,233,543,193,4007,321,0,0, + 1,1,3,5,9,47,87,1,51,1011,1595,2239,6467,0,0, + 1,3,7,9,1,33,87,137,469,749,1413,805,6817,0,0, + 1,3,1,13,19,45,95,227,29,677,1275,3395,4451,0,0, + 1,1,7,5,7,63,33,71,443,561,1311,3069,6943,0,0, + 1,1,1,13,9,37,23,69,13,415,1479,1197,861,0,0, + 1,3,3,13,27,21,13,233,105,777,345,2443,1105,0,0, + 1,1,7,11,23,13,21,147,221,549,73,2729,6279,0,0, + 1,1,7,7,25,27,15,45,227,39,75,1191,3563,0,0, + 1,1,5,7,13,49,99,167,227,13,353,1047,8075,0,0, + 1,1,3,13,31,9,27,7,461,737,1559,3243,53,0,0, + 1,3,1,1,21,41,97,165,171,821,587,2137,2293,0,0, + 1,3,1,11,17,41,29,187,87,599,1467,1395,5931,0,0, + 1,1,1,9,9,49,89,205,409,453,61,1923,1257,0,0, + 1,3,7,3,9,43,89,143,431,83,1243,1795,3599,0,0, + 1,3,5,13,3,25,59,219,43,223,797,2651,6015,0,0, + 1,1,5,15,7,55,65,207,213,311,1287,1269,6467,0,0, + 1,3,7,11,21,57,31,183,351,857,911,1683,7155,0,0, + 1,3,5,11,27,1,21,47,387,383,1593,115,3805,0,0, + 1,3,1,1,13,23,87,173,181,619,1653,3931,6073,0,0, + 1,1,7,5,17,43,37,61,307,621,1785,55,115,0,0, + 1,3,7,15,25,61,123,15,237,671,1473,467,1907,0,0, + 1,1,7,5,29,57,75,237,85,699,159,3577,4771,0,0, + 1,1,1,11,25,19,51,1,147,31,895,2617,625,0,0, + 1,3,7,5,29,15,115,175,395,391,1141,1827,1181,0,0, + 1,3,5,7,17,7,11,193,89,243,561,3787,4551,0,0, + 1,3,1,11,7,57,7,125,403,947,1261,409,8083,0,0, + 1,1,5,13,21,63,115,233,231,921,1747,3635,2519,0,0, + 1,1,5,11,3,27,15,91,505,591,1451,3881,2997,0,0, + 1,1,3,11,21,9,109,153,317,533,593,3967,2797,0,0, + 1,3,3,13,9,57,121,245,219,867,967,791,7095,0,0, + 1,1,1,9,29,21,99,35,375,959,329,4087,7171,0,0, + 1,1,1,9,11,17,17,97,89,135,631,3809,3253,0,0, + 1,1,1,15,21,51,91,249,459,801,757,2353,2033,0,0, + 1,3,5,9,23,29,77,53,399,767,1817,2171,1629,0,0, + 1,1,3,5,29,5,43,121,17,859,1479,3785,6641,0,0, + 1,1,3,7,7,61,45,109,371,833,91,153,4553,0,0, + 1,1,3,11,7,55,81,123,389,139,1933,891,1789,0,0, + 1,3,7,15,25,17,93,165,503,717,1553,1475,1627,0,0, + 1,1,1,13,13,63,13,225,357,571,33,4073,3795,0,0, + 1,1,3,11,1,31,107,145,407,961,501,2987,103,0,0, + 1,1,7,1,23,63,49,193,173,281,25,2465,5927,0,0, + 1,1,7,1,1,1,85,77,273,693,349,1239,4503,0,0, + 1,1,5,11,7,61,9,121,25,357,1443,405,7827,0,0, + 1,1,7,13,11,53,11,207,145,211,1703,1081,2117,0,0, + 1,1,3,11,27,23,19,9,297,279,1481,2273,6387,0,0, + 1,3,3,5,15,45,3,41,305,87,1815,3461,5349,0,0, + 1,3,3,13,9,37,79,125,259,561,1087,4091,793,0,0, + 1,3,5,7,31,55,7,145,347,929,589,2783,5905,0,0, + 1,1,7,15,3,25,1,181,13,243,653,2235,7445,0,0, + 1,3,5,5,17,53,65,7,33,583,1363,1313,2319,0,0, + 1,3,3,7,27,47,97,201,187,321,63,1515,7917,0,0, + 1,1,3,5,23,9,3,165,61,19,1789,3783,3037,0,0, + 1,3,1,13,15,43,125,191,67,273,1551,2227,5253,0,0, + 1,1,1,13,25,53,107,33,299,249,1475,2233,907,0,0, + 1,3,5,1,23,37,85,17,207,643,665,2933,5199,0,0, + 1,1,7,7,25,57,59,41,15,751,751,1749,7053,0,0, + 1,3,3,1,13,25,127,93,281,613,875,2223,6345,0,0, + 1,1,5,3,29,55,79,249,43,317,533,995,1991,0,0, + 1,3,3,15,17,49,79,31,193,233,1437,2615,819,0,0, + 1,1,5,15,25,3,123,145,377,9,455,1191,3953,0,0, + 1,3,5,3,15,19,41,231,81,393,3,19,2409,0,0, + 1,1,3,1,27,43,113,179,7,853,947,2731,297,0,0, + 1,1,1,11,29,39,53,191,443,689,529,3329,7431,0,0, + 1,3,7,5,3,29,19,67,441,113,949,2769,4169,0,0, + 1,3,5,11,11,55,85,169,215,815,803,2345,3967,0,0, + 1,1,7,9,5,45,111,5,419,375,303,1725,4489,0,0, + 1,3,5,15,29,43,79,19,23,417,381,541,4923,0,0, + 1,1,3,15,3,31,117,39,117,305,1227,1223,143,0,0, + 1,1,5,9,5,47,87,239,181,353,1561,3313,1921,0,0, + 1,3,3,1,3,15,53,221,441,987,1997,2529,8059,0,0, + 1,1,7,11,15,57,111,139,137,883,1881,2823,5661,0,0, + 1,3,5,5,21,11,5,13,27,973,587,1331,1373,0,0, + 1,1,7,11,29,51,93,29,217,221,55,2477,1979,0,0, + 1,3,3,13,3,11,49,75,379,371,1441,793,7633,0,0, + 1,1,1,13,19,45,89,249,91,649,1695,915,5619,0,0, + 1,3,1,7,7,29,1,77,313,895,519,771,295,0,0, + 1,3,1,15,5,3,1,57,331,109,485,2853,6831,0,0, + 1,1,1,15,17,3,35,99,245,971,839,2509,2803,0,0, + 1,3,3,3,9,37,57,251,325,317,529,1313,6379,0,0, + 1,1,1,15,25,59,1,119,95,15,795,2375,6463,0,0, + 1,3,1,5,1,49,117,21,47,179,863,85,1669,0,0, + 1,3,7,3,9,37,19,221,455,973,571,1427,817,0,0, + 1,1,1,15,17,9,67,213,127,887,1299,2913,7451,0,0, + 1,3,1,13,27,27,41,43,171,623,691,391,4885,0,0, + 1,3,1,13,17,17,123,239,143,227,1151,519,6543,0,0, + 1,3,7,5,7,63,97,39,101,555,1057,381,7891,0,0, + 1,3,5,1,3,27,85,129,161,875,1945,3541,695,0,0, + 1,3,3,5,21,59,25,183,35,25,987,1459,181,0,0, + 1,3,5,13,1,15,127,237,349,337,1491,2383,7811,0,0, + 1,3,5,5,31,5,109,51,409,733,1395,3207,6049,0,0, + 1,1,5,7,13,35,113,25,263,389,299,2521,1783,0,0, + 1,3,7,11,15,47,97,73,55,75,113,2695,1023,0,0, + 1,3,1,1,3,13,69,211,289,483,1335,787,677,0,0, + 1,1,3,3,17,7,37,77,505,137,1113,345,2975,0,0, + 1,1,1,13,3,11,95,199,453,109,479,3725,239,0,0, + 1,1,7,15,19,53,3,145,359,863,347,3833,3043,0,0, + 1,1,7,15,25,63,127,129,125,195,155,2211,8153,0,0, + 1,1,7,13,9,49,121,115,73,119,1851,727,47,0,0, + 1,3,3,13,13,11,71,7,45,591,133,2407,5563,0,0, + 1,1,1,13,23,29,87,89,501,71,1759,1119,687,0,0, + 1,1,7,7,13,7,13,183,53,951,1877,3991,6771,0,0, + 1,3,7,11,7,1,27,47,61,21,919,961,1091,0,0, + 1,3,5,5,1,27,1,5,63,157,1297,1049,5893,0,0, + 1,3,7,9,19,33,17,133,425,797,1721,153,119,0,0, + 1,3,3,7,13,37,1,215,509,1003,61,2353,7511,0,0, + 1,1,7,1,29,19,31,79,199,555,1209,1603,6089,0,0, + 1,3,1,1,5,31,111,127,333,429,1863,3925,5411,0,0, + 1,1,7,5,5,5,123,191,47,993,269,4051,2111,0,0, + 1,1,5,15,1,9,87,5,47,463,865,1813,7357,0,0, + 1,3,1,3,23,63,123,83,511,777,63,1285,4537,0,0, + 1,3,3,7,27,25,31,65,441,529,1815,1893,323,0,0, + 1,3,7,5,11,19,7,5,397,811,755,2883,4217,0,0, + 1,3,1,13,9,21,13,7,271,539,1769,3243,5325,0,0, + 1,1,7,1,31,13,47,131,181,457,1559,2663,6653,0,0, + 1,3,3,7,29,55,25,203,419,91,437,1159,5691,0,0, + 1,1,3,13,29,19,71,217,337,329,501,939,2205,0,0, + 1,1,3,1,1,27,17,201,97,285,1269,4043,2207,0,0, + 1,1,1,1,3,41,13,199,141,129,1515,3129,5969,0,0, + 1,3,3,9,3,17,119,41,271,933,877,701,2197,0,0, + 1,1,1,7,15,47,3,195,115,821,725,843,6071,0,0, + 1,3,5,15,17,33,85,65,297,571,1123,2743,5727,0,0, + 1,1,5,11,27,15,37,235,415,293,1439,2739,4171,0,0, + 1,3,7,7,1,55,71,35,307,11,401,1881,933,0,0, + 1,3,1,11,21,37,3,177,119,339,559,3991,3437,0,0, + 1,3,3,9,17,17,97,119,301,169,157,3267,2261,0,0, + 1,3,3,9,29,3,111,101,355,869,375,2609,7377,0,0, + 1,3,5,9,7,21,123,99,343,693,1927,1605,4923,0,0, + 1,1,3,5,13,31,99,17,75,385,1539,1553,7077,0,0, + 1,3,3,5,31,35,107,11,407,1019,1317,3593,7203,0,0, + 1,3,3,13,17,33,99,245,401,957,157,1949,1571,0,0, + 1,3,1,11,27,15,11,109,429,307,1911,2701,861,0,0, + 1,1,5,13,13,35,55,255,311,957,1803,2673,5195,0,0, + 1,1,1,11,19,3,89,37,211,783,1355,3567,7135,0,0, + 1,1,5,5,21,49,79,17,509,331,183,3831,855,0,0, + 1,3,7,5,29,19,85,109,105,523,845,3385,7477,0,0, + 1,1,1,7,25,17,125,131,53,757,253,2989,2939,0,0, + 1,3,3,9,19,23,105,39,351,677,211,401,8103,0,0, + 1,3,5,1,5,11,17,3,405,469,1569,2865,3133,0,0, + 1,1,3,13,15,5,117,179,139,145,477,1137,2537,0,0, + 1,1,7,9,5,21,9,93,211,963,1207,3343,4911,0,0, + 1,1,1,9,13,43,17,53,81,793,1571,2523,3683,0,0, + 1,3,3,13,25,21,5,59,489,987,1941,171,6009,0,0, + 1,3,3,7,1,39,89,171,403,467,1767,3423,2791,0,0, + 1,1,3,9,19,49,91,125,163,1013,89,2849,6785,0,0, + 1,1,5,9,9,11,15,241,43,297,1719,1541,1821,0,0, + 1,3,7,15,29,23,103,239,191,33,1043,3649,6579,0,0, + 1,3,3,9,21,51,123,55,223,645,1463,4021,5891,0,0, + 1,1,5,7,3,41,27,235,391,303,2021,3187,7607,0,0, + 1,1,1,9,5,49,49,29,377,251,1887,1017,1301,0,0, + 1,1,3,3,13,41,27,47,223,23,517,3227,6731,0,0, + 1,1,7,1,31,25,47,9,511,623,2047,1263,1511,0,0, + 1,1,3,15,15,23,53,1,261,595,85,241,7047,0,0, + 1,3,3,11,17,5,81,73,149,781,2035,3163,4247,0,0, + 1,3,7,7,29,59,49,79,397,901,1105,2191,6277,0,0, + 1,3,3,11,13,27,25,173,107,73,1265,585,5251,0,0, + 1,1,7,15,29,23,73,229,235,887,1469,4073,2591,0,0, + 1,1,3,9,17,15,83,173,207,879,1701,1509,11,0,0, + 1,1,3,5,5,37,65,161,39,421,1153,2007,5355,0,0, + 1,1,7,11,23,37,5,11,9,499,17,157,5747,0,0, + 1,3,7,13,25,9,49,7,39,945,1349,1759,1441,0,0, + 1,1,5,3,21,15,113,81,265,837,333,3625,6133,0,0, + 1,3,1,11,13,27,73,109,297,327,299,3253,6957,0,0, + 1,1,3,13,19,39,123,73,65,5,1061,2187,5055,0,0, + 1,1,3,1,11,31,21,115,453,857,711,495,549,0,0, + 1,3,7,7,15,29,79,103,47,713,1735,3121,6321,0,0, + 1,1,5,5,29,9,97,33,471,705,329,1501,1349,0,0, + 1,3,3,1,21,9,111,209,71,47,491,2143,1797,0,0, + 1,3,3,3,11,39,21,135,445,259,607,3811,5449,0,0, + 1,1,7,9,11,25,113,251,395,317,317,91,1979,0,0, + 1,3,1,9,3,21,103,133,389,943,1235,1749,7063,0,0, + 1,1,3,7,1,11,5,15,497,477,479,3079,6969,0,0, + 1,1,3,3,15,39,105,131,475,465,181,865,3813,0,0, + 1,1,7,9,19,63,123,131,415,525,457,2471,3135,0,0, + 1,3,7,15,25,35,123,45,341,805,485,4049,7065,0,0, + 1,1,1,5,29,9,47,227,51,867,1873,1593,2271,0,0, + 1,1,7,15,31,9,71,117,285,711,837,1435,6275,0,0, + 1,3,1,1,5,19,79,25,301,415,1871,645,3251,0,0, + 1,3,1,3,17,51,99,185,447,43,523,219,429,0,0, + 1,3,1,13,29,13,51,93,7,995,757,3017,6865,0,0, + 1,1,3,15,7,25,75,17,155,981,1231,1229,1995,0,0, + 1,3,5,3,27,45,71,73,225,763,377,1139,2863,0,0, + 1,1,3,1,1,39,69,113,29,371,1051,793,3749,0,0, + 1,1,3,13,23,61,27,183,307,431,1345,2757,4031,0,0, + 1,3,7,5,5,59,117,197,303,721,877,723,1601,0,0, + 1,3,5,1,27,33,99,237,485,711,665,3077,5105,0,0, + 1,1,3,1,13,9,103,201,23,951,2029,165,2093,0,0, + 1,3,5,13,5,29,55,85,221,677,611,3613,4567,0,0, + 1,1,1,1,7,61,9,233,261,561,953,4023,2443,0,0, + 1,3,3,13,1,17,103,71,223,213,833,1747,6999,0,0, + 1,3,5,15,25,53,57,187,25,695,1207,4089,2877,0,0, + 1,1,7,1,7,31,87,129,493,519,1555,1155,4637,0,0, + 1,1,1,15,21,17,23,29,19,255,927,1791,3093,0,0, + 1,1,3,9,17,33,95,129,175,461,287,2633,2325,0,0, + 1,3,5,7,23,19,63,209,249,583,1373,2039,2225,0,0, + 1,3,3,5,5,19,79,241,459,355,1455,3313,3639,0,0, + 1,1,7,9,21,41,97,119,129,769,1541,3495,7741,0,0, + 1,1,7,11,9,29,35,255,141,937,1763,41,1393,0,0, + 1,3,7,1,13,51,61,157,177,847,1829,3539,285,0,0, + 1,1,1,15,21,13,9,55,397,19,1495,1255,7235,0,0, + 1,1,7,7,25,37,53,237,319,197,269,1205,1485,0,0, + 1,1,5,15,23,17,35,247,323,807,233,3681,4407,0,0, + 1,1,3,7,9,59,85,105,493,763,1639,391,1451,0,0, + 1,3,3,9,15,33,5,253,129,625,1527,2793,6057,0,0, + 1,3,1,1,7,47,21,161,235,83,397,3563,5953,0,0, + 1,3,7,11,3,41,25,117,375,779,1297,3715,8117,0,0, + 1,1,3,7,31,19,103,173,475,189,2035,2921,1107,0,0, + 1,1,7,3,25,7,93,255,307,113,1893,2233,6919,0,0, + 1,3,5,15,9,57,79,143,165,5,1389,193,693,0,0, + 1,3,5,1,29,45,91,49,189,461,439,1283,7835,0,0, + 1,1,3,13,11,61,41,231,373,695,395,915,5393,0,0, + 1,3,7,11,5,51,67,53,483,95,1943,247,5653,0,0, + 1,3,7,5,5,57,45,235,137,793,1069,1661,1557,0,0, + 1,3,5,3,25,55,103,177,81,861,1151,143,7655,0,0, + 1,1,3,1,21,41,67,131,253,431,1269,3181,3429,0,0, + 1,3,1,1,21,7,77,221,257,663,71,2949,2481,0,0, + 1,3,5,3,3,23,45,107,299,739,1013,3,3165,0,0, + 1,1,5,1,3,37,109,37,243,983,1221,1691,3869,0,0, + 1,1,5,5,31,7,5,193,397,867,1495,3435,7441,0,0, + 1,1,1,1,17,59,97,233,389,597,1013,1631,483,0,0, + 1,1,1,11,7,41,107,53,111,125,1513,1921,7647,0,0, + 1,3,3,3,31,29,117,3,365,971,1139,2123,5913,0,0, + 1,1,1,13,23,3,1,167,475,639,1811,3841,3081,0,0, + 1,1,5,3,5,47,65,123,275,783,95,119,7591,0,0, + 1,3,1,15,13,33,93,237,467,431,705,4013,4035,0,0, + 1,3,5,1,19,7,101,231,155,737,1381,3343,2051,0,0, + 1,1,5,9,15,49,45,163,433,765,2031,201,2589,0,0, + 1,3,7,9,19,41,31,89,93,623,105,745,4409,0,0, + 1,1,5,1,11,45,127,85,389,439,829,477,7965,0,0, + 1,3,3,15,13,41,1,207,435,585,311,1725,2737,0,0, + 1,3,3,3,13,49,21,31,197,799,1411,2959,7133,0,0, + 1,3,1,3,7,43,9,141,133,579,1059,93,957,0,0, + 1,3,7,1,15,51,23,213,381,851,699,2261,3419,0,0, + 1,3,5,9,25,35,67,141,35,409,1423,365,1645,0,0, + 1,3,3,11,15,33,27,181,93,87,1761,3511,1353,0,0, + 1,3,5,3,25,63,111,137,321,819,705,1547,7271,0,0, + 1,3,1,1,5,57,99,59,411,757,1371,3953,3695,0,0, + 1,3,5,11,11,21,25,147,239,455,709,953,7175,0,0, + 1,3,3,15,5,53,91,205,341,63,723,1565,7135,0,0, + 1,1,7,15,11,21,99,79,63,593,2007,3629,5271,0,0, + 1,3,3,1,9,21,45,175,453,435,1855,2649,6959,0,0, + 1,1,3,15,15,33,121,121,251,431,1127,3305,4199,0,0, + 1,1,1,9,31,15,71,29,345,391,1159,2809,345,0,0, + 1,3,7,1,23,29,95,151,327,727,647,1623,2971,0,0, + 1,1,7,7,9,29,79,91,127,909,1293,1315,5315,0,0, + 1,1,5,11,13,37,89,73,149,477,1909,3343,525,0,0, + 1,3,5,7,5,59,55,255,223,459,2027,237,4205,0,0, + 1,1,1,7,27,11,95,65,325,835,907,3801,3787,0,0, + 1,1,1,11,27,33,99,175,51,913,331,1851,4133,0,0, + 1,3,5,5,13,37,31,99,273,409,1827,3845,5491,0,0, + 1,1,3,7,23,19,107,85,283,523,509,451,421,0,0, + 1,3,5,7,13,9,51,81,87,619,61,2803,5271,0,0, + 1,1,1,15,9,45,35,219,401,271,953,649,6847,0,0, + 1,1,7,11,9,45,17,219,169,837,1483,1605,2901,0,0, + 1,1,7,7,21,43,37,33,291,359,71,2899,7037,0,0, + 1,3,3,13,31,53,37,15,149,949,551,3445,5455,0,0, + 1,3,1,5,19,45,81,223,193,439,2047,3879,789,0,0, + 1,1,7,3,11,63,35,61,255,563,459,2991,3359,0,0, + 1,1,5,9,13,49,47,185,239,221,1533,3635,2045,0,0, + 1,3,7,3,25,37,127,223,51,357,483,3837,6873,0,0, + 1,1,7,9,31,37,113,31,387,833,1243,1543,5535,0,0, + 1,3,1,9,23,59,119,221,73,185,2007,2885,2563,0,0, + 1,1,1,13,7,33,53,179,67,185,1541,1807,4659,0,0, + 1,3,1,11,31,37,23,215,269,357,207,645,4219,0,0, + 1,3,3,13,19,27,107,55,91,71,1695,1815,89,0,0, + 1,1,3,15,3,19,35,247,49,529,1523,3317,6151,0,0, + 1,1,7,7,23,25,107,139,483,503,1277,243,7879,0,0, + 1,3,3,13,3,15,11,197,135,839,985,275,5527,0,0, + 1,3,5,3,25,47,95,21,113,307,1001,3065,295,0,0, + 1,1,3,9,19,19,99,213,363,449,735,2851,2521,0,0, + 1,1,3,9,5,49,63,61,157,857,497,2801,6987,0,0, + 1,1,1,9,1,41,109,119,499,939,867,3675,8023,0,0, + 1,3,1,1,13,33,109,123,289,3,1271,2773,4265,0,0, + 1,3,1,11,9,57,83,221,95,43,1189,457,7133,0,0, + 1,1,7,3,11,49,33,219,229,289,685,3359,4495,0,0, + 1,3,1,3,19,43,67,193,41,771,407,81,3891,0,0, + 1,1,7,11,5,29,51,175,297,539,1,2245,6439,0,0, + 1,3,7,15,21,33,117,183,511,489,1283,3281,5979,0,0, + 1,3,7,5,9,3,125,147,359,549,369,3049,2405,0,0, + 1,3,5,7,19,5,65,97,483,377,1523,1457,2995,0,0, + 1,1,5,1,11,21,41,113,277,131,1475,1043,2367,0,0, + 1,3,3,1,15,17,101,69,443,865,817,1421,5231,0,0, + 1,1,3,3,3,55,95,99,75,195,1929,3931,5855,0,0, + 1,3,1,3,19,23,93,213,241,551,1307,585,7729,0,0, + 1,3,1,11,23,15,53,249,467,519,95,741,409,0,0, + 1,1,1,15,29,37,43,203,233,877,77,1933,2729,0,0, + 1,3,7,11,27,39,43,161,255,15,1463,833,495,0,0, + 1,1,7,11,3,53,81,67,375,823,1903,3061,395,0,0, + 1,1,1,1,15,37,93,233,247,501,1321,3275,5409,0,0, + 1,3,3,7,7,11,5,105,139,983,1239,531,3881,0,0, + 1,1,5,3,19,49,107,227,361,101,355,2649,7383,0,0, + 1,1,7,5,25,41,101,121,209,293,1937,2259,5557,0,0, + 1,1,3,7,7,1,9,13,463,1019,995,3159,107,0,0, + 1,3,5,11,5,35,127,97,261,789,807,807,6257,0,0, + 1,1,7,5,11,13,45,91,417,101,1973,3645,2107,0,0, + 1,1,3,7,5,63,57,49,203,157,115,1393,8117,0,0, + 1,3,5,5,3,43,15,155,127,489,1165,3701,4867,0,0, + 1,1,7,7,29,29,69,215,415,367,371,1901,6075,0,0, + 1,1,1,3,11,33,89,149,433,705,1437,1597,505,0,0, + 1,3,5,1,13,37,19,119,5,581,2037,1633,2099,0,0, + 1,3,7,13,5,49,103,245,215,515,133,2007,1933,0,0, + 1,3,1,9,1,3,25,197,253,387,1683,2267,221,0,0, + 1,3,5,15,21,9,73,201,405,999,437,3877,6045,0,0, + 1,1,3,1,31,55,25,83,421,395,1807,2129,7797,0,0, + 1,1,3,1,23,21,121,183,125,347,143,3685,4317,0,0, + 1,3,3,3,17,45,17,223,267,795,1815,1309,155,0,0, + 1,1,1,15,17,59,5,133,15,715,1503,153,2887,0,0, + 1,1,1,1,27,13,119,77,243,995,1851,3719,4695,0,0, + 1,3,1,5,31,49,43,165,49,609,1265,1141,505,0,0, + 1,1,7,13,11,63,21,253,229,585,1543,3719,4141,0,0, + 1,3,7,11,23,27,17,131,295,895,1493,1411,3247,0,0, + 1,1,5,9,29,7,97,15,113,445,859,1483,1121,0,0, + 1,3,1,9,13,49,99,107,323,201,681,3071,5281,0,0, + 1,1,1,15,9,19,61,161,7,87,587,2199,2811,0,0, + 1,3,3,15,15,19,95,45,299,829,981,3479,487,0,0, + 1,1,1,9,3,37,7,19,227,13,397,513,1257,0,0, + 1,1,5,15,15,13,17,111,135,929,1145,811,1801,0,0, + 1,3,1,3,27,57,31,19,279,103,693,631,3409,0,0, + 1,1,1,1,15,13,67,83,23,799,1735,2063,3363,0,0, + 1,3,3,7,3,1,61,31,41,533,2025,4067,6963,0,0, + 1,1,5,7,17,27,81,79,107,205,29,97,4883,0,0, + 1,1,1,5,19,49,91,201,283,949,651,3819,5073,0,0, + 1,1,7,9,11,13,73,197,37,219,1931,3369,6017,0,0, + 1,1,7,15,11,7,75,205,7,819,399,661,6487,0,0, + 1,3,3,3,27,37,95,41,307,165,1077,3485,563,0,0, + 1,3,5,3,21,49,57,179,109,627,1789,431,2941,0,0, + 1,1,7,5,11,19,43,137,149,679,1543,245,1381,0,0, + 1,3,5,5,15,3,69,81,135,159,1363,3401,6355,0,0, + 1,3,5,1,9,61,49,53,319,25,1647,1297,615,0,0, + 1,3,5,11,31,43,9,101,71,919,335,3147,5823,0,0, + 1,3,1,1,15,5,29,109,511,945,867,3677,6915,0,0, + 1,3,3,15,17,49,91,111,215,29,1879,97,2505,0,0, + 1,3,1,13,19,61,11,111,163,777,533,1113,5339,0,0, + 1,1,7,9,17,55,117,91,455,289,557,913,4455,0,0, + 1,3,1,7,25,19,123,37,1,277,717,2965,4469,0,0, + 1,3,7,3,19,23,87,235,209,457,2041,2893,1805,0,0, + 1,3,3,5,5,43,23,61,351,791,59,2009,2909,0,0, + 1,1,3,7,5,1,27,231,385,257,1261,2701,1807,0,0, + 1,3,1,1,27,19,87,253,131,685,1743,3983,2651,0,0, + 1,3,7,11,21,17,11,81,191,641,1821,3005,7251,0,0, + 1,3,3,5,15,31,41,213,55,931,1953,49,6037,0,0, + 1,1,7,15,7,27,65,223,113,79,1875,911,5445,0,0, + 1,3,7,7,23,55,51,167,495,25,1585,3447,799,0,0, + 1,1,3,7,27,15,95,193,337,415,975,3085,967,0,0, + 1,1,7,15,19,7,93,41,433,551,401,3169,3971,0,0, + 1,1,7,11,13,15,53,69,433,59,1117,3359,6231,0,0, + 1,1,7,3,23,5,115,201,225,109,1903,3897,6265,0,0, + 1,1,1,11,17,1,39,143,361,659,1105,23,4923,0,0, + 1,1,1,9,27,57,85,227,261,119,1881,3965,6999,0,0, + 1,3,7,7,15,7,107,17,315,49,1591,905,7789,0,0, + 1,3,1,7,29,3,47,237,157,769,839,3199,3195,0,0, + 1,1,3,15,25,39,63,15,111,857,881,1505,7671,0,0, + 1,1,7,1,3,35,41,215,99,895,1025,1483,4707,0,0, + 1,3,5,1,1,31,25,247,113,841,397,1825,6969,0,0, + 1,1,3,5,19,41,49,243,225,973,241,175,1041,0,0, + 1,1,1,7,15,15,105,141,83,75,1675,3523,5219,0,0, + 1,1,7,5,13,27,47,199,445,841,959,1157,2209,0,0, + 1,3,5,15,23,31,31,81,85,33,785,2639,7799,0,0, + 1,1,5,13,21,3,47,99,235,943,1731,2467,7891,0,0, + 1,1,1,3,17,53,85,219,73,131,1339,875,1191,0,0, + 1,1,5,7,17,63,113,7,185,557,749,3563,4973,0,0, + 1,3,3,15,15,21,43,111,155,689,345,423,3597,0,0, + 1,1,5,1,15,29,93,5,361,713,695,3937,425,0,0, + 1,3,7,7,13,41,115,175,315,937,123,2841,4457,0,0, + 1,1,3,11,25,5,103,53,423,811,657,399,7257,0,0, + 1,1,1,1,1,13,101,211,383,325,97,1703,4429,0,0, + 1,3,7,9,31,45,83,157,509,701,841,1105,3643,0,0, + 1,1,1,7,1,9,69,17,129,281,1161,2945,7693,0,0, + 1,3,7,1,11,29,51,143,77,433,1723,2317,5641,0,0, + 1,1,1,1,21,43,13,67,177,505,1629,1267,4885,0,0, + 1,1,3,11,27,63,111,47,233,781,453,1679,3209,0,0, + 1,1,3,13,29,27,119,141,493,971,461,1159,633,0,0, + 1,1,3,15,23,5,79,215,163,149,1805,2399,61,0,0, + 1,3,5,13,19,5,1,39,409,561,709,829,1357,0,0, + 1,3,3,13,19,43,9,177,449,447,73,2107,5669,0,0, + 1,3,5,1,23,13,63,109,203,593,829,4017,6881,0,0, + 1,1,5,7,3,9,53,175,391,169,1283,3793,4451,0,0, + 1,1,5,7,29,43,9,5,209,77,927,2941,8145,0,0, + 1,3,5,15,17,49,5,143,131,771,1685,925,2175,0,0, + 1,1,3,11,27,27,27,159,161,1015,1587,4049,1983,0,0, + 1,3,1,3,23,57,119,67,481,577,389,3319,5325,0,0, + 1,3,5,1,19,39,87,61,329,657,1773,31,1707,0,0, + 1,1,3,1,5,25,15,241,131,815,1751,3029,8039,0,0, + 1,3,3,13,27,13,77,87,437,57,621,1031,7891,0,0, + 1,3,1,13,23,51,117,37,331,745,605,3179,4713,0,0, + 1,1,5,5,19,17,99,167,87,721,737,789,2165,0,0, + 1,3,5,13,1,51,119,211,165,299,1327,3053,3343,0,0, + 1,1,5,15,29,45,17,129,67,345,1553,2705,7369,0,0, + 1,1,1,9,23,7,13,209,7,407,317,3077,7287,0,0, + 1,1,1,5,9,59,89,3,487,451,505,2499,7563,0,0, + 1,3,1,7,21,1,21,203,101,417,1389,2751,1397,0,0, + 1,3,7,13,7,31,3,247,349,485,1259,549,6321,0,0, + 1,1,7,7,27,33,107,197,293,729,1753,2571,103,0,0, + 1,3,5,9,25,35,5,253,137,213,2041,3387,1809,0,0, + 1,1,7,13,15,35,67,83,295,175,839,2831,839,0,0, + 1,3,3,11,3,17,55,141,247,991,117,3799,1221,0,0, + 1,1,5,1,11,37,87,233,457,653,899,2933,3105,0,0, + 1,1,3,15,3,31,67,167,437,9,651,1109,1139,0,0, + 1,1,3,1,7,63,67,17,11,883,1855,1941,4751,0,0, + 1,3,7,9,19,33,113,117,495,39,1795,2561,5519,0,0, + 1,1,7,5,1,3,103,37,201,223,1101,877,6483,0,0, + 1,1,5,9,29,49,51,33,439,917,861,1321,2135,0,0, + 1,1,3,3,1,5,17,93,217,619,613,1357,6095,0,0, + 1,3,1,11,3,21,5,41,15,175,843,2937,6849,0,0, + 1,3,3,7,9,57,55,127,79,287,445,2205,7989,0,0, + 1,1,7,13,23,17,93,129,157,135,1747,1813,4183,0,0, + 1,1,1,5,31,59,99,33,425,329,887,367,1761,0,0, + 1,1,7,9,17,53,77,139,435,387,49,3649,1773,0,0, + 1,3,3,15,21,57,45,161,331,719,273,3479,4173,0,0, + 1,1,3,9,3,3,105,201,373,877,919,1263,6649,0,0, + 1,3,1,15,13,43,13,99,73,163,353,3569,5601,0,0, + 1,3,7,3,5,9,69,177,449,47,781,1125,4245,0,0, + 1,1,1,5,3,45,1,123,409,903,205,2057,7637,0,0, + 1,3,5,9,19,47,87,135,481,799,101,3409,2241,0,0, + 1,3,1,13,3,25,15,27,181,967,669,2577,7249,0,0, + 1,1,7,3,31,5,103,53,1,911,1209,3697,6685,0,0, + 1,1,3,1,5,5,49,135,281,747,761,2973,7963,0,0, + 1,3,3,5,19,61,125,199,299,515,1365,369,7027,0,0, + 1,3,1,7,5,41,63,229,283,571,147,447,657,0,0, + 1,3,1,11,5,15,55,7,259,61,27,1429,5631,0,0, + 1,1,5,1,3,53,51,253,155,553,1293,3735,6567,0,0, + 1,3,5,9,5,41,21,159,101,785,1981,3799,7693,0,0, + 1,3,7,7,9,3,95,105,129,213,1215,1027,5699,0,0, + 1,1,3,3,29,13,9,253,449,321,341,2879,171,0,0, + 1,3,7,11,21,11,75,35,43,965,675,2217,7175,0,0, + 1,1,5,15,31,5,29,137,311,751,47,1367,5921,0,0, + 1,1,3,15,17,1,45,69,55,649,835,569,7615,0,0, + 1,3,1,13,31,7,23,15,391,145,1845,1825,1403,0,0, + 1,1,3,15,5,9,79,77,105,399,1933,2503,4781,0,0, + 1,3,1,3,17,47,19,13,107,475,759,2933,3761,0,0, + 1,1,7,11,3,7,121,209,397,877,293,847,7039,0,0, + 1,1,1,15,29,45,5,109,335,461,143,931,4045,0,0, + 1,3,1,7,11,57,73,89,201,173,803,3953,5205,0,0, + 1,1,5,11,11,33,37,29,263,1019,657,1453,7807,0,0, + 1,3,3,13,31,25,37,47,261,607,1703,2603,417,0,0, + 1,1,1,1,31,61,45,115,275,239,1989,1897,4329,0,0, + 1,3,5,3,31,3,11,173,335,579,1193,2219,7875,0,0, + 1,1,7,9,29,45,13,67,399,177,1293,3865,2225,0,0, + 1,1,7,11,11,51,121,227,469,905,929,2635,4165,0,0, + 1,3,7,9,13,39,55,167,23,147,1603,2083,4645,0,0, + 1,1,3,15,27,53,11,155,157,629,259,3009,4605,0,0, + 1,3,1,7,15,47,51,1,259,603,887,2833,6581,0,0, + 1,3,5,3,1,47,91,43,361,571,29,1453,4269,0,0, + 1,1,3,9,11,51,55,23,415,277,1423,3475,1527,0,0, + 1,1,3,11,29,49,101,75,299,709,805,4037,4389,0,0, + 1,1,7,3,23,1,37,51,379,771,1301,3717,6673,0,0, + 1,1,5,3,23,11,125,177,375,665,951,1577,2603,0,0, + 1,1,1,1,1,5,71,255,21,459,467,2083,5415,0,0, + 1,1,5,13,23,29,109,157,363,971,549,647,1177,0,0, + 1,1,3,9,7,15,101,3,365,213,745,1155,6099,0,0, + 1,3,5,15,15,19,47,179,303,521,1279,219,2415,0,0, + 1,3,3,13,27,11,83,165,369,989,261,3933,4809,0,0, + 1,1,3,11,31,59,1,185,53,703,1471,2935,1107,0,0, + 1,3,3,7,25,3,81,27,93,521,433,2859,5861,0,0, + 1,3,3,11,29,15,49,167,315,927,543,3473,4307,0,0, + 1,3,1,3,29,33,53,15,183,691,703,1311,3393,0,0, + 1,3,5,13,23,49,3,11,1,357,1407,415,7211,0,0, + 1,3,7,15,1,25,91,113,323,371,189,925,1181,0,0, + 1,3,3,3,17,59,119,199,115,223,877,2193,193,0,0, + 1,1,1,5,5,35,31,59,437,411,37,2405,3797,0,0, + 1,3,1,13,9,37,1,241,59,157,1785,1223,563,0,0, + 1,3,5,13,3,21,25,95,15,745,85,701,5361,0,0, + 1,3,7,1,31,33,111,195,35,913,2013,2951,6611,0,0, + 1,3,5,1,19,3,75,119,111,409,951,1457,4957,0,0, + 1,3,1,15,19,59,3,155,237,657,1967,3323,6235,0,0, + 1,1,5,1,3,19,45,105,377,881,167,2255,4483,0,0, + 1,1,7,7,13,13,99,89,201,279,161,2483,6001,0,0, + 1,1,7,3,13,17,97,129,137,377,1519,183,3725,0,0, + 1,1,7,9,9,5,45,135,115,181,1685,3505,4387,0,0, + 1,1,1,1,19,35,69,113,305,419,949,2969,247,0,0, + 1,1,5,13,23,61,13,139,501,811,67,1501,6493,0,0, + 1,1,3,13,15,41,27,217,293,13,145,2631,6991,0,0, + 1,3,3,13,15,37,71,123,285,49,627,1283,5993,0,0, + 1,3,3,11,9,25,11,1,203,353,1347,1999,2799,0,0, + 1,3,5,1,7,49,101,231,499,63,1977,2207,7829,0,0, + 1,1,7,1,17,15,115,139,381,943,623,4037,2971,0,0, + 1,1,3,5,13,55,23,87,139,795,1669,1375,1185,0,0, + 1,3,3,5,5,45,97,253,241,333,645,555,7867,0,0, + 1,3,5,1,1,1,89,27,407,509,1433,609,2355,0,0, + 1,3,7,1,27,29,5,157,495,811,1293,1143,827,0,0, + 1,1,3,3,25,49,127,111,191,3,845,1383,2521,0,0, + 1,1,5,7,5,51,101,155,237,461,831,3091,3851,0,0, + 1,3,7,1,29,35,105,91,285,705,131,395,6011,0,0, + 1,3,5,3,13,21,83,173,221,827,1775,1931,6727,0,0, + 1,1,3,5,3,25,95,115,205,569,1447,933,6425,0,0, + 1,1,7,9,31,3,17,175,145,447,1321,1069,6527,0,0, + 1,1,3,3,23,1,79,51,421,419,873,3939,1801,0,0, + 1,1,5,1,3,39,15,85,169,669,919,397,5579,0,0, + 1,3,5,1,21,61,87,217,251,619,1091,4009,229,0,0, + 1,1,1,11,23,55,85,121,363,867,315,447,3373,0,0, + 1,3,3,13,29,19,89,85,137,469,1873,2765,3975,0,0, + 1,3,7,13,19,63,61,77,67,361,11,1787,4703,0,0, + 1,1,3,11,7,15,127,105,179,857,1671,3647,3389,0,0, + 1,1,1,7,19,21,99,161,499,519,1287,2973,479,0,0, + 1,1,3,13,29,51,95,251,55,519,1955,2881,5951,0,0, + 1,1,3,11,23,63,121,237,175,311,701,1539,2383,0,0, + 1,1,7,5,5,45,73,97,5,153,715,2037,3353,0,0, + 1,1,1,3,13,7,67,173,425,843,1497,2729,5193,0,0, + 1,1,7,1,23,3,119,11,77,141,1905,2269,4269,0,0, + 1,1,7,15,1,23,79,251,439,603,405,2449,6383,0,0, + 1,3,7,11,29,27,47,255,47,661,1967,1007,3689,0,0, + 1,3,7,5,19,39,35,115,417,373,291,329,603,0,0, + 1,3,1,9,11,33,27,193,207,423,1311,1369,7307,0,0, + 1,1,3,11,9,29,83,17,497,493,329,3141,5935,0,0, + 1,3,1,5,31,51,29,171,51,493,1621,3501,4091,0,0, + 1,1,5,9,21,43,105,207,245,363,1191,699,1139,0,0, + 1,1,3,11,19,5,81,119,247,169,1337,45,6565,0,0, + 1,3,1,11,3,51,3,101,159,11,253,299,5043,0,0, + 1,3,1,5,11,53,85,39,57,645,2007,1039,3627,0,0, + 1,3,5,3,17,61,97,165,415,357,283,601,5505,0,0, + 1,3,7,3,9,51,49,85,3,227,137,309,243,0,0, + 1,1,5,3,11,59,11,131,409,703,455,123,6727,0,0, + 1,3,7,9,25,49,21,171,287,379,667,313,713,0,0, + 1,1,3,9,7,35,47,3,367,581,1627,1665,3905,0,0, + 1,3,1,1,29,57,35,55,255,653,823,2197,6179,0,0, + 1,3,7,15,17,15,117,83,359,163,115,2999,5373,0,0, + 1,1,5,3,21,61,35,97,71,687,207,2917,1049,0,0, + 1,1,1,15,13,15,125,81,263,661,417,3243,1669,0,0, + 1,1,7,3,3,19,111,193,443,339,659,1211,1557,0,0, + 1,3,1,3,27,3,3,173,391,213,803,3281,3207,0,0, + 1,1,5,15,19,1,7,211,157,603,403,1387,1583,0,0, + 1,3,5,13,17,53,125,13,339,723,521,413,5801,10451,0, + 1,1,3,13,29,9,99,77,141,609,1533,983,2039,51,0, + 1,1,3,11,21,55,5,51,423,309,525,3715,3025,15055,0, + 1,1,3,7,9,21,77,171,239,341,1653,1093,2273,10723,0, + 1,1,1,15,31,15,23,35,317,869,1917,1415,4313,3687,0, + 1,1,1,5,21,25,99,167,439,453,473,431,6665,4989,0, + 1,1,7,9,31,47,81,83,345,43,1363,1885,3155,3185,0, + 1,3,7,1,31,17,61,185,341,129,547,717,2071,9991,0, + 1,3,1,13,23,61,77,217,455,77,1263,1601,3501,14953,0, + 1,1,7,7,19,19,1,229,431,943,1069,1949,1289,15729,0, + 1,1,3,5,1,35,97,251,487,459,1265,1739,165,10365,0, + 1,3,5,3,11,25,79,175,383,545,187,197,4329,3363,0, + 1,1,3,3,29,9,63,55,175,277,431,2549,2629,6409,0, + 1,1,3,15,17,21,79,139,99,135,1763,1805,3471,5439,0, + 1,1,3,9,9,15,35,119,289,835,769,3843,4119,4421,0, + 1,1,1,5,19,19,67,199,307,815,1367,1231,3927,6593,0, + 1,1,3,1,29,51,121,209,431,47,1115,907,2535,9755,0, + 1,1,3,5,17,1,5,119,121,223,1719,1291,3947,15891,0, + 1,3,1,15,29,25,3,131,373,307,645,3513,1289,1987,0, + 1,3,3,11,29,45,105,179,331,465,891,1315,403,3057,0, + 1,1,5,13,17,59,77,127,485,855,1147,3093,891,9869,0, + 1,1,1,7,23,27,31,203,285,463,827,685,1349,15051,0, + 1,1,1,5,29,5,107,195,31,425,19,2865,3869,11153,0, + 1,1,7,5,7,47,1,73,307,347,393,2205,7709,15121,0, + 1,1,1,13,15,61,25,131,113,369,1995,2527,4475,1745,0, + 1,1,1,1,31,63,21,253,307,281,859,3319,6721,2891,0, + 1,1,3,11,1,17,5,183,301,979,651,1685,6343,10067,0, + 1,1,5,15,23,45,99,145,263,507,1381,3425,2215,1815,0, + 1,3,1,5,11,63,85,203,411,881,1369,1237,4657,6541,0, + 1,3,3,13,17,53,121,201,269,983,215,3187,7121,6111,0, + 1,3,5,15,15,5,13,143,3,313,1677,1093,3295,3387,0, + 1,1,3,13,3,23,73,17,257,965,239,1271,2803,7327,0, + 1,3,5,13,9,57,115,37,41,467,135,1403,3811,4741,0, + 1,3,7,15,9,33,39,203,351,367,1355,1403,3685,4757,0, + 1,3,5,11,31,3,113,123,203,421,1821,3151,2375,4419,0, + 1,1,1,7,21,63,99,23,133,79,991,1755,4989,4709,0, + 1,3,5,1,25,63,113,239,49,443,173,1261,3201,10599,0, + 1,3,3,13,3,25,101,169,23,585,327,1327,111,10059,0, + 1,3,3,5,19,1,33,89,437,213,1933,1741,2603,5625,0, + 1,3,1,3,15,15,25,139,73,335,237,2461,3101,14951,0, + 1,3,5,1,31,15,31,187,177,659,1339,3767,4975,7123,0, + 1,3,1,3,25,19,47,89,107,107,649,683,3123,11085,0, + 1,3,7,9,15,21,101,25,11,625,1555,675,3893,5805,0, + 1,1,1,5,7,49,123,21,439,369,207,535,4619,14665,0, + 1,1,5,7,1,25,103,185,99,239,1093,1561,6177,4039,0, + 1,3,7,5,29,21,43,103,343,973,1561,2975,7467,7947,0, + 1,1,7,9,19,3,13,23,461,813,1191,985,559,3317,0, + 1,3,5,5,27,31,79,15,365,901,1949,117,3619,13311,0, + 1,3,5,7,5,33,67,199,425,189,1691,3099,815,1677,0, + 1,1,7,11,13,29,73,137,265,601,445,3893,2511,8047,0, + 1,1,3,1,13,5,57,101,357,391,335,601,1359,1065,0, + 1,1,1,1,25,57,27,115,31,873,611,2125,447,13585,0, + 1,3,3,13,27,17,73,11,359,33,1153,271,4537,15141,0, + 1,3,7,3,11,63,103,61,59,629,1629,3279,3919,3177,0, + 1,1,5,15,3,63,85,193,381,165,175,3247,2501,4209,0, + 1,1,5,15,1,33,59,219,487,193,1557,703,2907,7953,0, + 1,1,7,3,9,3,105,95,389,991,21,3841,6983,285,0, + 1,1,1,1,1,31,25,137,117,67,1283,1963,6591,15541,0, + 1,3,5,11,7,15,127,89,453,777,1827,2311,7661,11833,0, + 1,1,7,13,19,29,79,165,223,453,2039,3961,6467,5481,0, + 1,3,3,7,17,41,43,157,323,3,1001,2109,4513,12127,0, + 1,1,5,9,31,57,3,217,113,271,1663,1367,6949,8165,0, + 1,1,7,15,27,35,81,235,61,205,525,311,6357,2527,0, + 1,3,1,9,19,29,71,207,321,1011,1615,1333,3459,6681,0, + 1,3,7,7,3,57,41,19,25,397,565,1837,7625,11813,0, + 1,3,3,1,27,47,31,79,441,961,1255,423,2405,913,0, + 1,3,3,13,3,29,69,227,85,201,395,3199,3869,13099,0, + 1,3,3,7,29,61,99,7,27,227,945,873,475,4363,0, + 1,3,5,13,19,21,57,149,217,443,565,453,5487,10981,0, + 1,3,3,1,9,27,47,191,35,395,1429,4079,6871,8013,0, + 1,3,5,15,5,43,9,79,279,563,1125,985,8117,4099,0, + 1,3,5,1,13,41,21,117,287,667,701,1483,8167,13283,0, + 1,3,1,3,15,15,59,5,383,509,1657,3977,7697,10941,0, + 1,3,1,1,17,29,19,23,377,45,981,1631,3557,6749,0, + 1,3,3,9,9,51,9,193,345,361,1679,3333,713,5387,0, + 1,3,5,5,17,45,97,17,385,349,105,2245,7295,14393,0, + 1,3,7,3,19,51,35,99,79,301,1563,399,5879,14675,0, + 1,1,7,15,13,53,55,203,417,161,2033,1845,6763,3585,0, + 1,1,3,3,7,23,11,43,241,309,1453,3147,2619,3163,0, + 1,1,1,11,17,1,17,137,443,465,993,3217,7879,14607,0, + 1,1,7,13,29,49,71,217,291,793,135,21,2503,11091,0, + 1,3,1,11,31,51,121,227,377,157,1457,1317,5625,6217,0, + 1,1,3,7,23,61,47,93,79,617,1805,2403,5513,16335,0, + 1,3,5,11,23,25,41,11,495,587,1223,3107,1469,15223,0, + 1,3,7,7,9,1,1,49,23,723,1761,3717,7375,10875,0, + 1,3,3,11,25,37,57,63,309,603,183,285,1663,5627,0, + 1,3,7,11,19,25,25,201,391,257,529,1645,1,15111,0, + 1,3,3,9,11,43,91,65,5,959,301,1015,6343,3453,0, + 1,3,3,11,17,17,103,37,77,973,575,439,49,3639,0, + 1,1,5,7,1,15,107,237,231,967,923,1101,6715,1713,0, + 1,3,1,15,9,33,29,211,245,601,1783,887,1209,11785,0, + 1,3,3,7,21,43,27,89,27,141,865,367,1379,4063,0, + 1,3,7,7,15,17,15,15,131,649,1955,3289,3983,10689,0, + 1,3,1,5,17,7,125,69,359,981,1345,933,5281,7113,0, + 1,1,5,9,17,7,41,207,497,1015,493,891,3563,3541,0, + 1,3,5,11,27,3,47,31,303,1007,2047,2203,6257,8369,0, + 1,1,1,15,25,15,89,51,217,357,1133,1917,213,3365,0, + 1,1,5,13,29,23,123,207,429,805,819,2357,6313,11019,0, + 1,1,3,7,19,15,41,73,279,11,1089,3107,7737,15953,0, + 1,3,5,7,7,15,41,73,493,457,1731,1139,2513,12373,0, + 1,3,5,9,17,5,55,155,173,1005,529,3175,7667,4747,0, + 1,1,7,7,5,21,105,31,205,847,1033,3167,2347,8499,0, + 1,3,5,3,11,17,59,189,179,1007,33,3287,4813,8177,0, + 1,3,3,13,27,47,47,171,413,875,1081,1259,7139,8645,0, + 1,3,5,7,25,21,51,29,361,293,51,1119,1453,5283,0, + 1,3,7,7,29,55,103,199,511,341,1957,3987,2855,1279,0, + 1,1,1,9,23,51,61,63,391,37,55,3771,6517,15913,0, + 1,1,1,9,3,19,13,147,453,855,1321,189,5043,11215,0, + 1,3,3,13,23,3,87,155,401,981,607,3413,995,6473,0, + 1,3,1,9,29,47,95,123,421,353,1867,2609,2569,14083,0, + 1,1,5,13,25,39,29,111,125,545,1493,2371,6361,6307,0, + 1,3,3,11,13,31,87,75,27,393,921,3655,3343,16349,0, + 1,1,5,9,19,19,7,129,223,715,433,1627,4463,2951,0, + 1,1,7,1,31,13,49,33,89,43,1529,725,3809,3427,0, + 1,1,7,3,1,27,45,9,309,875,659,2661,553,7069,0, + 1,1,7,15,13,37,61,19,125,683,1227,2255,1455,9339,0, + 1,3,5,7,19,7,71,21,465,645,1885,873,7405,1913,0, + 1,3,1,11,11,35,79,61,79,57,1603,3719,6323,16371,0, + 1,1,7,1,29,57,85,21,205,37,2045,683,4901,8223,0, + 1,1,5,13,31,31,65,131,259,535,967,3943,2605,2089,0, + 1,1,7,9,27,61,39,243,207,41,1909,3279,1331,4635,0, + 1,3,3,5,11,63,105,19,169,95,773,3175,1869,1797,0, + 1,3,3,15,13,33,107,197,153,795,1477,105,4965,991,0, + 1,3,7,11,11,37,23,149,197,3,1035,3857,553,1059,0, + 1,3,1,3,17,29,89,189,193,59,1477,3517,2565,7739,0, + 1,1,1,9,23,3,25,163,469,305,1791,3393,6141,8119,0, + 1,3,5,7,7,41,19,101,179,487,1071,2761,8043,5103,0, + 1,1,7,9,1,21,101,103,349,85,1841,1033,4473,3563,0, + 1,1,3,13,23,61,39,27,479,13,45,1371,7897,10637,0, + 1,1,5,9,17,61,71,55,355,99,1695,3053,839,959,0, + 1,1,3,1,7,27,87,221,327,241,461,3177,5933,8299,0, + 1,3,7,9,5,41,111,245,447,263,1363,1767,6331,3355,0, + 1,3,3,13,15,11,15,169,429,149,1965,2477,7733,2499,0, + 1,1,5,15,15,47,25,33,469,701,773,2747,1533,14633,0, + 1,3,1,5,19,57,37,75,423,11,685,2487,1779,8797,0, + 1,3,1,5,19,41,67,99,333,991,953,3221,939,4197,0, + 1,3,1,15,11,39,25,1,159,679,465,1611,5799,2537,0, + 1,1,5,11,5,37,37,7,101,703,235,23,2209,12799,0, + 1,1,7,3,11,23,71,215,45,269,1539,3625,5773,6889,0, + 1,3,5,15,27,33,105,109,205,653,821,435,1087,2495,0, + 1,1,3,5,11,39,53,213,41,385,1425,25,5553,12523,0, + 1,3,5,15,29,49,13,253,505,407,985,2569,6727,4761,0, + 1,1,1,3,29,17,69,47,25,819,1145,2479,1183,3343,0, + 1,3,1,15,25,61,43,55,279,579,361,355,6101,3143,0, + 1,3,5,11,3,59,125,101,451,495,1711,3443,3625,15579,0, + 1,3,1,11,25,61,49,219,23,795,481,3609,3691,15419,0, + 1,3,7,5,9,59,49,233,345,143,181,3587,3041,1219,0, + 1,3,7,13,9,31,39,137,261,919,1367,3145,4659,5875,0, + 1,1,3,3,27,43,95,65,301,915,31,451,7743,7277,0, + 1,3,1,5,23,37,53,31,203,453,71,1585,6011,16369,0, + 1,1,5,1,15,47,91,227,297,45,1415,3647,7811,14015,0, + 1,1,1,1,29,27,93,121,169,69,1361,2907,1867,7017,0, + 1,3,1,7,23,53,77,41,25,873,1333,3889,3239,1771,0, + 1,1,1,7,31,27,87,81,167,343,1981,2499,7749,15747,0, + 1,3,5,13,1,17,97,37,81,645,1167,3547,7769,10731,0, + 1,1,7,5,9,17,31,55,151,463,1041,2303,4015,3737,0, + 1,1,3,11,31,9,81,213,95,215,2031,2129,4299,3021,0, + 1,1,1,3,25,25,115,229,101,441,783,1729,7905,2375,0, + 1,1,5,9,3,19,73,35,379,493,1333,1647,13,197,0, + 1,1,7,9,3,55,99,43,281,9,73,2477,8183,11055,0, + 1,3,7,13,25,19,27,195,469,175,355,1861,7255,15377,0, + 1,1,3,11,15,19,115,31,413,835,697,879,6515,13465,0, + 1,3,3,15,3,61,105,201,151,739,49,3963,2573,3303,0, + 1,3,5,7,23,5,11,215,19,591,509,2887,1631,4391,0, + 1,3,3,3,25,1,109,5,363,545,1745,503,827,4677,0, + 1,1,3,15,1,45,121,141,497,745,1825,2041,2561,8153,0, + 1,3,1,11,29,7,71,241,7,39,1379,2479,7483,7195,0, + 1,1,7,11,3,27,39,97,339,217,1409,1569,4761,1567,0, + 1,1,5,15,11,53,87,213,297,923,393,717,3297,16123,0, + 1,1,1,11,27,41,121,49,225,379,1305,319,2461,5445,0, + 1,1,5,5,25,3,121,23,47,843,1679,1427,6393,4199,0, + 1,1,5,13,17,3,17,25,161,487,121,361,1375,10745,0, + 1,1,7,3,3,37,7,245,107,107,745,2415,2131,11419,0, + 1,1,5,3,3,23,67,91,281,387,465,905,883,9775,0, + 1,3,7,15,25,55,123,49,23,983,1903,2589,2073,7823,0, + 1,1,5,11,25,17,63,229,267,175,1759,1947,479,11089,0, + 1,3,7,3,11,37,83,95,415,1003,1175,2361,2117,9809,0, + 1,3,1,9,5,39,51,129,249,161,1981,2755,8057,13641,0, + 1,1,7,1,15,47,9,197,199,549,1091,2853,2331,4535,0, + 1,3,3,13,15,21,23,111,463,719,1667,377,5039,10723,0, + 1,1,3,7,23,47,39,47,307,949,1651,2525,5835,1425,0, + 1,3,3,9,23,47,111,39,251,1001,179,3985,535,15435,0, + 1,1,3,13,5,45,51,123,205,651,1583,1691,1631,11975,0, + 1,1,7,9,1,29,59,27,389,497,1459,1633,521,14037,0, + 1,1,3,3,3,23,35,247,371,729,931,681,1777,8353,0, + 1,3,3,1,19,15,17,191,495,643,319,37,5691,7049,0, + 1,3,5,11,5,31,123,243,335,573,113,209,4825,7783,0, + 1,3,7,7,29,19,25,191,89,515,55,3013,4523,12913,0, + 1,1,3,3,15,3,35,37,339,7,697,359,4553,1431,0, + 1,3,1,1,9,15,33,77,161,13,255,1187,6587,11715,0, + 1,3,7,7,25,57,61,171,231,43,1219,903,5623,4781,0, + 1,1,5,15,29,47,117,23,213,907,1423,369,4529,9651,0, + 1,1,5,7,15,55,105,249,401,37,1885,3779,3441,9057,0, + 1,1,5,3,3,27,49,89,335,561,1235,3251,2731,12711,0, + 1,1,1,15,29,49,37,173,25,743,1321,821,5899,9213,0, + 1,1,7,3,1,41,61,209,275,925,521,3029,1569,9277,0, + 1,3,5,13,17,1,11,171,441,119,1589,299,157,11439,0, + 1,1,5,9,13,33,27,77,363,939,1103,2135,1759,5429,0, + 1,3,7,1,17,39,49,201,49,803,2003,1193,7415,13847,0, + 1,1,5,5,17,49,39,19,311,801,1441,3263,7973,14181,0, + 1,1,3,9,9,27,59,89,81,473,1369,3121,7929,10905,0, + 1,3,3,5,17,35,35,239,379,431,501,3561,2059,9679,0, + 1,3,5,15,25,29,113,179,269,891,301,2017,7513,9379,0, + 1,3,1,11,17,35,49,149,135,661,1691,3169,3765,9003,0, + 1,3,7,15,5,21,53,241,475,271,683,2351,2181,6333,0, + 1,1,7,13,25,33,71,153,221,507,2017,2401,7545,8489,0, + 1,1,7,5,1,49,87,1,179,331,1597,3713,809,11109,0, + 1,3,1,5,5,61,93,39,479,977,1099,1291,7049,2797,0, + 1,3,1,13,19,41,57,77,5,117,125,115,3969,1345,0, + 1,1,1,9,15,9,57,7,219,41,767,23,5771,14175,0, + 1,3,7,9,17,61,1,59,227,349,63,189,3871,7919,0, + 1,3,5,5,9,29,33,203,413,701,1129,2103,1889,8377,0, + 1,1,3,1,9,17,69,115,123,1001,1,2893,3957,8593,0, + 1,1,3,1,31,41,83,91,113,195,1121,2665,6815,1189,0, + 1,1,1,13,3,59,13,123,95,103,1689,2809,5049,4055,0, + 1,1,1,15,21,41,11,167,375,589,207,1631,1597,8091,0, + 1,3,5,5,1,33,57,89,157,921,1353,2777,461,14567,0, + 1,1,5,1,25,5,51,247,1,577,463,3741,303,16059,0, + 1,1,7,5,13,7,17,87,51,987,835,93,5203,3973,0, + 1,1,7,7,3,27,7,1,135,171,231,3349,4459,2925,0, + 1,1,5,5,9,51,71,153,115,315,265,2207,4127,12631,0, + 1,1,3,15,23,59,35,121,425,921,1255,2123,5811,15937,0, + 1,3,7,7,11,21,45,57,269,395,555,783,6677,2889,0, + 1,3,5,7,31,19,73,35,465,349,1429,863,4707,6121,0, + 1,3,3,9,25,27,119,159,195,949,19,73,4511,15711,0, + 1,3,3,7,9,59,47,57,91,749,1579,1297,2445,5167,0, + 1,3,3,3,31,57,19,203,61,927,1477,2863,1305,11673,0, + 1,3,7,11,29,13,3,111,351,79,1863,2213,3273,7049,0, + 1,3,3,9,7,23,47,237,121,877,441,119,2723,3989,0, + 1,3,3,11,17,23,63,177,231,363,1451,33,2169,7251,0, + 1,1,5,11,31,41,93,229,39,1009,1061,433,2393,15401,0, + 1,1,5,15,31,37,25,135,135,897,33,3713,7663,8079,0, + 1,1,5,7,17,49,43,89,411,731,1431,3893,1635,7063,0, + 1,1,1,13,29,27,5,77,283,913,789,817,3309,475,0, + 1,1,3,1,19,21,67,77,423,551,5,1057,5469,7859,0, + 1,1,5,1,1,21,99,237,215,759,1505,1983,1517,8923,0, + 1,3,5,7,19,61,73,215,165,127,205,259,7755,15395,0, + 1,1,5,9,15,23,17,111,471,751,1923,775,6901,13095,0, + 1,1,7,1,25,5,63,141,461,687,1589,1559,7719,11349,0, + 1,1,1,3,11,63,11,27,253,439,297,1315,829,3765,0, + 1,3,1,1,9,47,127,179,173,809,241,35,7355,5049,0, + 1,3,1,11,19,63,93,1,205,977,303,3409,6529,10927,0, + 1,3,7,9,31,63,41,79,477,91,1801,3487,6885,13341,0, + 1,1,3,7,15,59,9,101,459,247,549,2855,5765,7785,0, + 1,1,7,3,13,59,71,123,93,517,1453,2389,4429,5053,0, + 1,1,5,3,19,21,77,53,81,879,1653,1637,3667,2623,0, + 1,1,1,15,17,57,65,53,407,765,417,497,5009,2175,0, + 1,3,3,7,31,13,5,203,263,17,119,1607,6773,11195,0, + 1,3,3,13,19,13,13,147,93,735,689,781,655,6853,0, + 1,1,1,1,1,25,63,159,493,987,71,1249,5859,11717,0, + 1,1,1,15,13,23,61,61,5,947,1853,3331,467,8081,0, + 1,1,3,9,19,61,65,189,95,309,283,1725,5683,15463,0, + 1,1,7,5,9,33,35,75,475,831,1445,1485,5047,9631,0, + 1,1,3,15,11,23,59,87,433,221,685,3113,4095,13819,0, + 1,1,7,15,25,29,67,17,349,353,1321,563,57,533,0, + 1,3,3,3,5,43,109,217,15,185,1895,1015,1831,10623,0, + 1,1,7,1,1,47,81,185,59,691,191,3709,1535,13347,0, + 1,1,5,1,23,57,83,217,457,771,1877,2789,8143,4797,0, + 1,1,3,7,23,35,79,49,227,205,1523,3873,4843,10505,0, + 1,1,1,1,17,43,121,95,205,35,189,2061,1693,13273,0, + 1,1,1,15,31,49,83,249,433,497,1949,1845,5215,5971,0, + 1,3,1,1,21,53,73,211,265,929,923,279,3621,9469,0, + 1,3,7,7,1,57,13,45,467,705,371,1345,1647,3411,0, + 1,3,1,11,27,29,117,163,143,669,489,3913,7891,9031,0, + 1,3,7,15,27,15,77,217,107,839,1517,1543,357,10365,0, + 1,1,1,5,31,17,107,245,345,939,1453,3645,6865,16173,0, + 1,3,5,5,9,61,43,97,453,917,945,2143,5473,5611,0, + 1,1,5,11,3,33,71,97,137,549,1605,3839,4883,2677,0, + 1,3,1,11,29,23,85,47,225,633,1613,1297,1415,15813,0, + 1,1,3,3,9,19,57,107,79,449,1951,753,6317,10377,0, + 1,1,1,5,21,3,39,187,299,517,1313,741,7259,4197,0, + 1,1,5,13,1,39,39,41,381,123,1257,3185,493,3723,0, + 1,3,7,7,3,37,15,161,129,169,555,3605,4287,15831,0, + 1,3,7,15,15,23,81,163,257,791,505,1903,2703,11919,0, + 1,3,7,7,27,63,17,147,111,851,1533,1365,5359,3315,0, + 1,3,7,1,15,5,61,143,385,261,1019,1705,1737,14485,0, + 1,3,5,5,25,17,49,229,431,567,1613,3431,2139,2981,0, + 1,3,5,11,17,57,71,241,31,1007,1695,2965,149,14125,0, + 1,1,3,11,7,49,39,101,5,501,1491,3061,225,12255,0, + 1,3,5,7,17,35,37,97,415,15,1349,997,2949,4511,0, + 1,3,1,5,25,35,99,183,161,59,1363,515,3767,3641,0, + 1,1,7,15,7,15,127,137,281,67,139,2315,3517,13371,0, + 1,1,5,15,23,49,19,79,425,805,1035,429,7707,14195,0, + 1,3,5,3,21,25,123,11,425,475,961,2995,7405,5449,0, + 1,1,7,1,21,1,75,231,451,595,719,2369,5907,1227,0, + 1,1,1,9,21,57,45,255,19,79,481,3363,3451,8399,0, + 1,1,7,13,31,49,95,69,483,427,37,4047,7057,9111,0, + 1,3,3,11,3,61,87,79,499,91,771,1987,2017,3381,0, + 1,3,1,7,5,57,1,121,155,225,501,477,6555,9863,0, + 1,3,7,11,27,49,83,213,61,283,1599,3205,2525,8553,0, + 1,1,1,9,9,49,3,51,141,33,301,2167,587,15067,0, + 1,1,1,11,7,55,99,81,191,553,953,3753,6731,1093,0, + 1,1,3,3,11,59,57,235,297,197,853,1411,3799,7527,0, + 1,3,5,3,7,7,5,201,393,95,91,3273,6285,10661,0, + 1,1,5,7,17,57,87,3,413,915,659,369,3593,14429,0, + 1,3,7,1,31,31,45,115,417,427,745,4087,953,1119,0, + 1,3,7,3,29,43,45,221,41,641,451,173,2999,12103,0, + 1,1,3,11,25,57,117,201,135,787,1525,3879,3247,8907,0, + 1,1,7,11,3,35,69,157,331,615,573,2169,3575,289,0, + 1,3,3,13,15,51,67,127,265,495,103,3145,2685,15919,0, + 1,3,5,11,31,27,65,57,153,465,1163,467,4103,4713,0, + 1,3,7,3,23,31,9,51,239,417,1597,229,2865,15199,0, + 1,3,5,3,11,45,123,217,31,765,1009,2001,3645,9407,0, + 1,3,3,9,5,23,117,83,237,1017,251,1187,2631,5151,0, + 1,1,1,7,23,55,97,141,501,305,467,4061,2369,15973,0, + 1,1,7,5,31,51,125,191,219,495,37,3337,813,241,0, + 1,3,1,1,11,39,93,109,285,147,1297,737,4051,7223,0, + 1,3,1,15,13,17,57,171,463,163,609,1681,7583,9231,0, + 1,3,1,1,23,5,51,5,205,415,419,989,4239,10943,0, + 1,1,3,15,3,13,65,145,387,59,395,1067,4143,5649,0, + 1,3,1,13,9,59,121,127,95,71,1541,1423,1753,8041,0, + 1,1,3,15,7,5,69,167,181,991,1189,4017,5935,6669,0, + 1,3,5,7,23,41,53,21,47,261,1231,2011,133,2247,0, + 1,1,1,5,17,47,77,19,331,609,1893,3965,3123,9093,0, + 1,3,1,3,9,39,103,231,249,75,373,107,1823,10801,0, + 1,3,3,7,1,51,35,111,137,879,1221,225,4285,2287,0, + 1,1,7,9,23,17,75,245,409,163,395,3731,7111,6845,0, + 1,1,3,13,29,47,75,153,497,621,1691,3187,2125,10533,0, + 1,1,7,7,9,7,55,159,255,417,1335,643,3843,3733,0, + 1,3,3,1,21,41,7,21,5,679,1655,95,5699,5785,0, + 1,1,1,13,19,7,85,7,195,357,1097,2893,2913,9635,0, + 1,1,5,9,25,33,41,155,39,655,1993,3117,3639,7977,0, + 1,1,1,13,3,63,121,247,151,673,609,285,2299,7663,0, + 1,3,7,11,17,13,49,253,245,21,273,993,911,863,0, + 1,1,5,5,23,1,121,95,225,9,1237,1183,6461,559,0, + 1,3,7,13,3,7,121,151,233,561,281,3583,897,1767,0, + 1,1,7,7,9,47,107,41,25,569,1697,2299,6231,12209,0, + 1,3,7,7,27,43,59,37,31,51,503,149,4043,11847,0, + 1,3,3,11,5,1,119,181,47,641,685,4017,637,16251,0, + 1,3,3,7,11,1,101,7,239,747,307,1721,5979,4367,0, + 1,3,5,7,1,63,19,151,469,333,1587,2453,897,4711,0, + 1,3,1,5,11,61,21,253,91,993,1347,1993,5607,13031,0, + 1,3,5,5,1,39,65,71,189,389,1437,1055,6439,3989,0, + 1,1,3,3,19,15,93,3,339,165,1675,3953,2145,12113,0, + 1,1,3,13,13,45,5,175,211,993,705,2761,3023,13633,0, + 1,1,3,1,19,39,121,29,287,87,281,3491,7107,13007,0, + 1,1,7,1,29,49,103,187,39,923,51,1533,3249,4399,0, + 1,1,5,5,5,43,25,107,453,955,115,57,4589,14573,0, + 1,1,3,5,21,45,103,99,183,987,1207,1697,8033,13703,0, + 1,1,5,7,11,23,9,17,261,749,1957,935,6283,8625,0, + 1,1,1,9,9,51,69,225,265,323,1161,2993,7305,2249,0, + 1,3,1,9,23,19,57,205,503,489,1499,3277,817,11931,0, + 1,3,3,5,1,7,49,1,313,123,643,2027,1469,3585,0, + 1,3,7,11,27,47,95,111,27,213,465,3693,3661,7531,0, + 1,1,7,9,3,37,115,189,31,613,1393,1229,4767,12425,0, + 1,1,3,3,25,17,99,47,161,931,959,1293,7095,8325,0, + 1,1,1,7,23,9,11,51,205,419,479,1497,2493,13921,0, + 1,3,1,9,17,29,51,79,159,435,477,413,3815,5589,0, + 1,3,7,5,7,23,99,43,169,665,403,1163,4337,1335,0, + 1,3,1,5,25,27,125,249,421,267,1259,4089,59,9377,0, + 1,3,3,1,27,37,91,17,123,597,1749,3449,6503,11043,0, + 1,3,7,7,23,41,19,245,109,569,547,1917,7943,2697,0, + 1,3,7,7,9,1,123,105,329,435,2013,2745,347,11045,0, + 1,1,1,13,29,53,51,67,105,89,1887,3543,963,8159,0, + 1,1,5,3,5,27,41,67,67,883,973,1785,901,14969,0, + 1,3,3,13,17,11,117,115,163,939,79,641,4365,2267,0, + 1,1,3,3,9,5,41,123,149,9,1533,3939,5995,12701,0, + 1,1,1,15,31,1,101,229,191,965,61,2671,4177,15779,0, + 1,1,5,15,1,25,49,185,33,697,1043,2639,7819,3171,0, + 1,3,5,13,19,9,111,49,47,847,1865,717,5287,13417,0, + 1,3,7,11,5,61,63,111,171,735,2003,73,5701,647,0, + 1,3,1,11,1,49,121,79,431,671,1241,1161,2057,263,0, + 1,3,3,1,1,23,75,15,117,641,313,1525,2041,1409,0, + 1,3,5,11,15,57,13,67,139,131,1339,2419,7945,11877,0, + 1,3,1,1,19,39,97,83,297,595,1611,5,4753,3435,0, + 1,3,1,9,7,49,125,101,383,717,63,2295,3873,13461,0, + 1,1,3,3,15,29,89,77,269,689,229,1207,7311,8663,0, + 1,1,1,1,1,61,25,255,203,233,271,987,2277,8735,0, + 1,1,5,7,21,27,63,79,337,133,1453,3633,6157,15875,0, + 1,3,1,7,7,55,31,81,203,709,1743,1677,4247,11411,0, + 1,1,3,3,29,51,37,17,487,325,1393,1433,3467,2851,0, + 1,1,7,9,3,41,99,177,241,869,739,2729,4585,14801,0, + 1,1,3,1,9,43,97,65,99,295,1693,2083,3241,4073,0, + 1,1,1,9,5,39,67,119,235,543,795,2773,3195,6273,0, + 1,1,5,5,21,41,89,1,85,81,57,2951,1531,10101,0, + 1,1,1,7,3,35,127,69,39,265,1643,2973,267,12365,0, + 1,3,1,1,21,57,99,205,119,477,1771,1989,2761,12573,0, + 1,1,3,13,1,59,93,125,279,935,1877,2061,4845,7835,0, + 1,1,7,9,7,45,69,99,273,35,1579,2137,7175,6999,0, + 1,1,7,7,29,21,127,91,9,383,787,1783,601,5047,0, + 1,1,7,13,7,29,35,219,43,581,2043,2211,6169,12173,0, + 1,3,5,13,29,29,39,63,411,645,415,2383,1989,11411,0, + 1,1,7,9,15,9,87,95,321,709,543,3831,2453,4167,0, + 1,3,1,5,31,25,5,85,239,487,1613,3937,4661,3535,0, + 1,3,5,11,27,41,3,201,39,91,1997,237,5639,14703,0, + 1,1,7,3,27,49,87,71,473,247,1007,47,475,5413,0, + 1,3,7,15,9,57,81,149,287,333,1911,3417,1081,8995,0, + 1,1,5,1,3,63,43,151,97,431,961,1019,5153,2407,0, + 1,1,5,5,27,21,127,161,507,311,129,3489,1133,3241,0, + 1,3,7,15,21,33,117,83,497,667,1399,931,1695,8171,0, + 1,1,1,13,3,39,53,27,193,993,671,1871,7579,11457,0, + 1,1,5,11,7,39,81,107,195,387,849,395,1317,6487,0, + 1,3,3,3,3,15,45,127,279,111,331,357,4637,4697,0, + 1,1,3,9,21,49,47,97,61,101,181,1867,1201,14099,0, + 1,1,5,11,25,19,51,51,101,451,545,101,7497,9141,0, + 1,1,1,3,13,53,119,81,377,245,765,251,3757,16045,0, + 1,1,1,3,5,61,65,37,331,925,1439,3219,2843,11397,0, + 1,3,5,9,23,31,95,155,83,641,1129,135,477,1623,0, + 1,1,3,9,9,61,93,11,331,585,799,1417,1533,463,0, + 1,1,7,7,21,51,61,29,467,935,11,3357,1087,12337,0, + 1,3,3,11,1,39,103,153,351,893,1823,835,2149,4203,0, + 1,1,1,9,31,13,61,235,369,359,835,2067,2697,15289,0, + 1,1,7,1,15,1,107,27,201,451,1521,313,3195,3847,0, + 1,1,5,13,1,27,63,137,355,489,2039,1015,2519,13797,0, + 1,1,7,9,29,33,23,197,49,555,1087,3447,7299,15513,0, + 1,3,5,11,7,37,55,63,443,573,1715,631,3405,6155,0, + 1,3,3,3,31,35,51,167,225,617,2007,2555,6819,12709,0, + 1,1,1,13,15,5,73,85,109,43,1067,3941,1125,10269,0, + 1,1,7,11,17,3,127,145,279,19,1007,3287,4751,12507,0, + 1,3,7,3,19,1,117,111,193,435,47,1801,529,8547,0, + 1,3,3,13,1,19,101,19,469,187,207,1243,8153,3273,0, + 1,3,1,5,11,51,69,189,453,775,241,3331,4067,14759,0, + 1,1,1,1,23,55,113,133,497,731,391,2777,3529,955,0, + 1,3,1,11,5,49,59,35,261,949,325,3595,7433,11099,0, + 1,3,5,9,13,37,103,219,329,865,1787,2497,7249,9877,0, + 1,3,7,9,11,33,19,255,191,935,1115,1901,1577,9623,0, + 1,1,5,7,29,23,77,43,283,143,1211,73,2835,10235,0, + 1,1,7,3,3,27,35,173,453,425,1225,3023,2159,8433,0, + 1,1,1,5,27,21,35,25,71,145,1545,523,4527,7655,0, + 1,1,5,3,13,49,61,157,113,775,763,1785,225,11851,0, + 1,1,3,1,31,57,97,229,291,777,213,4067,921,8203,0, + 1,1,5,1,25,13,125,123,263,207,119,3111,3841,843,0, + 1,1,7,7,25,57,81,129,31,133,1869,2949,5563,14965,0, + 1,3,3,7,3,51,33,127,281,425,1253,405,7941,8799,0, + 1,1,3,9,3,63,93,173,255,609,49,111,7785,15865,0, + 1,1,1,3,17,59,113,55,155,789,1335,177,3071,1851,0, + 1,3,7,15,15,23,35,35,131,623,47,437,1337,9891,0, + 1,3,7,5,29,57,39,31,111,271,59,1473,949,3899,0, + 1,1,3,11,17,19,41,229,259,691,1455,3023,7455,9711,0, + 1,3,5,11,29,13,9,165,499,355,1415,1395,7595,15571,0, + 1,3,1,9,5,5,25,247,185,241,1325,3133,7471,2649,0, + 1,3,3,11,17,29,57,61,51,203,993,1837,3785,15163,0, + 1,1,7,7,21,57,79,165,277,133,93,1055,7169,15685,0, + 1,1,5,3,5,17,25,177,95,323,367,1359,4915,6409,0, + 1,1,1,1,11,25,115,45,373,221,1483,591,6561,4527,0, + 1,3,5,3,5,23,69,77,313,473,1037,4045,3969,5445,0, + 1,3,1,5,1,15,73,83,439,463,203,361,6835,1061,0, + 1,1,3,11,21,5,89,233,405,253,773,3901,6085,5677,0, + 1,1,3,9,15,53,71,29,101,599,1073,705,4507,12779,0, + 1,1,3,1,3,9,27,97,207,859,417,735,2179,5071,0, + 1,1,1,3,13,63,65,125,195,611,649,2221,3143,143,0, + 1,3,3,15,17,57,99,119,243,407,1229,813,5245,1893,0, + 1,1,1,5,27,27,49,13,313,287,473,2629,3509,11371,0, + 1,1,7,7,23,3,75,59,245,689,1215,2375,3325,1593,0, + 1,3,1,5,21,51,43,107,91,611,1405,677,2087,9565,0, + 1,3,7,11,9,27,81,101,449,201,1507,2217,6767,8059,0, + 1,1,3,9,13,41,21,195,421,315,347,2621,2359,9247,0, + 1,1,5,7,31,45,77,229,455,575,1087,1147,2273,13773,0, + 1,1,1,1,9,5,87,19,207,545,1435,495,1299,4947,0, + 1,1,3,3,15,9,63,67,219,735,1911,2361,6503,11977,0, + 1,3,1,9,31,27,103,153,81,939,461,2753,697,537,0, + 1,3,3,9,21,53,49,211,415,817,321,3775,2921,9473,0, + 1,1,7,3,23,55,15,51,435,1013,73,3967,4575,13099,0, + 1,1,3,7,5,27,43,225,267,21,1261,603,6913,4421,0, + 1,1,7,13,25,31,101,109,237,91,1587,1987,2795,6991,0, + 1,1,3,13,23,51,91,89,287,39,1513,463,6135,10469,0, + 1,3,3,1,9,43,125,157,369,495,1849,785,6357,6557,0, + 1,3,1,13,5,25,107,139,367,239,1671,1239,7027,5291,0, + 1,3,5,13,11,13,35,177,45,939,251,59,333,13105,0, + 1,3,5,7,29,57,109,227,435,739,423,1941,3345,12731,0, + 1,3,3,9,23,51,19,207,69,99,955,519,7305,2415,0, + 1,1,5,13,17,1,67,201,61,403,1059,2915,2419,12773,0, + 1,3,1,11,17,19,25,27,207,299,143,1955,5669,2301,0, + 1,1,5,3,25,57,45,255,489,1011,1699,2637,5279,12211,0, + 1,3,3,15,7,47,113,33,511,907,1815,1741,2091,13857,0, + 1,3,3,5,5,27,95,3,353,253,947,393,1815,14551,0, + 1,1,5,11,29,19,63,117,293,861,2039,9,5999,6909,0, + 1,3,7,3,15,63,107,173,509,817,99,2825,131,7917,0, + 1,3,1,1,29,49,33,153,119,777,1315,3581,5675,4043,0, + 1,3,5,15,13,11,17,147,327,305,367,3237,5423,13757,0, + 1,1,5,13,1,39,35,29,25,751,1365,2243,8181,7063,0, + 1,3,7,11,25,53,11,111,289,755,1201,691,3679,3725,0, + 1,1,1,11,11,37,33,211,395,691,1817,861,6485,12077,0, + 1,3,3,11,21,3,111,171,305,561,1501,2011,7841,10931,0, + 1,3,7,9,9,59,109,113,31,915,103,1861,2779,10619,0, + 1,1,1,1,7,25,61,97,103,723,1145,3105,371,339,0, + 1,1,7,13,17,9,113,51,233,209,1117,211,6969,2347,0, + 1,1,5,9,25,43,21,217,327,735,197,1063,799,801,0, + 1,1,7,13,9,13,73,33,415,923,863,1999,5383,8119,0, + 1,3,1,5,7,33,51,185,289,967,1277,1011,767,15505,0, + 1,3,3,13,21,11,105,235,343,1021,2009,2251,3865,6923,0, + 1,3,5,9,29,11,33,17,149,155,1739,3039,7015,2401,0, + 1,3,7,7,17,13,89,177,297,267,545,3861,329,13267,0, + 1,3,5,15,27,33,1,231,181,557,447,379,7845,1295,0, + 1,1,5,13,3,63,59,33,263,877,1867,1383,641,7139,0, + 1,3,7,5,13,51,9,113,223,605,1189,4063,6925,9563,0, + 1,1,1,13,5,35,83,107,295,231,265,5,4087,6407,0, + 1,1,5,1,7,25,95,137,97,987,1753,2781,1369,6903,0, + 1,1,5,13,19,61,77,229,193,165,811,249,79,10719,0, + 1,3,7,7,27,9,119,193,459,43,1989,2959,3595,6341,0, + 1,1,5,11,5,43,35,33,25,581,897,351,4201,3971,0, + 1,1,7,11,21,29,53,45,359,197,313,3825,6717,4077,0, + 1,1,1,15,3,45,99,133,357,315,1159,241,2463,11253,0, + 1,1,7,11,9,33,111,85,443,601,447,337,6471,7029,0, + 1,3,7,9,13,33,25,31,9,729,1763,4077,7575,7877,0, + 1,3,5,13,13,37,29,103,53,229,591,1073,1323,14405,0, + 1,1,5,1,17,33,15,183,473,297,2003,93,4955,1787,0, + 1,1,5,13,5,29,113,161,267,451,1193,149,273,11809,0, + 1,1,1,9,17,39,47,233,165,373,955,2891,7523,7235,0, + 1,1,1,3,7,21,115,205,153,449,339,2073,1077,5749,0, + 1,1,7,13,9,39,117,187,37,753,227,3519,7391,5751,0, + 1,1,1,9,5,19,41,161,141,195,1719,3321,5,12877,0, + 1,3,7,11,21,13,83,55,299,75,1905,3765,4685,12297,0, + 1,1,7,3,3,23,111,243,187,297,1061,2515,977,9555,0, + 1,3,7,3,29,11,103,177,225,875,1649,1401,6383,8309,0, + 1,3,5,3,3,41,71,3,373,757,701,2825,1521,13217,0, + 1,1,5,3,11,5,103,227,209,723,1543,3895,6345,7901,0, + 1,1,5,1,9,51,77,67,359,937,557,993,3871,3577,0, + 1,3,7,1,1,15,121,239,29,113,1123,3877,6941,14129,0, + 1,1,5,1,27,61,83,113,185,601,947,3933,381,13869,0, + 1,1,5,3,5,37,97,31,81,367,747,1811,5313,14151,0, + 1,3,5,9,27,61,87,31,185,521,837,959,5001,3957,0, + 1,3,5,3,11,61,37,19,107,749,1345,3829,6701,4315,0, + 1,3,1,15,13,45,101,113,243,963,1861,3283,1419,12131,0, + 1,1,7,1,11,63,17,117,271,819,677,669,1991,12511,0, + 1,1,1,13,13,33,41,73,187,537,993,3147,1013,16063,0, + 1,3,1,1,25,21,107,81,117,917,113,349,4475,9149,0, + 1,1,1,11,21,21,29,251,125,681,141,2893,5843,14359,0, + 1,3,3,1,5,41,85,163,387,29,1593,221,2769,10809,0, + 1,3,5,11,1,17,69,127,273,449,1855,2971,7031,10583,0, + 1,1,5,7,1,61,9,211,123,563,111,1883,5801,2191,0, + 1,1,3,11,11,51,1,81,405,803,2017,161,5429,731,0, + 1,1,7,9,15,55,65,51,459,485,1539,3135,2929,7867,0, + 1,1,7,11,3,45,15,7,331,417,1813,4009,1341,10965,0, + 1,1,1,5,9,29,89,121,277,509,1989,1293,4787,16097,0, + 1,1,3,9,17,45,97,197,339,943,1377,2947,5833,7,0, + 1,1,7,9,15,61,75,233,401,705,825,2521,3787,14387,0, + 1,1,7,15,25,57,3,43,361,459,1551,1859,6787,2293,0, + 1,3,3,11,11,35,91,65,43,509,1829,1149,4801,4109,0, + 1,3,5,9,15,3,81,109,231,481,417,2505,315,6693,0, + 1,1,3,9,3,7,107,221,297,543,149,579,927,79,0, + 1,3,1,11,17,3,81,137,157,587,741,1277,2631,3953,0, + 1,1,7,5,13,43,117,19,495,185,1105,605,5249,11099,0, + 1,1,7,9,23,55,91,213,21,779,857,2047,7813,10053,0, + 1,1,1,1,27,7,39,181,63,519,1073,3147,4111,363,0, + 1,3,7,9,15,61,7,139,495,805,1545,3789,2411,3989,0, + 1,1,3,1,25,11,23,241,167,607,479,153,7787,13929,0, + 1,3,5,15,29,35,45,71,457,297,883,3021,5361,15427,0, + 1,3,1,7,29,27,93,241,427,89,1185,37,3863,14095,0, + 1,3,1,5,5,45,51,15,235,889,1649,2331,2713,10943,0, + 1,1,3,11,11,15,71,85,135,163,139,1147,1043,3195,0, + 1,3,5,13,3,43,71,131,473,933,569,2491,7751,1865,0, + 1,1,7,9,21,37,105,227,329,509,1319,307,1557,14625,0, + 1,1,3,13,15,1,25,93,335,953,769,4039,369,10727,0, + 1,3,7,5,17,21,59,89,437,679,437,1543,7663,5005,0, + 1,1,7,15,27,49,125,13,397,877,1087,2191,4711,9065,0, + 1,1,7,5,15,47,115,125,187,31,1003,2575,5397,3883,0, + 1,1,7,11,15,1,127,207,383,707,183,1053,3123,14071,0, + 1,3,3,1,31,53,15,19,477,245,777,1613,5813,7443,0, + 1,3,1,11,23,59,65,23,493,157,1389,2833,4535,3907,0, + 1,1,7,1,19,7,51,135,327,441,1841,3091,3451,14381,0, + 1,1,7,7,3,37,29,249,437,319,1693,945,7639,5923,0, + 1,3,7,15,7,61,81,127,383,99,23,3833,3973,7651,0, + 1,3,1,7,7,21,119,185,243,619,1363,2033,4835,5089,0, + 1,3,1,1,3,27,63,145,271,735,695,3981,3049,5433,0, + 1,3,3,1,3,29,79,211,279,819,501,3665,1455,10455,0, + 1,1,3,3,31,61,113,5,411,91,489,3257,5939,6715,0, + 1,1,5,1,23,11,103,89,377,441,43,967,3383,8717,0, + 1,1,5,13,29,39,97,189,197,621,1755,333,6783,9711,0, + 1,1,5,13,27,17,97,197,351,799,335,765,5329,12549,0, + 1,1,5,11,29,17,9,211,127,633,1187,3965,4145,12667,0, + 1,1,7,5,27,29,65,115,287,325,461,5,899,2027,0, + 1,1,1,5,27,17,31,13,231,627,1163,649,1693,9975,0, + 1,3,1,15,7,49,113,123,427,603,347,2785,7129,4645,0, + 1,1,3,7,1,33,113,105,411,939,205,3965,4361,4649,0, + 1,1,1,1,5,21,35,159,275,929,1193,3205,4787,3515,0, + 1,1,1,5,1,21,29,191,275,233,1239,515,4349,14989,0, + 1,1,5,11,27,43,111,83,153,577,1537,149,231,839,0, + 1,3,5,13,21,19,57,69,87,163,271,3535,1057,8517,0, + 1,3,3,13,17,49,65,45,457,241,391,2033,2507,7771,0, + 1,1,5,7,11,19,79,133,341,761,27,3905,4137,14363,0, + 1,3,3,13,19,1,11,139,249,245,1393,2151,2857,1665,0, + 1,1,3,15,11,7,127,47,385,1007,713,2235,5489,8755,0, + 1,3,5,13,19,21,21,167,405,655,1653,889,7367,4177,0, + 1,1,5,3,19,63,99,39,89,415,951,2863,6569,3797,0, + 1,1,1,13,31,29,119,35,311,839,1749,941,7487,2385,0, + 1,3,7,3,17,3,97,143,465,345,1457,2201,5329,359,0, + 1,3,7,11,1,15,3,115,335,567,1749,1811,3491,15939,0, + 1,1,3,13,3,21,7,141,149,571,1877,473,2143,9569,0, + 1,3,3,11,23,61,47,179,297,453,181,3405,2981,13409,0, + 1,3,1,13,1,43,5,201,371,1003,367,2709,7675,14973,0, + 1,3,3,15,29,17,19,241,495,317,1135,2227,6457,4783,0, + 1,3,3,7,29,9,57,95,261,531,1717,3389,7991,3793,0, + 1,1,1,5,31,43,73,119,499,589,1529,3337,4097,15641,0, + 1,1,7,9,29,43,127,91,243,979,1325,2835,2787,9445,0, + 1,1,7,5,9,3,115,199,219,901,747,1077,3197,2443,0, + 1,3,5,1,3,43,7,117,297,313,1043,1579,5099,13289,0, + 1,1,7,11,29,33,15,121,131,579,317,1871,1121,11653,0, + 1,1,5,9,25,25,43,89,355,1011,1385,2901,6387,1653,0, + 1,1,1,9,5,47,61,165,85,757,1397,1177,1657,4899,0, + 1,1,3,9,11,49,15,139,261,613,931,1299,2777,2835,0, + 1,1,1,5,3,55,83,227,125,581,1607,1171,6681,14463,0, + 1,3,5,13,5,55,3,247,493,155,1073,3743,5719,4019,0, + 1,1,7,1,11,23,13,75,399,847,499,1643,6977,3699,0, + 1,3,1,9,11,41,47,131,313,627,481,2469,3281,979,0, + 1,3,5,13,29,3,65,101,11,29,1807,153,1487,16109,0, + 1,1,5,9,13,31,83,195,351,355,467,3871,3085,4441,0, + 1,3,5,3,19,21,111,179,143,361,1619,1547,3409,6905,0, + 1,1,5,9,31,1,93,199,491,135,1627,2559,1389,14561,0, + 1,3,3,9,25,53,3,105,39,445,259,1045,1129,9153,0, + 1,1,5,9,19,63,71,9,73,435,1377,4015,1821,6453,0, + 1,3,7,13,19,13,37,247,391,23,1491,1257,6395,237,0, + 1,1,3,3,19,55,109,23,227,747,729,2221,727,2209,0, + 1,1,5,11,25,21,75,37,219,355,1005,1895,7039,5225,0, + 1,3,5,13,11,43,9,67,87,797,1077,245,4521,11845,0, + 1,3,5,3,15,29,127,237,277,373,1859,3083,587,1123,0, + 1,1,7,15,13,7,103,53,13,965,1497,775,3439,1501,0, + 1,3,3,15,17,13,97,169,67,953,189,2739,1459,10543,0, + 1,1,5,1,17,39,15,127,327,989,1471,3235,2801,15311,0, + 1,1,1,15,5,37,55,155,47,463,1851,3467,2765,9359,0, + 1,3,3,15,1,13,93,239,291,115,365,61,395,15853,0, + 1,1,5,1,19,27,61,95,105,369,1557,961,6917,3621,0, + 1,3,3,9,7,35,115,53,111,345,1145,1687,3401,12107,0, + 1,1,1,5,7,31,63,19,373,79,1369,3037,2835,4439,0, + 1,3,7,9,11,17,29,33,331,447,1981,3333,6535,6557,0, + 1,3,3,5,11,41,29,43,365,279,1919,945,179,1987,0, + 1,3,1,13,7,7,25,33,103,367,1267,763,5691,8643,0, + 1,3,1,5,11,15,3,213,511,211,1069,4047,3335,12729,0, + 1,1,3,1,5,11,27,201,361,537,679,3709,293,2997,0, + 1,1,3,1,25,15,19,185,369,577,1625,655,2363,3861,0, + 1,1,5,5,1,47,61,45,411,597,955,1007,3775,5809,0, + 1,1,5,3,27,51,101,167,429,333,1703,3541,2947,3695,0, + 1,3,5,5,1,53,17,63,141,215,1223,3129,635,15919,0, + 1,3,3,1,23,31,25,11,195,241,995,3941,573,13855,0, + 1,3,3,7,17,13,71,203,465,479,1857,1493,8067,7113,0, + 1,1,5,3,11,57,9,59,225,691,425,2423,6031,6631,0, + 1,3,7,1,29,57,103,123,401,807,471,2759,5113,15937,0, + 1,3,1,1,3,1,67,123,157,655,519,323,1853,15041,0, + 1,1,7,5,11,11,105,135,247,689,1141,2347,7113,9347,0, + 1,1,3,11,15,37,87,3,209,575,1521,3863,3893,211,0, + 1,3,1,3,29,55,115,31,19,195,985,3275,363,9801,0, + 1,1,3,9,13,31,57,251,201,275,1751,389,1463,13159,0, + 1,3,5,15,19,51,127,255,397,243,29,3007,7845,4687,0, + 1,1,7,15,9,37,39,217,509,137,1123,3361,6323,5323,0, + 1,3,7,5,25,3,93,203,345,581,261,2811,4829,6977,0, + 1,1,7,1,15,41,51,227,447,893,1209,3865,5229,4277,0, + 1,1,1,5,31,19,23,195,359,853,595,337,2503,16371,0, + 1,3,7,5,5,13,89,157,351,777,151,3565,4219,7423,0, + 1,1,1,5,7,1,9,89,175,909,1523,2295,7949,6739,0, + 1,3,5,15,27,17,11,235,19,105,457,465,3819,11335,0, + 1,3,1,13,3,41,85,221,451,613,543,2265,6831,1725,0, + 1,1,7,7,3,29,9,197,455,665,343,1811,5395,393,0, + 1,1,3,13,29,55,71,95,475,615,2029,123,413,16127,0, + 1,1,5,9,15,61,9,51,105,271,511,2801,693,11839,0, + 1,1,7,13,29,9,105,59,377,635,717,4033,6963,10541,0, + 1,1,1,13,7,13,59,17,335,355,77,3665,7003,9521,0, + 1,3,1,1,23,43,51,209,151,365,1021,2859,3937,2899,0, + 1,1,3,3,31,41,111,107,171,433,1233,505,2971,6927,0, + 1,3,7,13,17,25,127,195,257,551,1867,2145,3695,14567,0, + 1,1,5,13,13,45,39,195,55,991,1981,1043,5875,581,0, + 1,3,3,11,25,31,91,153,415,449,1301,563,7755,10671,0, + 1,1,3,5,31,63,1,157,229,949,971,137,6589,8387,0, + 1,3,7,15,25,7,89,133,73,497,1361,613,455,1005,0, + 1,3,3,1,13,5,119,93,175,511,1923,763,7573,7545,0, + 1,1,3,15,27,59,49,205,497,485,117,2523,4495,15153,0, + 1,3,7,9,15,47,111,31,363,11,475,2931,6813,1259,0, + 1,1,5,5,1,35,95,225,17,991,809,2601,6455,13803,0, + 1,1,5,5,15,1,1,171,433,887,1813,3431,2471,7803,0, + 1,3,3,15,1,15,43,179,15,949,1881,1027,6989,8955,0, + 1,3,7,13,1,3,49,183,373,175,1733,913,929,1065,0, + 1,3,5,7,15,51,107,115,323,357,167,2069,7541,9601,0, + 1,1,3,5,5,21,31,107,21,299,1937,43,3673,8155,0, + 1,3,5,11,9,55,35,113,29,99,161,1607,8141,4951,0, + 1,3,7,15,25,7,113,179,213,19,1717,1027,2021,11263,0, + 1,1,5,1,31,33,85,111,67,95,2013,2217,871,5329,0, + 1,1,1,7,7,63,67,145,495,419,1945,3437,6255,151,0, + 1,3,5,7,17,37,97,187,215,399,1603,2195,5923,769,0, + 1,1,3,9,25,1,119,193,385,861,2005,2769,675,767,0, + 1,3,1,15,19,7,5,227,173,383,289,461,579,3689,0, + 1,3,1,11,1,37,93,239,465,891,1479,921,4439,15265,0, + 1,1,1,13,27,61,99,69,279,655,1853,1593,6319,9003,0, + 1,1,1,11,5,7,19,7,387,303,321,931,5809,16029,0, + 1,1,1,15,21,55,43,107,217,687,19,3225,3419,9991,0, + 1,1,7,5,7,55,79,41,317,357,859,1205,191,9395,0, + 1,1,3,11,3,43,7,133,115,995,1205,1055,4153,10481,0, + 1,1,7,11,31,57,53,9,459,223,1969,3513,7033,8505,0, + 1,1,3,7,17,11,115,255,281,97,1685,2039,2845,11637,0, + 1,3,7,1,23,41,69,199,53,105,657,1453,4429,1101,0, + 1,3,1,5,11,33,91,131,191,73,823,117,1053,127,0, + 1,3,7,11,7,3,21,65,187,103,1393,1797,6673,1409,0, + 1,3,7,1,31,25,25,161,299,275,417,2267,6861,1255,0, + 1,3,5,13,5,11,61,155,115,1001,747,889,3235,5709,0, + 1,3,7,7,7,1,97,177,507,273,1781,3455,5123,15607,0, + 1,1,7,5,1,7,59,49,147,343,97,3517,5611,8705,0, + 1,1,5,13,21,29,13,21,503,515,1217,3905,5513,15849,0, + 1,3,1,9,9,39,65,111,385,757,583,2225,2039,2817,0, + 1,3,3,15,23,17,63,169,503,949,849,461,6799,669,0, + 1,1,1,3,1,41,63,159,251,457,521,1653,623,3287,0, + 1,1,7,3,9,1,41,37,441,921,1415,2955,5841,1451,0, + 1,1,5,11,23,29,89,185,413,357,1131,2369,3835,6233,0, + 1,1,5,15,27,35,17,73,315,911,1761,797,5349,3219,0, + 1,3,7,11,21,9,119,233,249,901,189,3625,2691,16201,0, + 1,3,3,13,29,61,105,145,187,79,609,321,4289,3933,0, + 1,3,1,15,19,63,13,185,115,219,1021,1205,4273,11521,0, + 1,1,3,3,23,31,93,153,87,947,1039,469,4047,8869,0, + 1,1,1,1,9,1,85,3,15,995,455,2769,6781,16203,0, + 1,1,3,3,13,7,55,215,185,367,765,441,4497,1521,0, + 1,1,1,5,1,31,13,95,417,735,975,3407,4871,16133,0, + 1,1,3,3,5,43,111,107,419,515,1075,3597,1187,4143,0, + 1,1,3,13,31,51,83,163,489,887,863,599,9,13861,0, + 1,3,3,3,19,27,91,115,103,969,593,3667,1867,15433,0, + 1,3,3,13,7,25,47,141,57,553,1785,1709,7453,2209,0, + 1,3,1,13,11,13,71,219,5,451,2043,1605,6439,12203,0, + 1,3,1,13,5,57,61,223,401,413,321,1365,619,12477,0, + 1,3,1,5,25,57,89,211,195,455,1165,3979,6313,5751,0, + 1,1,1,9,31,23,71,145,89,285,1593,1171,5685,15459,0, + 1,3,7,7,9,41,65,251,65,137,1577,3027,5555,2865,0, + 1,1,5,13,27,5,125,21,171,647,983,2921,6623,5695,0, + 1,1,1,13,15,9,117,197,123,953,1191,3657,5757,15957,0, + 1,1,3,7,29,13,5,175,395,127,679,255,6055,7639,0, + 1,3,7,15,15,51,77,147,319,147,1775,3983,3175,5723,0, + 1,3,3,3,7,11,119,41,43,153,975,679,3081,10359,0, + 1,1,5,13,3,7,65,67,63,399,1561,2789,2083,12289,0, + 1,1,7,3,19,53,103,67,35,865,161,93,2533,3851,0, + 1,1,1,11,31,9,29,189,199,817,1571,395,345,3777,0, + 1,3,5,11,31,3,9,67,277,735,181,2777,3009,7233,0, + 1,1,3,3,17,7,17,3,375,933,237,3919,5409,3355,0, + 1,3,3,5,9,27,19,77,221,3,1965,309,3001,15977,0, + 1,1,5,1,3,33,35,133,37,709,627,1705,2525,4307,0, + 1,1,7,3,25,21,105,55,375,681,881,1299,5879,459,0, + 1,3,7,1,13,7,113,103,313,515,1041,3683,4619,5093,0, + 1,1,3,7,19,43,83,37,39,133,1759,1171,1521,13717,0, + 1,1,7,13,7,35,15,155,293,1001,157,3883,405,1797,0, + 1,1,3,3,13,19,125,49,333,387,339,1815,4503,7359,0, + 1,1,3,13,19,19,105,225,151,27,1251,885,4815,7863,0, + 1,1,1,5,7,59,17,145,77,117,1355,1429,2301,16177,0, + 1,3,3,13,5,31,119,167,459,727,1799,2537,695,13637,0, + 1,3,3,3,27,51,107,85,267,57,1279,823,6247,3603,0, + 1,1,7,15,29,17,67,197,215,465,109,3461,5269,15287,0, + 1,1,3,5,11,15,123,53,293,797,1105,1777,6509,217,0, + 1,3,3,13,3,5,109,53,203,693,871,135,369,11149,0, + 1,3,5,15,17,43,81,235,119,817,1777,261,8049,4251,0, + 1,1,3,7,7,13,87,99,481,931,1507,651,5267,8281,0, + 1,3,1,13,27,43,77,225,341,163,933,429,4943,7781,0, + 1,1,7,1,1,49,85,211,449,479,1395,787,5653,14891,0, + 1,1,5,9,25,13,49,85,125,85,1281,3365,4305,11791,0, + 1,3,1,13,3,31,117,39,43,151,663,669,1571,5207,0, + 1,3,7,15,17,7,79,163,37,841,1799,1787,4501,3785,0, + 1,1,3,9,1,23,67,191,449,931,1521,2705,887,7037,0, + 1,1,1,1,5,13,55,161,419,577,1703,2589,2651,2873,0, + 1,3,3,3,5,19,37,169,69,1003,1755,3101,1469,8583,0, + 1,1,1,1,11,33,105,79,283,91,299,835,3193,5593,0, + 1,3,3,13,25,21,81,213,465,475,331,457,61,9511,0, + 1,1,3,11,1,11,77,95,455,949,1999,1833,1275,5631,0, + 1,1,1,1,15,25,51,137,275,451,1179,3595,5177,7105,0, + 1,3,3,3,3,59,79,143,393,583,349,3039,7079,14245,0, + 1,1,7,9,21,11,123,105,53,297,803,4025,5421,14527,0, + 1,3,7,11,21,15,103,109,311,321,1217,2777,5457,1823,0, + 1,3,5,11,19,31,79,89,295,413,817,499,3699,14411,0, + 1,1,1,5,11,3,81,13,315,841,1543,411,6883,6347,0, + 1,3,3,11,23,43,23,131,17,517,995,2687,7443,15085,0, + 1,1,1,1,11,57,73,9,123,905,1763,1789,3701,7131,0, + 1,1,3,5,9,53,99,229,43,207,625,1583,6727,15249,0, + 1,1,7,7,17,39,91,1,297,711,225,513,7391,291,0, + 1,1,7,11,7,55,111,129,423,521,1807,3015,1449,12321,0, + 1,3,7,3,13,9,125,187,11,485,647,275,3495,11989,0, + 1,1,3,11,11,25,49,33,361,105,271,3841,4837,2437,30181, + 1,3,5,1,27,15,119,35,159,273,1489,3157,5433,3337,26859, + 1,3,5,13,23,31,97,145,41,605,1455,59,5389,5527,14447, + 1,1,7,9,7,41,61,193,353,879,1805,581,5447,11177,7331, + 1,1,7,11,29,19,55,207,361,759,63,2255,2119,14671,21783, + 1,3,1,13,17,7,73,179,103,23,917,1205,4925,1691,5419, + 1,3,5,3,15,3,9,109,227,861,867,3529,1535,489,22873, + 1,3,3,9,15,15,95,193,385,997,1525,1865,1425,4079,14771, + 1,1,3,5,5,29,49,171,171,623,1167,3743,1809,12009,7043, + 1,3,7,5,23,11,87,183,299,555,1857,489,3505,9161,28763, + 1,3,5,9,19,21,85,127,337,439,1183,1891,1877,4373,10451, + 1,3,7,13,27,17,29,83,463,385,1167,3453,4523,4759,9321, + 1,1,3,7,21,59,65,83,177,763,317,2913,7527,5967,17167, + 1,1,7,15,13,27,49,35,253,101,1699,355,2181,10859,24221, + 1,1,5,1,17,17,81,91,349,655,1373,2225,945,899,31801, + 1,3,7,11,5,1,81,53,215,587,167,4045,5671,5597,13529, + 1,3,5,15,1,9,59,235,315,195,909,2237,505,10415,28145, + 1,1,1,3,9,31,41,43,275,921,25,671,5737,11241,4193, + 1,3,3,13,29,13,95,213,317,995,1489,3779,3043,8569,28823, + 1,1,7,5,9,49,125,241,87,153,1673,3849,7253,1715,11627, + 1,1,3,9,27,27,19,223,63,463,1095,1395,6643,11589,2145, + 1,1,3,15,21,17,45,23,357,11,1307,1791,2481,2123,24341, + 1,3,5,15,31,53,117,51,433,193,1239,3329,2403,12745,32219, + 1,1,5,9,7,27,9,115,417,579,83,173,4717,15665,27463, + 1,3,5,7,9,9,31,35,249,567,331,905,5101,14817,14255, + 1,3,7,3,1,61,29,129,119,421,1597,2987,3041,7629,23451, + 1,1,7,9,13,1,99,105,107,509,989,2259,1009,6827,8903, + 1,3,5,15,11,29,85,29,265,105,2035,3349,3543,13903,10213, + 1,3,1,1,25,19,53,139,467,485,491,3067,7353,13861,25819, + 1,1,5,3,3,43,41,185,45,463,351,2823,2519,6705,11395, + 1,3,7,13,11,15,87,221,427,673,1631,599,3259,10691,31283, + 1,3,5,11,9,9,15,49,275,335,1613,3587,5309,14849,26475, + 1,3,7,9,29,13,79,225,381,781,1411,2761,7157,14983,19717, + 1,1,7,11,29,25,117,183,101,651,653,3157,445,14389,23293, + 1,1,1,3,5,33,73,155,473,387,591,2045,5965,16299,31499, + 1,3,1,7,11,33,29,21,491,937,729,4075,975,2461,18991, + 1,3,7,15,29,39,105,111,173,943,69,295,8175,13037,26131, + 1,1,5,15,7,5,97,147,105,887,443,2595,5889,10753,1619, + 1,3,3,15,11,45,87,207,353,909,1847,323,2283,12885,16415, + 1,1,5,3,19,33,43,79,115,653,359,2873,4609,12439,6339, + 1,3,7,9,17,61,49,227,291,69,1753,3899,483,3187,29041, + 1,3,5,3,25,35,61,211,393,199,691,1779,6295,13371,15817, + 1,3,7,5,7,23,37,91,245,915,579,867,6193,1063,17363, + 1,3,7,7,23,51,41,63,375,3,159,1889,4419,1687,17977, + 1,1,1,7,13,11,53,43,317,325,1749,2423,4123,8595,20773, + 1,1,7,7,9,9,61,113,437,213,1407,645,4345,807,30411, + 1,3,3,11,17,39,17,113,391,385,581,2023,7449,10153,22033, + 1,1,3,5,29,31,101,215,379,377,1113,2855,7147,14377,25515, + 1,3,5,5,13,3,121,125,227,969,11,1115,5657,9209,6117, + 1,3,7,15,29,17,33,123,317,301,749,1365,5619,605,1613, + 1,3,1,15,7,53,125,249,219,655,105,2825,1649,12783,19777, + 1,1,7,1,25,53,19,53,157,373,1855,495,5065,9465,2313, + 1,3,5,13,3,57,57,161,431,415,1859,1033,6349,1577,31579, + 1,1,7,5,23,63,29,221,13,965,1997,2265,1583,10491,9551, + 1,1,3,13,31,25,23,61,285,5,2005,879,795,13299,19685, + 1,1,7,1,21,45,121,89,263,543,1333,2711,219,10823,26139, + 1,1,3,3,27,13,19,117,161,457,1541,295,4953,12125,14503, + 1,3,5,3,7,63,13,247,439,681,977,2537,6923,10323,7349, + 1,3,5,9,3,51,81,251,349,983,581,2515,2281,2849,31915, + 1,3,5,3,11,63,47,137,303,627,91,2269,7097,2145,31059, + 1,1,3,15,13,17,53,27,133,13,117,1837,4103,5843,29153, + 1,1,5,13,21,33,37,253,465,209,309,49,3209,15677,14569, + 1,1,7,15,13,21,33,203,499,141,1155,3893,1663,2115,27459, + 1,3,5,11,21,9,39,157,257,273,1257,1831,515,7969,20133, + 1,1,3,13,19,29,15,189,103,219,1395,517,7425,6585,15865, + 1,1,5,11,21,31,49,151,39,537,1783,3449,6915,223,11587, + 1,3,3,11,7,63,69,31,27,911,1903,2821,7977,12949,32257, + 1,1,7,9,25,45,23,233,511,595,1383,1721,6789,12055,21179, + 1,1,7,13,1,27,123,49,439,683,501,641,1947,6111,25423, + 1,3,3,5,1,23,57,241,243,593,2039,1617,2209,5171,9675, + 1,1,1,7,5,19,83,55,481,125,177,1021,1139,11403,23099, + 1,1,3,5,29,39,33,217,461,907,733,3795,4811,12939,27715, + 1,3,7,3,7,11,39,165,495,147,999,1827,817,603,9293, + 1,3,7,15,25,53,35,15,431,733,1213,2907,8087,3939,27363, + 1,3,7,13,13,9,33,27,485,183,455,3341,2555,4985,8793, + 1,1,1,15,25,47,75,21,205,15,1639,3067,1295,11693,16903, + 1,1,1,15,3,31,93,57,43,185,251,1899,7885,10829,3609, + 1,1,3,1,29,9,69,223,221,537,365,3411,5771,15279,5309, + 1,1,7,5,1,5,125,243,213,1003,1571,3355,3981,8781,25993, + 1,1,1,13,7,19,53,243,301,75,1183,2723,6687,13,16581, + 1,3,1,13,17,51,91,239,437,191,1065,2495,5755,3405,8299, + 1,1,5,5,11,59,21,169,299,123,1845,2199,2157,14461,10327, + 1,3,7,7,19,47,51,179,41,19,1347,2325,8063,5993,15653, + 1,1,1,9,25,27,7,133,223,533,719,353,7093,8285,10375, + 1,3,5,15,31,5,67,39,441,495,977,3699,1435,11385,14567, + 1,1,3,15,15,39,25,33,91,523,249,4035,769,5181,9691, + 1,1,3,3,3,57,83,187,423,165,161,3453,2241,981,8429, + 1,1,7,15,1,17,57,189,283,11,823,3505,7025,11879,15441, + 1,1,3,11,1,41,7,255,385,339,607,1405,1473,13697,9491, + 1,1,7,15,5,9,91,99,211,233,51,2663,1165,9283,18495, + 1,1,3,7,21,37,13,91,39,27,1021,2813,5937,6645,3403, + 1,3,1,1,29,29,5,69,399,665,1407,3921,2653,11753,18925, + 1,3,7,15,13,41,39,1,437,549,161,2315,5631,8335,22661, + 1,1,3,1,7,17,115,61,69,955,475,3763,8035,927,17893, + 1,3,1,13,21,59,81,145,463,145,1941,2777,7453,14229,11281, + 1,1,1,15,15,11,27,165,461,395,1645,3611,7463,12379,26787, + 1,1,7,9,29,19,27,123,21,149,1643,4001,7207,6769,4647, + 1,1,1,11,13,9,103,139,185,587,591,1113,2223,11667,32671, + 1,3,1,1,31,13,19,93,229,125,1471,2369,3055,10277,28563, + 1,3,7,5,7,53,99,175,161,851,617,4027,2357,11199,1931, + 1,3,5,11,3,31,111,179,237,845,539,1057,259,3417,26637, + 1,1,5,3,21,49,125,119,463,403,737,1811,3941,13015,29081, + 1,3,5,13,5,29,69,251,313,357,663,1097,3307,12845,28495, + 1,3,3,5,29,17,89,15,411,409,2013,757,4085,12521,11131, + 1,1,1,15,7,51,3,193,493,133,381,2027,227,6635,12931, + 1,1,1,15,7,23,99,203,323,1007,1465,2887,2215,1787,22069, + 1,1,5,9,29,59,77,151,509,313,415,3977,5431,8019,8571, + 1,3,1,15,19,13,57,217,87,119,25,1149,5667,3765,6959, + 1,3,7,13,19,31,119,3,457,117,905,361,1483,12405,27005, + 1,3,5,11,15,35,61,77,119,51,1753,2765,1091,10573,23595, + 1,3,3,7,1,35,17,93,197,511,1253,3031,2739,15127,15147, + 1,3,3,1,11,55,55,107,161,75,129,2195,2023,4877,25797, + 1,3,5,7,23,19,113,167,167,271,1303,125,5057,1323,5165, + 1,1,5,3,21,31,11,119,215,483,1535,407,6485,15401,30297, + 1,3,5,9,21,5,77,95,443,247,913,605,365,7465,19707, + 1,3,1,7,17,59,9,35,391,767,1493,475,4725,7529,31579, + 1,3,3,7,31,21,61,31,421,179,273,771,5745,10575,32765, + 1,3,5,15,27,13,125,55,423,1021,497,3521,6903,15111,8285, + 1,1,5,9,13,31,105,93,421,709,643,1079,1533,9149,10799, + 1,3,1,11,19,29,53,199,319,247,655,3039,6411,12267,14245, + 1,3,1,11,9,57,5,91,469,149,259,329,5433,6941,15093, + 1,3,1,5,5,51,59,25,455,367,1623,441,3155,11695,20767, + 1,3,7,7,11,49,113,95,91,389,605,1973,2051,2315,22229, + 1,3,5,3,19,11,99,135,433,781,1473,885,1105,3573,3739, + 1,3,1,11,3,25,9,227,433,723,317,139,6627,8067,28439, + 1,1,1,9,9,9,5,63,241,215,1991,2949,3943,775,31511, + 1,1,3,7,17,49,35,167,131,107,1295,2465,4577,11147,29833, + 1,1,5,1,5,25,119,129,391,743,1069,2957,349,6891,13635, + 1,3,1,7,9,31,63,253,215,51,1347,2361,3125,13049,28461, + 1,1,7,9,3,31,21,163,255,47,259,535,5461,3349,30649, + 1,3,3,13,17,33,87,47,243,709,929,3943,3107,3421,13721, + 1,3,5,11,25,61,61,173,397,735,2005,3355,8121,11593,27697, + 1,3,5,15,17,43,63,231,275,311,1277,2669,7307,2099,9755, + 1,3,5,3,25,43,71,191,9,121,1873,3747,7491,14055,24293, + 1,3,5,13,17,35,113,113,385,941,39,2705,1225,5167,1373, + 1,3,5,5,7,35,19,105,487,71,139,627,4187,3183,713, + 1,1,5,13,29,29,103,5,157,869,1675,423,6689,10697,5303, + 1,1,5,1,29,31,61,111,473,963,685,1483,2383,8109,8495, + 1,1,5,3,19,13,95,113,217,59,1353,1647,3617,3271,2321, + 1,3,5,7,25,35,59,131,309,445,415,93,1453,8789,30201, + 1,1,5,1,5,43,71,241,123,189,831,3469,8093,6187,32721, + 1,3,7,5,25,31,123,171,319,379,889,2365,4881,12225,16609, + 1,3,1,11,27,43,121,63,291,591,811,1995,4777,2083,31385, + 1,1,5,11,27,53,85,187,461,823,703,399,6925,11517,28697, + 1,1,3,5,13,11,33,121,93,717,1275,3877,4247,5845,26909, + 1,3,1,9,7,5,47,199,367,561,185,2855,5997,2699,7581, + 1,1,5,9,23,11,71,201,61,729,1011,3529,663,1413,25675, + 1,3,7,13,27,21,11,127,281,487,1217,3129,5541,3129,17783, + 1,1,5,9,1,29,85,193,213,743,1473,611,391,9405,21137, + 1,3,3,3,31,63,37,147,39,351,79,3069,2441,8901,8777, + 1,1,7,7,25,49,55,47,441,343,1267,1123,5917,14395,10579, + 1,1,7,1,13,55,55,123,103,773,125,2145,4743,13347,2589, + 1,3,7,3,9,33,25,183,469,213,291,75,6725,6847,26745, + 1,3,3,7,15,43,7,79,171,21,1767,2537,4285,12007,24039, + 1,3,7,13,9,61,125,23,227,879,215,1635,2835,883,15939, + 1,1,5,13,25,45,63,43,183,829,149,989,987,3819,12181, + 1,1,3,7,19,27,35,83,135,459,785,131,2655,3329,3009, + 1,1,7,5,11,41,9,219,475,985,1329,3787,1975,4679,8627, + 1,1,7,3,1,17,91,155,3,763,1879,233,215,2955,25993, + 1,1,1,11,25,11,23,227,453,775,1935,3833,4583,269,705, + 1,3,3,11,7,25,105,21,449,555,1275,3475,5503,15617,813, + 1,3,7,13,31,37,25,255,233,663,1155,1563,4775,7449,29949, + 1,1,3,1,23,51,51,137,63,809,349,2789,6953,10605,18959, + 1,3,3,13,21,45,15,161,393,229,437,2967,4019,3893,21305, + 1,1,3,7,5,11,15,211,287,131,1847,2569,7881,15669,31037, + 1,3,3,15,27,19,85,251,221,639,665,3729,5771,7873,28005, + 1,3,7,15,15,47,93,215,343,85,1401,1375,2949,13661,25453, + 1,1,1,9,7,51,53,217,471,389,551,1141,1767,2237,17797, + 1,1,7,9,3,29,65,29,223,591,1719,1049,7643,3853,29867, + 1,1,1,11,13,41,85,29,451,387,1783,3733,8033,4711,31643, + 1,3,1,11,11,57,75,153,7,373,2011,271,469,3267,18969, + 1,1,5,3,19,43,7,243,385,293,923,843,4895,469,8421, + 1,3,1,15,29,47,17,125,471,927,349,3859,3059,11483,14791, + 1,3,1,11,17,17,111,109,9,213,1313,3903,4411,4329,28277, + 1,3,3,15,1,55,47,69,143,789,1149,3833,5053,6949,10569, + 1,3,5,7,11,15,79,83,123,937,1115,2775,3041,11869,21167, + 1,3,7,13,9,47,45,221,139,923,1661,1379,2485,7233,6035, + 1,1,3,3,11,55,77,3,87,693,1991,1145,2783,16207,24569, + 1,1,5,11,3,35,91,9,391,927,101,1839,3755,10345,16907, + 1,3,5,3,5,49,79,91,205,443,1369,197,2537,11219,17765, + 1,1,3,15,9,7,25,25,357,247,477,421,7679,5987,30079, + 1,1,5,3,29,5,89,117,481,491,371,389,7101,2253,23617, + 1,1,5,13,29,59,17,181,511,291,1991,3499,8177,5559,30045, + 1,3,3,11,23,31,117,217,241,115,749,945,1897,12253,8473, + 1,1,7,15,25,47,31,1,165,311,635,3629,1593,8305,30033, + 1,3,5,9,3,17,101,237,379,503,49,929,1687,3865,26723, + 1,3,5,5,15,41,1,239,53,215,1733,827,579,4089,6579, + 1,3,1,15,15,21,35,21,403,257,1475,2403,4705,11553,203, + 1,3,5,11,9,53,113,9,447,511,543,3141,7389,11249,431, + 1,3,5,9,9,11,55,93,325,411,305,2573,6871,12339,6435, + 1,3,3,7,31,27,21,113,99,853,365,589,3731,10875,12767, + 1,3,1,7,15,27,31,17,275,93,1161,2619,1329,7307,587, + 1,3,5,9,17,47,49,237,27,193,1237,591,5151,5521,31583, + 1,3,5,3,13,1,27,87,43,977,305,3293,2475,14571,18321, + 1,1,5,7,15,13,101,1,291,807,1711,2277,5573,11051,13133, + 1,3,3,1,9,3,65,81,415,733,1527,2747,6069,159,7095, + 1,3,3,15,27,1,71,49,231,851,2039,613,1899,2537,14511, + 1,1,1,11,3,41,55,23,247,1011,581,2363,2745,1337,20931, + 1,1,3,11,17,61,67,255,143,357,945,3407,5817,4155,23851, + 1,3,5,3,23,1,75,247,265,413,1899,2565,6629,15655,16117, + 1,1,1,9,11,49,11,189,223,177,1457,1931,163,15905,17297, + 1,3,7,13,17,1,111,189,343,961,427,2507,2393,8653,6353, + 1,3,7,13,23,61,59,51,313,963,791,3681,5637,3965,9263, + 1,3,7,7,21,53,127,141,499,859,337,2835,3195,4351,32369, + 1,1,7,5,1,5,53,63,497,535,35,305,4395,9757,13193, + 1,1,5,13,13,31,59,229,211,745,1453,3677,3005,7703,23907, + 1,3,5,5,7,63,17,197,493,861,499,3015,6349,1815,7437, + 1,1,1,13,13,37,29,189,253,1017,321,3145,407,7547,17099, + 1,3,3,3,23,53,69,77,175,17,1831,841,3851,1295,32107, + 1,3,7,13,13,39,107,237,389,729,635,3717,3041,3169,14987, + 1,1,3,1,25,7,69,35,495,49,659,2783,6051,13875,23927, + 1,3,7,5,5,25,49,7,193,493,93,657,1515,13975,14155, + 1,3,1,1,11,15,113,45,21,595,731,3397,4117,9711,16625, + 1,3,3,9,19,19,59,7,105,579,599,2859,97,14717,15361, + 1,1,1,5,27,49,113,5,367,563,1397,2805,3021,3111,20671, + 1,3,3,15,27,51,99,167,109,365,1959,1523,6959,14405,18191, + 1,3,1,5,21,51,125,67,123,45,1657,51,4825,14081,31049, + 1,1,5,7,21,59,21,249,77,793,1687,2561,2241,4321,7477, + 1,1,1,7,15,35,71,29,267,611,1813,1823,7039,3299,9919, + 1,3,7,11,21,59,109,213,371,785,659,1687,4827,6017,19619, + 1,1,3,11,27,17,1,55,367,939,333,127,5105,2405,28139, + 1,1,7,13,5,35,59,133,509,573,625,3857,7935,5279,3727, + 1,1,1,7,11,47,127,157,19,403,151,1143,7407,8985,32521, + 1,3,1,1,5,13,105,123,63,139,1569,1983,563,7175,27705, + 1,1,3,13,9,35,105,227,145,21,1369,57,393,2921,18511, + 1,3,1,7,17,61,99,187,261,281,437,2219,5999,1857,18001, + 1,3,3,5,1,59,67,45,451,439,2005,3607,3,7167,14227, + 1,3,3,3,29,19,25,251,275,733,1749,4021,871,3227,13701, + 1,3,3,13,27,53,57,243,491,521,1921,1037,5013,5703,15261, + 1,3,1,11,13,57,1,15,123,533,785,335,1423,14269,3483, + 1,3,7,13,15,55,5,139,385,47,1981,1291,7397,12925,29445, + 1,1,7,1,23,23,59,93,117,57,63,3047,4849,11637,25311, + 1,1,7,13,19,37,25,203,477,447,1345,3485,2099,13347,11621, + 1,1,7,3,11,23,81,17,41,735,1149,3253,7665,8291,22293, + 1,1,5,3,15,9,57,167,463,493,747,1947,6471,1111,31619, + 1,1,5,15,7,15,107,205,325,167,1749,927,3589,6127,7617, + 1,1,1,13,21,25,83,147,411,399,1423,2279,3661,7591,17429, + 1,1,1,9,5,17,69,205,243,647,473,1717,1977,10725,2913, + 1,1,3,5,5,37,103,15,485,641,1761,3755,6997,10985,11773, + 1,1,5,13,9,51,87,195,97,807,1801,961,6341,4307,29105, + 1,3,1,13,9,35,83,61,387,817,951,3993,7831,8479,23941, + 1,1,7,11,19,47,75,37,91,337,953,1169,163,2259,24713, + 1,1,1,11,13,15,83,171,159,87,619,2973,2653,13725,12499, + 1,3,5,3,5,63,119,25,343,269,553,2183,959,3825,22189, + 1,1,5,15,5,37,89,109,497,1013,265,669,1859,2647,3445, + 1,3,3,9,21,21,15,245,107,649,367,1601,7279,15783,4943, + 1,3,3,15,5,41,125,113,159,161,1191,3491,3531,55,20857, + 1,3,5,9,21,57,21,195,99,193,1915,2923,6349,15085,24929, + 1,1,1,11,31,11,73,141,361,621,1021,2067,5115,12665,26845, + 1,1,1,3,29,11,43,61,209,923,1753,1937,843,205,8367, + 1,1,1,5,15,33,119,209,215,973,1775,815,6693,7957,14517, + 1,1,1,5,17,57,27,147,489,59,1439,2279,445,11791,19739, + 1,3,1,7,11,55,1,83,305,17,1909,405,2325,5293,28559, + 1,3,3,7,11,27,103,157,455,1005,2033,3145,1919,15723,25197, + 1,1,5,11,15,51,37,131,503,1007,1795,2421,1335,7413,21741, + 1,1,3,1,23,63,69,83,419,283,583,123,7725,2243,8403, + 1,1,5,5,27,45,109,17,299,65,351,947,1165,10723,2053, + 1,1,3,3,23,61,115,253,1,931,1481,3187,441,14735,27207, + 1,1,5,3,25,11,83,141,359,343,901,1629,731,12841,14357, + 1,1,3,9,7,45,97,3,299,217,663,1527,6379,4527,26147, + 1,1,7,9,11,53,9,203,337,713,1517,719,4587,11443,26905, + 1,1,7,9,11,41,125,213,237,377,361,3231,4223,3263,12655, + 1,3,7,7,7,33,99,19,117,273,985,107,3831,10135,19423, + 1,1,5,15,25,41,13,125,449,169,1149,4021,5663,3077,19163, + 1,3,5,9,25,57,47,103,269,51,1805,2503,6687,8065,12045, + 1,3,5,7,3,35,87,225,189,229,931,3293,1347,1427,3269, + 1,1,1,3,5,31,61,19,247,9,1667,343,559,2703,3763, + 1,3,5,15,31,19,57,187,109,121,1287,2269,659,16235,1273, + 1,1,1,3,5,47,59,243,255,97,1959,1723,1347,3019,26989, + 1,3,3,15,29,35,75,67,497,731,193,3307,3579,12005,7209, + 1,1,5,9,13,35,79,213,51,983,1927,1793,5037,5463,965, + 1,1,7,11,5,41,7,83,15,411,1775,3515,6755,3249,16425, + 1,3,5,1,19,61,3,19,395,819,1331,179,5225,5333,3601, + 1,1,3,9,7,5,87,15,387,609,1465,277,987,8377,903, + 1,1,1,3,15,11,123,107,355,333,285,1801,6989,1549,25791, + 1,1,7,13,27,13,73,111,481,227,1091,365,5713,5087,27217, + 1,3,3,15,1,55,95,213,377,405,139,1867,2175,4217,28813, + 1,3,5,11,21,43,109,155,181,901,1951,507,4389,10815,3141, + 1,1,1,15,17,11,43,215,501,19,259,3479,6381,6927,31247, + 1,3,5,15,19,61,75,41,391,95,865,1441,7993,13979,24663, + 1,3,1,3,21,15,115,213,1,645,777,1517,2543,11223,3633, + 1,3,5,3,9,57,39,211,407,65,1795,2805,2799,8691,1987, + 1,1,3,13,17,55,47,113,29,139,1301,3303,1129,13947,29821, + 1,1,3,13,5,35,97,151,477,409,1397,3399,4421,15929,6163, + 1,3,1,9,21,51,99,133,149,763,623,173,4311,11081,1095, + 1,3,7,15,13,3,99,3,195,907,1335,1355,7977,5773,32383, + 1,1,3,9,17,43,43,217,475,917,1373,1677,4871,9619,16657, + 1,3,3,7,31,31,55,11,73,693,25,417,1195,6225,32279, + 1,3,5,9,21,57,127,149,79,379,1609,2543,6473,16033,27191, + 1,1,5,1,13,9,81,153,297,789,1749,2819,3961,11231,24927, + 1,3,5,3,23,61,45,43,43,133,1481,1543,2991,13739,10287, + 1,1,3,9,25,43,31,177,337,193,1083,1,991,9725,8379, + 1,3,5,11,13,33,65,83,421,149,409,2443,7423,8847,29599, + 1,1,5,11,11,1,23,225,77,585,1505,2525,739,10915,25733, + 1,3,7,13,7,55,3,223,415,521,1865,2349,5663,7455,16569, + 1,1,7,13,1,45,121,49,463,99,1061,2559,5087,13389,11035, + 1,3,7,11,31,51,35,235,385,1023,1771,2013,5437,4877,22119, + 1,3,3,11,21,3,11,119,81,737,1093,2377,4055,1121,15767, + 1,1,5,13,9,3,83,217,387,249,1047,1861,4103,15367,24545, + 1,3,3,1,5,37,43,183,383,463,937,1165,1481,959,17047, + 1,1,3,5,7,43,127,243,81,1021,165,753,4711,12965,22049, + 1,1,5,5,3,61,65,53,425,89,5,1467,1395,9579,8961, + 1,3,7,13,11,35,123,21,83,689,667,1203,5959,15697,26885, + 1,1,5,13,9,49,41,101,291,339,1067,657,4453,1137,21131, + 1,3,3,3,17,61,11,213,27,805,1691,1057,6011,11941,18883, + 1,3,1,7,3,51,5,63,121,3,245,2631,3737,16121,26803, + 1,3,1,1,23,51,79,19,161,107,609,3489,3389,4035,2427, + 1,3,1,1,17,11,101,101,373,63,1641,285,1333,165,14025, + 1,1,1,5,1,51,83,137,45,1019,821,867,6055,10443,9857, + 1,3,1,5,17,23,25,181,429,495,317,3219,5963,13945,9969, + 1,3,7,3,3,15,123,191,369,177,1697,2113,3889,5201,21839, + 1,3,1,11,21,39,51,139,271,605,1007,3513,3365,3781,6799, + 1,1,7,5,13,19,47,165,249,405,255,1295,4513,14395,5587, + 1,1,3,7,5,17,99,1,393,31,621,797,6113,16003,32043, + 1,3,5,13,11,21,65,81,147,443,775,3671,7029,11749,3339, + 1,3,7,1,23,33,99,177,161,577,1729,617,3465,11787,17577, + 1,1,5,7,15,15,53,193,97,255,1223,545,5153,873,24525, + 1,3,5,1,7,57,47,121,383,835,1709,2363,4731,12163,7001, + 1,3,3,11,19,33,63,99,387,95,783,1009,6373,4021,7685, + 1,1,1,15,25,33,73,135,335,785,935,1927,5847,10501,7719, + 1,1,5,3,27,45,71,215,489,157,1189,2577,6901,10219,3025, + 1,1,7,7,21,3,97,225,101,159,293,2789,7955,14829,1209, + 1,3,1,5,23,41,83,63,361,195,1707,2081,5363,6327,179, + 1,1,3,1,21,51,59,67,175,363,825,2971,3321,8837,11805, + 1,3,7,1,19,3,15,21,429,675,1589,2615,2575,1537,7139, + 1,3,3,5,21,29,17,115,345,397,523,1699,7043,11173,3023, + 1,1,5,7,19,63,99,175,91,433,153,3749,517,13667,7423, + 1,3,7,3,25,23,53,149,65,551,1231,365,6637,15137,16319, + 1,3,7,13,5,45,11,151,323,31,1749,409,6753,10503,14991, + 1,3,7,3,5,21,29,117,321,341,1811,3619,4337,12255,8629, + 1,3,7,3,7,3,5,221,407,671,1763,3669,2353,8175,23489, + 1,1,3,7,11,55,53,185,247,35,1823,513,1379,11827,20069, + 1,3,3,5,29,51,73,191,185,961,881,2019,5651,1019,15587, + 1,3,7,13,7,55,59,5,417,829,453,2339,587,13283,797, + 1,3,7,3,11,41,75,85,65,149,1583,529,2707,11479,7109, + 1,3,7,9,13,57,37,243,91,613,665,171,1631,13737,2377, + 1,1,3,7,5,43,97,53,477,793,999,3647,2555,7371,19295, + 1,1,7,1,1,9,99,253,317,817,1559,2081,2529,14611,15997, + 1,3,3,1,5,41,57,121,387,441,709,1511,7045,8409,13297, + 1,1,1,13,29,57,63,183,327,473,1943,213,3973,16289,2739, + 1,3,7,9,25,15,75,185,335,881,1041,3339,4471,6823,21121, + 1,3,3,13,23,3,57,117,511,927,771,3229,949,15487,11963, + 1,1,3,7,27,19,55,207,331,705,1945,797,7125,10493,16585, + 1,3,1,1,29,7,91,93,459,93,1501,1927,6415,16255,9823, + 1,1,5,5,31,11,97,179,505,807,877,4003,4377,8851,4239, + 1,1,3,5,11,25,17,131,23,95,311,1429,2029,13091,23739, + 1,1,3,11,13,27,33,127,481,117,1127,1619,6493,8507,6615, + 1,3,1,13,19,27,89,101,27,235,1579,1701,4421,16037,16239, + 1,3,1,15,1,15,3,117,317,475,1691,2423,5519,1703,2969, + 1,1,3,1,13,15,19,37,237,467,1321,453,2169,13313,31499, + 1,1,3,15,29,55,31,199,85,285,967,367,3941,151,20587, + 1,3,7,15,7,13,31,35,117,543,1179,3441,3039,11225,30229, + 1,1,3,15,3,43,1,63,353,395,1775,3493,5175,13193,25343, + 1,3,3,15,17,25,57,205,411,83,1877,2093,5599,12115,8751, + 1,1,1,11,15,9,115,99,85,887,987,4015,7077,3739,21505, + 1,3,1,11,25,39,127,37,329,273,1531,3211,7115,15501,26575, + 1,1,5,13,15,3,3,101,431,645,493,723,8083,1423,14879, + 1,3,3,5,31,35,37,131,259,849,325,3403,3627,3295,30885, + 1,3,7,1,9,3,31,201,379,907,1005,3333,7457,2533,30357, + 1,3,1,9,7,7,95,103,121,157,895,2683,5839,12403,14327, + 1,3,7,3,13,5,55,233,3,855,859,1115,3883,8041,3353, + 1,1,5,9,3,55,99,79,263,831,1579,205,5673,1999,14879, + 1,3,1,5,17,25,85,19,189,141,877,667,4461,11915,23247, + 1,1,5,5,1,35,15,219,469,725,1793,3683,3661,15627,30197, + 1,1,7,5,27,3,41,153,431,487,759,1345,6735,9937,26277, + 1,1,1,11,11,13,41,121,265,465,1447,5,3407,1907,10037, + 1,3,5,9,15,63,5,7,407,83,365,3687,7721,6973,16967, + 1,1,7,7,5,41,75,155,417,565,1199,1111,2823,10703,22561, + 1,3,7,5,7,43,39,185,105,327,1977,1137,3261,10583,11661, + 1,3,7,7,19,19,103,137,169,273,1357,3413,7647,10531,32489, + 1,1,3,13,13,3,81,23,161,295,735,2031,1027,15513,20165, + 1,1,5,1,15,1,91,35,375,207,1417,1115,2237,11749,8509, + 1,3,7,3,25,51,49,219,195,417,1523,3953,5739,7499,27071, + 1,1,3,11,23,29,19,81,421,633,513,547,7545,29,11909, + 1,1,1,7,13,61,33,243,221,231,111,879,2861,1795,27531, + 1,3,7,3,19,21,1,141,159,605,969,3013,6583,2447,19919, + 1,3,7,3,31,9,91,83,29,873,929,43,2253,12539,23951, + 1,1,5,3,31,15,87,105,319,973,1489,3417,3377,15749,2357, + 1,1,3,15,7,23,3,81,383,419,713,997,6873,593,285, + 1,3,3,1,29,13,29,101,441,693,2039,2951,5921,12129,12053, + 1,1,3,15,9,29,97,117,421,433,1017,125,3607,9415,6843, + 1,3,5,9,11,13,75,155,413,75,109,1599,6161,16115,12621, + 1,3,3,3,11,13,49,225,401,599,1815,1643,7853,13305,25195, + 1,3,7,5,15,11,27,95,387,931,549,2179,3397,15883,16563, + 1,1,7,3,9,39,121,5,453,27,1747,657,2593,1289,12577, + 1,3,7,5,25,25,109,49,185,985,631,803,3865,8955,17901, + 1,1,3,13,3,59,47,49,139,275,1471,2995,5593,14011,18741, + 1,1,5,15,29,11,97,225,245,291,1873,2365,767,3419,14943, + 1,3,3,5,15,17,19,209,359,891,1375,2003,7247,5299,28841, + 1,3,7,7,9,55,105,35,77,47,1023,13,2901,847,10265, + 1,3,7,7,7,5,65,233,141,277,1333,2357,443,7257,21979, + 1,3,5,11,13,63,41,87,193,737,1085,2317,7869,10149,12163, + 1,3,1,1,7,57,75,235,461,857,155,2679,5925,2565,10881, + 1,1,7,15,13,41,63,135,433,387,1943,2249,5469,11679,28661, + 1,3,3,13,5,3,103,161,367,649,789,1179,4163,5699,16787, + 1,3,7,7,31,13,45,141,113,769,1035,457,6709,14989,27311, + 1,1,3,1,1,43,119,145,111,593,1139,417,637,4437,17285, + 1,3,5,9,9,33,19,99,201,685,1793,2621,6857,8769,5623, + 1,3,5,5,23,43,27,189,325,415,215,1253,3599,1215,10093, + 1,1,3,13,11,35,113,173,503,19,1459,503,5363,3967,13945, + 1,1,5,11,31,49,13,173,199,623,1231,2495,6581,7957,25321, + 1,3,1,9,23,3,79,149,505,937,1839,3701,1673,8589,8031, + 1,3,3,5,21,27,107,11,505,407,177,3593,4729,12773,11685, + 1,3,1,11,29,49,79,53,61,895,2035,563,5613,6065,6207, + 1,1,3,7,1,53,3,215,99,865,1749,3533,4305,1243,28463, + 1,1,1,13,31,59,115,53,403,909,847,103,4967,10623,30073, + 1,1,7,5,27,1,119,83,457,81,395,811,6221,14337,541, + 1,1,5,5,5,53,83,117,269,327,875,101,3343,715,26339, + 1,1,1,11,31,39,121,147,305,383,1211,1897,7647,11687,18907, + 1,3,3,15,23,53,17,85,395,503,61,1745,4713,4641,13787, + 1,1,7,7,27,1,105,29,287,37,959,975,4427,4705,10175, + 1,3,3,5,7,63,57,199,27,107,1095,3923,6969,713,11619, + 1,3,5,1,5,49,85,45,449,45,49,3419,1109,455,15917, + 1,1,1,5,13,15,39,27,467,85,1537,3055,1977,8829,25231, + 1,1,1,15,1,47,23,121,147,547,1865,1491,779,3515,12667, + 1,3,3,1,19,5,77,101,1,721,1149,2967,4925,11889,16655, + 1,1,1,7,1,35,95,239,127,855,1031,455,7631,6039,21983, + 1,3,7,9,23,43,75,105,335,223,1825,3217,413,7473,30005, + 1,1,5,15,29,9,43,145,223,523,511,323,5955,11141,22533, + 1,1,3,1,13,61,93,133,461,233,383,693,7347,3165,27493, + 1,3,7,1,13,45,113,207,53,1007,815,1145,2937,289,22195, + 1,3,5,5,19,17,113,89,19,1023,1625,3277,697,5187,15433, + 1,1,3,13,21,15,15,197,409,391,1993,2475,3189,4431,29585, + 1,1,5,5,31,7,111,231,187,543,45,3863,3811,4573,4437, + 1,3,3,7,19,7,123,23,79,513,189,3663,1291,13257,8949, + 1,1,5,13,3,53,109,133,157,223,651,3059,6055,14455,26903, + 1,1,7,1,23,63,59,229,17,199,643,637,7631,13647,7399, + 1,1,1,3,1,51,119,67,335,543,913,3565,4795,13405,7463, + 1,1,5,3,31,5,91,97,23,223,837,1353,1929,12043,10039, + 1,3,5,7,19,3,79,171,301,687,1545,355,4709,12965,16797, + 1,3,5,11,11,49,111,123,251,569,1605,401,5439,13519,8847, + 1,3,1,3,3,53,7,55,369,633,181,4037,2993,15815,8661, + 1,1,1,13,31,29,75,167,279,597,539,1791,8013,4387,9717, + 1,1,5,7,17,15,99,183,211,49,225,3143,4537,13141,23375, + 1,1,3,5,3,59,25,149,467,69,1939,1007,2765,4693,29815, + 1,3,1,3,17,33,119,189,447,251,879,177,5395,13487,9587, + 1,3,3,7,15,31,115,3,21,817,475,1849,6041,12541,18701, + 1,1,5,13,31,33,7,115,361,587,1919,1007,3537,7493,19357, + 1,3,7,13,23,35,15,111,123,633,805,1983,2109,14477,4985, + 1,3,3,11,25,13,11,205,97,893,927,1291,4007,13593,29693, + 1,3,5,15,9,13,121,89,215,823,1389,1581,8095,4707,16061, + 1,3,1,3,23,39,83,23,47,941,1419,2389,5699,7519,5829, + 1,3,1,9,23,43,79,237,93,203,695,225,5645,3591,16775, + 1,3,5,3,15,19,89,129,375,125,225,1323,2267,11607,17937, + 1,3,3,1,31,37,93,133,377,959,707,621,7179,15493,30287, + 1,3,7,13,5,13,15,1,37,525,1641,2829,6139,4069,19187, + 1,3,3,9,17,3,67,97,375,845,403,973,3919,2275,31627, + 1,1,3,3,25,7,91,67,271,465,481,3477,5229,241,8411, + 1,1,1,11,1,41,109,115,75,787,309,2887,179,9073,13895, + 1,3,3,15,11,31,113,91,303,907,1933,2167,7799,11821,20659, + 1,3,1,15,27,17,21,41,99,137,1397,929,5819,11977,6201, + 1,1,7,13,21,29,47,239,287,305,899,2711,1723,3315,199, + 1,1,1,3,31,21,101,149,107,761,1197,1703,4803,8411,10649, + 1,1,5,15,23,45,109,221,85,619,169,1013,3305,9451,26189, + 1,3,5,13,7,57,19,153,231,627,565,1595,6309,5037,25505, + 1,1,7,7,1,45,43,79,271,59,219,2255,1785,7919,24061, + 1,3,7,5,31,57,57,231,33,227,531,679,1141,85,19777, + 1,1,3,15,11,59,59,169,459,693,907,1191,3783,12809,6263, + 1,1,7,13,19,21,105,65,267,141,1547,781,7295,13565,17775, + 1,3,3,5,31,63,97,155,477,661,329,797,2539,4061,10537, + 1,3,3,7,11,17,119,89,71,103,1043,413,6035,12829,11559, + 1,3,1,9,5,19,53,185,103,629,2015,1257,5163,10581,13449, + 1,1,1,5,23,35,25,129,179,959,677,2249,6315,12151,3459, + 1,1,1,1,9,47,93,45,35,45,265,2065,6225,25,27135, + 1,3,1,11,21,53,127,163,311,667,597,1561,4515,23,9551, + 1,1,3,3,7,47,105,211,241,95,389,899,6001,8129,19889, + 1,1,3,15,29,45,9,27,483,799,269,1811,4493,7109,22149, + 1,1,3,3,29,5,57,205,187,615,1677,3987,4577,8799,16311, + 1,1,5,3,15,5,91,101,319,445,1261,2039,4071,8249,11611, + 1,3,7,11,19,17,1,185,153,579,1001,2031,2295,16335,24771, + 1,3,3,15,13,45,93,185,319,667,1085,93,577,11551,11355, + 1,1,7,13,3,61,45,191,51,981,1151,2715,2503,4147,4587, + 1,1,3,3,27,17,71,141,57,981,1033,333,4639,15885,1039, + 1,3,3,15,21,55,33,123,357,893,829,4045,5027,11727,13357, + 1,1,1,9,31,47,27,223,311,205,179,3411,4019,10997,28115, + 1,3,5,1,3,39,15,7,501,641,735,295,2005,12641,19779, + 1,3,3,1,15,1,75,243,329,267,1323,2285,5389,11881,15737, + 1,1,3,3,13,17,101,99,209,939,1147,3221,5159,3435,183, + 1,1,1,1,27,43,29,179,179,659,807,313,4165,963,11317, + 1,1,3,13,9,51,125,245,381,555,1383,3887,2045,12829,12029, + 1,1,1,9,29,39,55,127,235,617,1553,3133,7735,14725,16733, + 1,1,3,5,15,9,47,217,89,987,1083,1045,4745,12915,13719, + 1,3,3,7,23,3,35,79,45,435,1549,2645,2831,10359,10041, + 1,1,7,15,31,61,25,223,511,319,487,1677,739,7097,18417, + 1,1,7,5,19,21,123,237,299,367,1341,1449,2949,8629,11051, + 1,3,7,7,31,53,125,33,257,719,1297,895,5095,10237,12309, + 1,3,1,5,31,59,73,211,97,209,1289,4033,6143,14275,7997, + 1,1,5,7,31,5,75,105,389,985,9,4033,1185,7821,19083, + 1,1,1,15,11,39,73,253,275,813,25,3441,2493,5873,3739, + 1,3,7,1,31,19,119,5,109,397,1329,3347,5941,12449,2533, + 1,1,1,1,5,59,61,175,435,985,65,3781,5425,15073,16361, + 1,3,5,7,31,13,53,87,69,305,1455,273,2197,4277,24423, + 1,3,3,15,13,13,91,171,71,583,15,3599,6801,10041,26097, + 1,3,3,5,5,13,91,225,63,69,1795,341,461,5015,9471, + 1,3,7,5,21,55,109,39,459,925,229,2855,5807,2117,31739, + 1,1,3,3,1,5,17,177,401,727,1555,3097,1243,5933,14579, + 1,1,7,3,19,19,37,87,105,73,197,4067,6237,10553,9207, + 1,1,3,15,1,55,119,115,441,3,1003,1631,197,12929,25385, + 1,3,7,11,31,1,119,49,467,647,685,2771,3689,11049,26787, + 1,1,1,11,19,19,21,73,459,935,615,371,1099,14407,10375, + 1,3,5,13,15,3,107,179,259,677,1101,315,7673,14639,11241, + 1,1,7,9,15,21,93,25,349,23,1087,27,5691,12997,29301, + 1,3,3,5,7,43,1,195,69,753,1315,2629,3259,5595,19439, + 1,3,5,5,31,9,75,217,217,197,1925,2033,3585,15219,20251, + 1,1,5,11,17,31,3,209,315,49,949,2267,4611,4375,16431, + 1,1,7,9,17,35,13,115,119,553,1527,2857,3599,391,25101, + 1,3,3,15,13,59,17,177,301,719,909,1663,5033,1129,529, + 1,1,7,5,15,13,99,157,379,975,1019,2251,3807,10621,351, + 1,3,3,13,5,57,5,31,361,981,883,3723,2259,5151,11783, + 1,1,1,13,1,43,125,19,77,509,1817,3795,1863,8401,27253, + 1,1,5,7,19,41,21,151,89,189,769,1937,4497,13607,24691, + 1,1,1,9,21,9,1,195,31,907,1719,1549,809,13629,16597, + 1,1,1,3,21,61,103,219,311,849,523,21,4533,6367,3935, + 1,1,7,9,7,33,77,19,489,933,1729,1813,6741,10701,7, + 1,1,1,5,23,53,43,63,453,209,1313,2847,2641,13783,14983, + 1,3,7,7,15,45,83,241,509,659,213,221,5205,6019,18945, + 1,1,5,9,25,43,37,9,191,505,765,295,953,1045,11203, + 1,3,7,11,5,49,45,177,379,695,355,1711,7747,497,7597, + 1,1,5,13,23,47,101,145,301,207,195,2225,8093,15345,14097, + 1,3,7,13,9,9,55,223,343,921,1825,3281,2627,855,27651, + 1,1,7,1,21,1,67,149,433,111,577,3675,495,9043,23613, + 1,3,1,13,9,39,37,73,117,559,1131,2511,7599,8393,24747, + 1,3,3,7,11,15,85,229,7,21,1649,739,375,13991,27053, + 1,1,5,5,15,41,49,117,173,825,1343,377,1789,12519,30667, + 1,1,7,15,9,11,97,99,347,729,9,1703,1177,5189,9061, + 1,1,5,11,15,25,99,63,89,675,561,215,8111,3955,24635, + 1,1,1,1,7,53,99,193,233,731,733,1883,7783,14413,14003, + 1,3,5,7,31,23,45,153,337,293,443,2301,5135,7455,13123, + 1,3,1,3,23,53,23,165,53,875,1543,1035,4247,5101,28445, + 1,1,1,15,13,41,77,93,205,743,1101,1413,2371,7183,12337, + 1,1,3,15,17,63,25,101,147,149,1207,3525,2661,9539,11145, + 1,3,1,9,17,5,3,35,389,909,1017,2803,5243,13025,8851, + 1,1,7,15,19,27,69,91,71,547,1421,831,6969,5517,28233, + 1,1,3,3,17,45,55,63,263,819,1211,2739,655,13269,22281, + 1,3,1,5,23,13,81,251,83,551,491,1029,3561,357,23393, + 1,3,1,13,25,27,93,143,407,403,1395,1733,3187,1917,31453, + 1,1,7,13,3,21,85,113,483,461,1343,561,2081,10857,24253, + 1,1,1,1,11,11,53,135,25,163,1729,617,1533,10881,16041, + 1,1,5,1,3,49,125,139,77,891,815,3431,4875,12513,4595, + 1,1,1,1,27,63,111,109,421,425,345,1613,5447,1357,32413, + 1,3,5,3,17,5,37,171,259,281,1003,2901,3241,15557,21415, + 1,1,5,11,15,55,75,199,493,215,1625,2345,7873,2325,11003, + 1,3,7,1,21,33,23,5,495,941,1185,475,5799,15161,10677, + 1,1,5,9,31,37,37,29,217,389,297,3097,7319,2601,15307, + 1,3,7,5,7,45,111,167,297,275,1669,2489,1511,15753,1289, + 1,3,1,7,3,45,19,11,189,199,1227,2647,1897,9077,17189, + 1,1,1,13,15,39,19,179,147,341,283,3029,7599,8937,18761, + 1,3,3,9,3,11,41,255,365,835,921,389,919,15223,14541, + 1,1,3,3,5,37,29,203,313,271,1207,487,3711,3811,26757, + 1,3,7,9,19,53,49,139,351,537,1681,1595,5399,13839,28685, + 1,3,1,1,15,35,21,37,247,891,1855,1243,3137,10381,30379, + 1,3,7,5,9,47,91,25,479,337,781,3545,1045,9491,22853, + 1,1,5,15,19,31,81,5,117,923,565,2443,7383,1795,11685, + 1,3,3,5,17,15,21,245,489,889,2047,2737,7445,14785,13401, + 1,1,1,15,19,45,67,117,299,607,953,743,6863,12123,6701, + 1,1,3,1,1,43,19,129,345,861,209,2387,7205,7131,8235, + 1,3,5,1,1,13,75,99,333,157,23,1217,1857,15479,16031, + 1,3,3,11,7,61,119,89,491,401,227,1739,3807,16003,2875, + 1,3,7,15,13,55,3,159,405,593,975,361,2563,6061,28087, + 1,1,3,13,19,5,5,9,119,41,33,1111,4443,4663,28841, + 1,1,7,7,25,59,125,255,49,947,1673,2947,6369,2267,8813, + 1,1,5,15,25,25,111,193,217,193,821,2779,69,2957,27043, + 1,3,5,7,21,19,51,157,203,487,1745,1875,911,14071,7557, + 1,1,5,9,3,15,55,73,313,245,1061,1929,3035,607,11563, + 1,1,5,7,3,57,105,121,461,43,803,1801,4059,2157,17547, + 1,3,7,7,19,11,1,121,499,841,601,3515,2969,13697,8917, + 1,3,3,3,13,35,113,231,391,689,697,2871,7387,715,27005, + 1,1,1,13,19,5,17,43,175,291,987,1917,7635,15655,10689, + 1,1,7,15,19,37,121,243,125,623,1231,29,2325,5147,21435, + 1,3,5,15,25,27,57,187,77,401,1489,2977,5415,3381,2551, + 1,1,1,7,1,1,85,27,115,559,9,2365,711,5733,2819, + 1,3,1,15,9,29,61,113,169,349,591,1061,6041,7613,23691, + 1,1,5,1,13,45,49,227,345,563,87,3597,3961,7205,8441, + 1,1,1,5,3,21,121,183,463,83,1365,539,1485,10063,24867, + 1,3,5,5,3,61,101,237,41,147,1907,3049,7583,8283,6099, + 1,3,1,15,31,57,19,155,445,805,1793,207,1975,3357,14281, + 1,1,7,13,9,39,27,73,165,345,543,4095,133,10469,11573, + 1,1,7,15,17,57,99,81,359,367,1057,1173,4225,15127,2615, + 1,3,5,3,31,23,113,111,495,947,1625,1195,2053,1509,1347, + 1,1,5,5,9,47,25,63,455,107,771,3815,3827,16287,11615, + 1,1,7,9,17,61,51,215,63,123,1253,3927,721,9647,3283, + 1,1,5,15,11,17,83,255,473,107,681,763,7855,8043,31503, + 1,3,1,7,7,31,37,5,253,155,2017,609,1421,14927,25241, + 1,3,3,13,31,25,21,241,431,193,681,2265,5091,11479,21443, + 1,3,5,5,15,9,49,255,157,995,631,1995,3605,9085,24245, + 1,3,3,7,19,31,85,153,493,951,451,1587,6609,3681,13205, + 1,1,5,1,17,41,107,231,307,361,575,3239,3443,16159,20625, + 1,1,7,9,31,49,93,79,181,117,1241,3645,4901,12599,13247, + 1,3,3,9,7,31,127,201,11,199,1851,23,5667,8159,20951, + 1,3,3,7,3,37,29,189,65,461,769,321,6577,16223,16865, + 1,1,5,11,1,13,91,167,33,111,1445,1047,2479,12623,22893, + 1,1,3,1,3,1,47,185,329,903,1651,3005,907,1255,8303, + 1,3,5,13,19,31,5,233,265,769,1303,2503,2229,14019,20257, + 1,3,7,3,27,11,67,195,5,661,125,3761,7211,16043,7267, + 1,1,1,3,27,13,115,25,473,417,1751,2223,2099,5913,14273, + 1,3,7,15,13,53,99,115,225,737,1621,539,4131,471,31865, + 1,1,5,5,25,19,39,207,153,569,1755,2477,3065,7383,29919, + 1,3,5,11,13,59,33,3,435,273,701,3819,7291,11803,26111, + 1,1,3,9,29,19,71,59,93,1019,887,83,4675,7541,26821, + 1,3,1,3,21,53,71,73,43,321,1581,1399,4043,12995,16825, + 1,3,7,15,3,13,37,11,93,873,1193,3481,451,15869,17879, + 1,3,1,11,31,19,101,57,129,753,853,463,6757,11083,8667, + 1,3,5,15,25,41,25,197,235,609,905,993,3233,1935,24661, + 1,3,1,5,21,7,53,107,473,77,1135,1045,4933,5615,15931, + 1,3,7,11,3,9,105,183,151,527,425,975,4073,913,2793, + 1,1,7,13,19,61,81,9,413,851,1723,1113,1453,8635,3353, + 1,3,7,15,19,53,83,31,441,343,575,935,4543,1303,12567, + 1,1,1,5,29,19,119,75,3,591,845,649,1717,13695,26905, + 1,1,7,9,5,53,127,191,15,773,1433,2899,21,4977,17839, + 1,1,5,9,21,9,99,115,397,99,725,3835,973,1219,21159, + 1,3,5,3,7,39,29,93,303,913,981,3549,5225,10907,393, + 1,3,3,11,9,25,105,101,1,867,389,2241,773,14123,10015, + 1,1,5,1,1,37,117,213,391,779,1851,1485,1277,5607,819, + 1,3,7,1,3,5,43,47,483,367,749,1693,4961,15257,3775, + 1,3,3,1,27,11,21,83,437,379,1041,393,5611,2421,31739, + 1,3,5,7,19,1,79,63,53,201,1159,2501,6327,11317,9537, + 1,3,5,13,9,37,61,217,427,913,1311,3503,5473,10583,19723, + 1,1,3,9,11,29,121,175,141,515,925,837,6011,10419,32157, + 1,3,5,9,27,57,97,175,365,367,1737,3845,1257,12243,2201, + 1,3,3,9,23,1,53,123,127,333,1335,707,5747,6541,9809, + 1,3,1,9,17,37,101,41,91,61,433,979,4345,12351,10829, + 1,3,3,13,3,21,15,49,257,99,1793,2987,5233,11625,28069, + 1,1,7,11,21,13,89,11,135,153,783,2893,6815,12007,15605, + 1,3,7,13,5,61,73,5,269,699,925,2925,5919,5841,24875, + 1,3,5,5,25,45,43,93,15,927,1253,319,1173,14559,20221, + 1,1,3,3,27,45,9,103,447,627,1239,3869,2169,49,17917, + 1,3,7,7,11,9,1,1,1,527,825,3295,623,2095,10537, + 1,3,3,11,21,11,59,165,33,743,1461,1535,6393,1301,17823, + 1,1,7,3,19,43,47,245,469,551,1447,1963,169,1481,31925, + 1,1,3,1,11,21,51,7,251,199,1153,767,6417,3417,30171, + 1,3,7,1,31,5,41,103,447,263,211,2029,8021,4705,10579, + 1,1,3,5,17,25,55,75,393,107,2017,2389,1685,14021,9161, + 1,1,1,9,13,1,75,237,205,461,689,2531,2839,13925,23351, + 1,3,7,1,23,39,33,189,157,571,239,1053,1559,1685,23059, + 1,3,3,3,27,61,71,121,49,157,1341,1707,2417,11689,26507, + 1,3,7,7,19,63,47,53,95,791,1467,1273,2045,755,8555, + 1,1,3,15,27,33,21,253,317,153,1509,1765,3809,601,5907, + 1,3,5,15,11,17,97,91,165,199,1751,2135,1315,3077,29995, + 1,3,1,5,3,33,93,49,39,743,341,2549,7603,3369,30889, + 1,1,3,13,3,5,87,63,293,785,1591,675,3915,2209,18201, + 1,3,3,11,3,15,69,231,241,127,429,2201,8173,12549,25745, + 1,1,5,11,15,39,3,29,125,685,643,1385,829,7347,28793, + 1,1,7,15,27,15,59,237,299,773,1097,3875,6503,7129,28495, + 1,3,5,13,9,17,31,227,69,443,1633,525,1659,14681,15209, + 1,3,5,5,13,51,69,173,111,433,279,2145,2091,9741,24881, + 1,3,1,7,7,35,55,51,357,99,1789,333,2073,10151,14527, + 1,3,3,7,13,41,101,87,425,701,1143,2733,6473,8667,17419, + 1,1,5,5,25,29,63,31,385,537,563,607,6723,9251,6531, + 1,3,5,5,9,63,111,131,239,723,705,2805,6579,12691,17521, + 1,3,1,7,31,55,101,225,477,271,611,3179,7859,9835,2165, + 1,1,3,3,5,15,81,127,391,333,419,1091,5997,12315,31521, + 1,3,5,15,23,7,35,109,181,295,825,419,969,15753,9365, + 1,3,5,5,25,23,69,177,325,359,1577,619,6233,11753,8103, + 1,3,5,11,31,13,79,61,241,1011,1961,949,6211,497,7099, + 1,3,5,3,25,19,67,235,337,1015,1485,355,3653,12735,14503, + 1,3,5,7,31,23,35,231,147,15,263,1995,431,5941,18931, + 1,3,3,7,1,35,37,7,85,443,715,743,2189,12537,17427, + 1,1,3,1,7,41,1,209,121,929,661,3999,955,5123,31115, + 1,1,3,5,11,43,127,125,107,293,273,2071,3003,11631,7769, + 1,1,1,13,13,29,39,217,111,779,1287,1675,4201,4869,20403, + 1,1,3,15,25,53,25,135,389,925,1971,663,7545,2673,7725, + 1,1,5,13,3,59,97,91,357,45,947,3031,8095,6269,13975, + 1,1,5,15,25,31,1,171,375,939,507,3591,1089,13605,2813, + 1,1,3,7,25,21,41,131,147,737,9,1603,1859,11573,28397, + 1,3,3,9,21,9,59,27,169,875,711,1389,2899,7937,4173, + 1,1,5,9,13,29,71,39,51,337,1067,2661,1203,5967,19249, + 1,3,7,1,17,21,43,79,181,741,1901,3445,7171,2109,1589, + 1,1,3,9,23,37,105,51,227,775,1265,2987,2197,13903,28891, + 1,1,1,13,23,47,111,41,93,261,75,2155,4301,11517,16101, + 1,1,3,3,27,27,123,125,501,775,413,1065,7607,15065,26013, + 1,3,7,3,27,11,59,87,207,743,1765,2969,913,8101,11583, + 1,3,3,1,23,7,113,17,285,993,695,2399,5019,4779,28917, + 1,3,1,5,11,51,49,139,213,435,1475,2209,6695,12981,9851, + 1,3,5,7,1,63,31,151,173,767,1453,1497,6911,9597,25551, + 1,1,7,7,21,53,39,159,389,231,309,359,7701,14819,5175, + 1,1,1,1,11,47,83,29,247,89,369,2727,3103,14421,17369, + 1,3,1,5,25,25,111,245,239,755,113,1765,3583,917,403, + 1,3,3,3,5,59,85,151,463,591,743,3767,121,2927,11031, + 1,3,5,9,11,39,77,161,275,233,1991,2683,6545,2423,32113, + 1,3,5,11,5,57,13,229,329,757,1863,3959,4243,7265,15599, + 1,1,1,1,1,23,19,67,453,593,2011,1813,4695,8903,9623, + 1,3,3,7,1,29,103,255,493,647,1709,4065,4199,949,28829, + 1,1,7,9,3,55,53,33,5,223,423,3347,7647,7211,25157, + 1,3,5,13,3,43,79,255,471,573,1007,2119,6731,10047,23179, + 1,1,1,3,7,39,55,61,53,377,435,401,3307,12621,14299, + 1,3,3,7,21,31,67,17,243,425,747,2995,1389,2557,18415, + 1,3,1,3,3,39,75,11,447,249,1135,1011,1657,10767,19501, + 1,3,1,11,17,51,117,129,17,143,785,103,5049,14703,28479, + 1,3,7,5,13,17,75,255,75,661,1175,477,1811,1479,15783, + 1,3,7,9,11,57,101,77,431,247,997,3657,5117,6815,3841, + 1,1,5,1,17,21,101,183,209,69,299,1585,6381,12983,10053, + 1,1,7,3,5,13,21,63,83,857,749,1251,5363,9629,16563, + 1,3,3,9,3,59,9,45,55,489,137,2423,2661,12111,4375, + 1,1,5,9,23,9,41,177,447,671,1631,3115,4215,14435,8743, + 1,3,7,11,19,23,15,221,413,783,1247,2343,4397,3145,32043, + 1,3,3,1,31,55,31,87,333,849,1777,343,5199,1507,11621, + 1,3,7,3,17,57,63,63,111,977,631,3019,2953,14273,29209, + 1,3,1,13,9,39,87,15,397,185,701,1487,3807,13727,19883, + 1,3,7,1,17,57,57,157,119,181,899,353,3603,15041,7421, + 1,1,7,3,29,13,29,191,105,373,961,1991,5531,6793,29497, + 1,3,3,11,7,61,65,39,215,187,191,1651,2481,3951,24965, + 1,1,7,5,25,11,105,23,257,771,1359,2837,7821,12223,28033, + 1,3,5,11,3,3,23,139,407,885,1679,2979,8149,14281,12487, + 1,3,7,3,21,45,13,85,249,1015,2023,1429,965,7091,31721, + 1,1,1,13,19,5,119,47,91,285,211,2607,4287,9197,455, + 1,3,1,1,9,59,25,137,121,287,577,3325,2365,8823,5033, + 1,3,3,13,25,63,99,43,15,855,245,3189,59,5181,21299, + 1,3,5,11,7,9,41,157,359,773,1347,2049,4589,13731,32133, + 1,1,7,11,31,37,83,105,183,375,79,1821,1989,15199,22207, + 1,1,5,3,23,37,127,9,467,651,993,69,6943,4093,20871, + 1,1,3,15,31,49,123,149,211,371,1825,3011,485,1251,17343, + 1,1,1,15,11,33,127,251,89,317,1869,219,2275,14201,27063, + 1,1,5,5,19,5,81,35,233,95,9,863,725,11095,16217, + 1,1,1,15,23,47,51,43,169,637,865,57,1509,1683,7587, + 1,3,1,3,7,7,117,187,273,303,717,3091,2083,3315,647, + 1,1,5,15,13,27,23,227,145,547,1783,987,6895,7135,11023, + 1,1,5,11,21,39,57,203,477,17,985,1729,4297,7483,13263, + 1,3,7,9,3,49,71,45,143,967,39,583,2123,5165,17437, + 1,1,1,9,21,51,71,163,441,709,397,445,6167,7753,11513, + 1,1,7,7,27,35,5,181,449,53,621,3401,5263,4557,9141, + 1,1,5,7,7,37,83,111,485,881,465,3371,5603,371,29393, + 1,3,1,15,7,47,41,245,377,823,309,3929,2159,13917,13365, + 1,3,7,7,7,29,25,141,19,611,79,2689,109,12321,8345, + 1,1,1,13,3,53,113,151,381,791,137,3185,3567,211,597, + 1,1,3,9,7,53,87,89,491,861,467,3763,2025,4187,9637, + 1,1,7,1,27,33,71,41,63,1011,741,1135,175,3739,21493, + 1,3,3,5,9,19,55,175,325,55,1193,1423,2049,9633,17515, + 1,1,3,1,27,55,69,103,401,707,825,399,6799,13199,6295, + 1,3,7,3,19,63,25,151,17,159,1673,615,6317,13261,26267, + 1,3,7,9,27,1,77,129,423,647,707,2579,3525,6723,31615, + 1,3,3,7,7,31,35,241,309,369,895,3683,4795,11319,451, + 1,3,5,7,17,7,117,141,267,713,569,1915,4369,7793,30853, + 1,3,7,1,29,61,81,73,413,13,1977,3229,5853,8451,15539, + 1,3,7,1,5,45,109,21,431,487,2019,2647,927,16015,10711, + 1,3,1,3,11,19,37,183,451,377,269,3993,3229,4899,26561, + 1,3,1,11,5,19,121,55,57,117,687,83,3047,1367,17595, + 1,3,1,7,17,31,41,219,239,963,199,2895,5599,7639,17201, + 1,3,3,5,27,53,71,183,509,771,1809,1539,2229,4893,17115, + 1,1,3,9,9,9,13,49,265,643,1929,859,497,9797,27771, + 1,3,7,11,19,39,115,139,207,903,963,1849,4403,6229,10021, + 1,3,7,13,3,57,99,223,503,423,1755,807,1885,213,18723, + 1,3,7,15,11,15,111,193,243,599,593,3385,5393,15073,17777, + 1,1,5,3,19,63,121,207,99,435,1961,2747,6405,3971,23481, + 1,3,5,13,9,29,79,131,415,49,229,1003,3263,12975,15987, + 1,1,3,7,1,41,127,155,29,73,963,659,2741,3465,2595, + 1,1,3,5,23,23,93,233,113,521,427,1557,6917,12953,22441, + 1,1,5,13,5,25,85,191,387,69,955,243,4473,9813,21711, + 1,3,3,7,1,53,95,65,231,995,539,2103,5513,14087,28655, + 1,3,5,3,17,13,19,227,197,91,1437,1121,3307,6903,3297, + 1,1,5,11,31,29,109,171,257,783,861,9,4895,1859,10909, + 1,1,7,13,5,47,61,5,363,351,1525,823,2883,12435,17629, + 1,1,5,11,9,3,69,159,371,477,1223,1973,2757,413,31223, + 1,1,3,5,23,45,43,195,423,829,1673,1563,6633,14775,21097, + 1,1,3,3,13,9,107,209,49,609,1047,3691,7483,4269,7557, + 1,1,3,15,3,43,73,161,53,813,325,3439,7009,8691,11711, + 1,1,3,3,23,45,99,61,407,15,1515,1557,953,8567,13729, + 1,1,5,9,31,35,117,57,227,923,1373,1811,3405,11979,10149, + 1,1,3,9,15,53,105,209,153,67,1477,667,3077,4911,3871, + 1,1,3,3,21,53,93,101,183,1023,3,3041,5815,9043,5801, + 1,3,3,5,17,49,127,161,321,869,1369,923,3235,711,30007, + 1,1,3,3,15,17,97,229,389,159,1075,2001,7905,15191,14693, + 1,1,5,11,5,5,121,173,95,173,1883,3915,1439,9981,24375, + 1,3,3,1,31,53,29,189,37,623,217,949,3959,7189,25427, + 1,3,5,9,21,45,101,23,355,729,797,2317,2931,7433,29175, + 1,3,7,1,1,63,63,155,237,865,1169,43,7335,6445,7979, + 1,3,7,7,11,51,37,199,503,991,319,3013,7885,12837,32419, + 1,3,7,7,27,31,101,243,37,811,1909,109,6455,7903,11821, + 1,1,3,13,23,21,89,99,243,605,1017,1871,1101,12825,8227, + 1,3,3,13,19,3,51,59,501,605,385,2189,3229,7981,31407, + 1,1,1,1,25,11,127,215,295,237,1245,3657,7803,3897,655, + 1,1,7,7,5,9,63,129,143,417,795,3409,2847,5887,3093, + 1,3,3,13,7,57,67,57,5,847,1185,3349,4841,11457,8857, + 1,1,3,3,9,53,51,43,85,437,13,2543,3651,15493,767, + 1,1,7,9,1,49,97,115,133,1011,1399,2653,7765,13999,12097, + 1,1,5,1,3,27,123,107,389,401,1759,1333,1371,5277,14865, + 1,1,5,1,13,23,3,123,137,821,399,1671,3095,3121,31387, + 1,1,5,3,7,35,57,237,509,753,1783,2815,6495,13283,7091, + 1,1,7,11,5,37,77,109,7,969,1087,3705,1695,14223,28959, + 1,3,1,11,25,5,25,163,179,185,671,1031,4537,11601,9323, + 1,1,3,7,17,25,49,221,183,619,1953,343,4523,14883,6833, + 1,3,7,5,27,19,59,153,11,807,513,3019,6875,5307,8405, + 1,1,1,13,25,41,21,109,321,135,497,1235,5177,5167,18609, + 1,1,7,5,21,53,25,197,411,503,1009,1921,4305,2633,31415, + 1,3,5,1,25,45,27,227,271,903,639,3805,657,8683,29585, + 1,1,5,3,9,49,37,35,351,491,851,2983,31,5619,6919, + 1,1,5,3,11,49,33,153,393,1017,1561,2795,4435,12589,22349, + 1,1,1,15,17,29,49,245,217,359,1133,393,3317,415,16407, + 1,1,3,5,3,9,95,63,319,319,1009,19,6453,16279,6975, + 1,1,5,9,3,25,67,95,369,237,285,2409,671,5143,121, + 1,1,3,1,9,49,35,87,317,185,445,2263,7923,10183,26615, + 1,3,3,11,9,59,29,135,129,477,353,3571,1057,16329,23523, + 1,1,1,15,13,11,19,5,133,827,1799,1893,1939,1101,12147, + 1,1,3,3,15,49,33,185,511,1013,41,3499,6235,7643,16725, + 1,1,5,11,27,45,89,157,63,137,2047,1275,4995,625,6111, + 1,3,7,11,3,1,121,1,341,33,1895,3033,3929,10257,21037, + 1,3,3,11,7,11,117,5,115,287,335,3415,5397,15065,19121, + 1,3,3,13,21,25,15,125,277,125,801,3761,2623,11333,16867, + 1,3,5,11,19,33,21,71,499,747,1515,185,1759,14623,895, + 1,3,7,1,29,35,9,203,277,299,1509,2017,2897,14175,1643, + 1,3,5,11,7,47,111,197,459,941,1619,2119,2191,11049,6811, + 1,1,5,9,7,43,103,115,87,269,1235,77,5887,1611,29041, + 1,1,5,7,1,61,83,225,179,81,1145,2403,1485,8967,20607, + 1,3,3,1,25,47,27,157,359,803,1683,1995,6445,13113,17899, + 1,3,1,7,21,37,43,119,245,49,1581,2275,3311,4087,29765, + 1,1,3,13,5,33,49,191,455,105,665,3855,3207,2671,32203, + 1,3,1,1,25,63,19,217,17,353,947,1951,4097,9041,11921, + 1,3,1,7,21,31,113,97,347,993,1799,3831,3711,6193,1235, + 1,1,1,5,3,63,11,203,425,445,1361,531,1265,1755,11685, + 1,3,1,7,13,29,23,85,57,467,1835,133,7961,4175,2445, + 1,1,1,15,23,27,37,5,123,913,1293,1633,3113,5413,26407, + 1,1,5,13,27,1,121,151,303,931,375,3679,1863,12301,30907, + 1,3,1,9,31,9,49,203,177,937,1503,933,5867,12533,13621, + 1,3,3,15,1,41,23,191,191,931,837,3553,2611,4735,18105, + 1,1,5,7,27,49,51,111,435,195,1229,711,7145,14571,31707, + 1,1,7,7,3,41,59,203,291,903,1727,2757,1463,6287,31535, + 1,1,7,13,23,5,75,3,207,525,411,2133,2231,477,7155, + 1,3,5,7,13,19,111,225,489,83,1177,4077,4617,14413,7133, + 1,3,1,7,9,59,3,113,379,803,1289,3347,4127,6669,14867, + 1,3,7,3,31,37,87,79,399,749,995,1611,3137,12543,31955, + 1,1,5,7,21,59,49,45,511,639,1033,2169,3265,15001,10745, + 1,1,5,1,25,19,23,203,11,883,1031,4087,5059,11321,21675, + 1,3,7,5,11,27,33,205,163,289,501,3505,1515,1895,15889, + 1,3,1,1,23,7,39,239,29,119,1499,2071,6495,12107,5339, + 1,3,1,1,23,29,55,181,327,905,427,1033,427,3687,5367, + 1,3,3,7,21,27,115,127,393,855,1291,2121,381,9995,29757, + 1,3,5,1,25,13,15,183,269,1005,1531,3451,3975,9479,23695, + 1,3,7,7,19,31,111,97,33,179,1343,2069,977,5043,9129, + 1,3,1,5,17,57,99,129,379,829,837,1845,3613,7351,19291, + 1,3,3,5,31,23,119,229,135,389,9,705,6697,15441,5303, + 1,1,1,11,25,31,105,95,5,931,789,375,7543,9957,28627, + 1,1,7,15,21,17,19,103,389,545,1725,2867,4251,3829,6907, + 1,3,7,7,15,37,97,65,337,409,1649,2869,7929,8905,21989, + 1,3,5,3,11,15,69,29,353,207,233,411,2047,10303,31655, + 1,3,3,7,27,43,125,107,69,981,215,1955,3589,597,12703, + 1,1,7,9,25,13,109,73,227,663,1115,285,471,3359,15787, + 1,3,7,5,1,45,7,79,441,149,701,1457,6595,14829,20865, + 1,3,7,15,15,47,83,239,295,23,1085,813,1209,3573,2855, + 1,1,3,15,13,7,59,67,255,537,1841,3857,6821,15175,13997, + 1,3,1,1,9,57,59,21,21,41,1693,2805,7953,1389,14105, + 1,3,5,15,19,49,107,117,99,607,145,53,1863,9383,12029, + 1,3,3,13,1,39,5,141,503,265,281,1785,2673,6597,6333, + 1,1,5,3,3,19,3,181,169,269,955,2399,3157,11053,8563, + 1,3,3,13,11,1,95,43,179,507,443,209,3239,14239,21829, + 1,1,7,9,3,17,99,179,445,479,1897,1507,5753,4757,2135, + 1,3,3,1,9,51,29,13,295,291,927,85,5707,7447,32319, + 1,1,1,3,13,11,21,157,213,327,1071,591,2639,15405,6617, + 1,3,5,1,7,25,55,47,495,681,727,2707,2955,705,7489, + 1,1,3,9,17,3,73,67,465,367,1473,3195,7825,5299,1817, + 1,1,1,1,19,31,77,253,71,599,1601,871,2243,6699,13013, + 1,1,7,9,21,1,71,115,5,65,767,925,7901,10761,19431, + 1,3,1,7,23,31,31,15,105,391,585,2995,2635,10607,24951, + 1,3,3,1,19,25,71,211,41,197,787,225,6781,813,10117, + 1,3,3,3,17,29,3,153,231,643,1151,447,3699,9625,26677, + 1,1,5,9,1,25,71,21,395,297,557,3841,233,1877,4569, + 1,1,3,13,1,45,115,61,5,937,173,2109,2927,9599,9155, + 1,1,3,3,15,21,61,121,253,285,1083,3545,5537,6773,2629, + 1,3,3,15,13,63,33,77,49,849,1795,2771,5481,9833,603, + 1,1,7,5,1,39,113,237,225,1005,1687,2297,3213,2605,14669, + 1,1,3,1,11,1,39,23,67,441,1235,2545,3139,15901,29243, + 1,3,1,3,15,49,39,57,311,345,525,223,4923,6311,25275, + 1,1,5,7,9,13,69,11,349,423,1773,1055,1001,9359,17025, + 1,1,1,13,15,63,89,207,335,591,1223,2701,55,12471,13127, + 1,1,3,5,15,19,83,67,407,113,1961,779,5803,12417,21751, + 1,3,3,1,21,53,81,95,405,427,1047,2443,4153,5843,22511, + 1,1,7,7,7,25,115,155,453,537,741,2379,2343,16035,19587, + 1,3,3,11,27,21,111,121,503,437,803,3399,5303,10163,18199, + 1,1,5,13,19,27,7,81,259,545,965,743,4533,8813,21253, + 1,1,5,5,1,59,37,11,105,343,75,1319,6317,9593,1699, + 1,3,1,9,13,9,115,131,387,1023,253,693,5191,12777,10565, + 1,3,1,15,7,35,111,195,287,305,533,1901,3363,10085,30791, + 1,1,3,9,27,51,21,77,413,925,717,791,4147,585,5649, + 1,3,3,5,25,59,79,249,185,567,71,1997,7373,2327,18637, + 1,3,3,11,15,21,97,99,391,57,1973,29,7451,2529,25737, + 1,3,7,5,7,59,93,5,287,469,1639,3637,5465,14431,32265, + 1,1,3,11,3,1,71,75,427,299,811,3697,3529,5433,26957, + 1,3,1,9,19,59,37,255,165,1005,19,2851,4309,455,9485, + 1,1,1,5,1,55,15,233,133,47,1831,713,2601,1017,3201, + 1,1,5,5,21,55,127,69,377,41,25,2295,7595,4733,11615, + 1,1,5,3,23,5,7,181,161,775,1095,2271,6637,14489,6873, + 1,3,5,9,9,15,5,133,357,21,127,2685,6299,4363,17573, + 1,3,3,9,13,39,51,223,201,401,1839,2461,7633,6039,10445, + 1,1,5,1,9,21,19,249,227,359,255,2895,4117,2073,27687, + 1,1,5,15,5,61,113,161,95,3,877,2775,293,6655,4023, + 1,3,7,1,7,55,73,39,295,403,985,2315,1667,13525,1453, + 1,1,5,1,27,1,85,195,11,713,1841,3895,3131,2193,17607, + 1,3,5,13,25,1,119,97,239,167,1393,1753,6989,12155,12509, + 1,1,7,15,31,21,41,255,425,445,165,2097,5627,4971,13207, + 1,1,1,15,13,33,81,105,453,197,13,1547,7381,8709,15103, + 1,1,3,11,11,33,107,123,483,367,121,995,1911,8205,22577, + 1,1,1,9,9,43,71,49,273,431,1705,3313,4259,16291,14345, + 1,1,1,7,3,1,43,213,97,547,1559,1149,2791,3751,887, + 1,1,3,15,25,47,49,251,425,35,295,3767,6305,9633,5045, + 1,3,3,1,5,55,91,245,27,981,331,555,6553,11017,15289, + 1,1,3,7,1,23,23,155,223,565,1005,3211,3847,7479,3643, + 1,1,5,1,17,7,47,95,35,779,1685,2099,7505,15425,18089, + 1,3,3,7,3,63,83,151,211,147,611,1171,1681,7687,13423, + 1,3,3,1,3,27,107,117,497,537,195,3075,2753,1665,19399, + 1,1,1,7,23,5,103,209,117,845,1243,1283,4253,9723,20937, + 1,3,1,1,5,49,7,13,419,125,287,1599,8161,1275,24661, + 1,3,3,3,13,63,23,183,39,979,1301,2349,905,15805,30151, + 1,1,3,9,17,11,97,189,189,511,1779,2077,6891,11623,23949, + 1,1,7,11,13,45,15,37,11,853,915,1569,6103,10633,3137, + 1,3,3,5,15,61,91,255,131,821,1755,1501,2663,1747,941, + 1,1,3,7,19,19,65,95,499,239,2023,3185,4649,3861,3767, + 1,3,5,15,15,63,55,93,127,303,171,1763,4991,9479,9917, + 1,3,7,5,31,53,111,35,433,163,1903,3991,3585,643,21941, + 1,3,1,9,27,39,67,89,487,349,587,1723,4311,11321,25785, + 1,3,5,7,1,63,23,237,507,689,1341,441,1721,843,20335, + 1,1,3,3,31,63,83,103,25,799,1379,1817,3809,12285,16673, + 1,1,5,3,25,29,99,193,21,549,33,3109,4135,10071,32355, + 1,3,1,7,13,27,83,189,121,167,379,1503,7955,13189,313, + 1,3,5,15,25,19,83,87,257,237,709,1169,1561,7117,4785, + 1,1,1,7,9,55,21,5,439,367,403,2311,6243,8349,13127, + 1,3,7,3,5,35,51,67,453,767,29,3293,6665,11459,2799, + 1,3,3,3,5,19,59,7,367,683,783,1317,7119,6129,19525, + 1,1,5,5,5,19,61,67,381,291,875,2179,2481,9325,11253, + 1,3,5,5,7,47,107,9,141,667,1989,821,3909,1733,10187, + 1,1,7,7,31,61,1,71,477,689,1539,3617,8105,6535,3293, + 1,1,5,5,23,9,103,197,241,249,297,3607,6217,1673,30103, + 1,3,1,5,23,15,115,105,365,51,825,2687,359,16325,15083, + 1,1,3,11,29,45,65,251,169,189,1243,2345,1345,14471,25631, + 1,1,5,9,7,63,81,167,309,539,1169,3949,4193,12047,1491, + 1,3,1,9,29,33,89,167,67,73,1885,477,5745,13365,6819, + 1,3,7,9,9,49,95,13,157,997,1725,935,7543,6349,18277, + 1,1,5,5,11,59,97,17,303,469,93,2761,7395,9021,24299, + 1,1,7,3,27,63,71,99,407,139,711,2589,4715,5405,3277, + 1,3,7,3,11,15,49,57,271,493,1165,2839,8191,2609,14759, + 1,1,1,7,21,15,71,245,413,473,1321,1165,1027,6983,12867, + 1,1,5,3,15,21,19,197,401,627,2047,2761,5807,5751,28025, + 1,1,3,3,5,57,19,209,341,165,489,455,231,14385,12457, + 1,3,3,11,13,63,79,129,17,315,1881,1069,177,12013,29567, + 1,1,3,7,31,29,51,235,475,375,617,437,6379,8505,23079, + 1,1,3,7,27,3,3,137,203,959,363,371,2899,13491,22979, + 1,3,3,3,9,1,57,7,363,537,713,2417,509,7747,22135, + 1,3,3,3,13,21,79,121,487,921,113,281,2853,14855,19747, + 1,1,1,11,3,53,89,123,307,585,567,1925,505,15935,20419, + 1,1,3,3,15,45,77,197,499,683,1405,3573,981,14135,19763, + 1,1,1,11,27,31,61,191,29,601,373,2011,6193,3599,4387, + 1,3,5,9,7,13,1,193,469,603,1315,3329,3761,8355,10425, + 1,1,3,9,29,61,103,17,117,251,2029,2963,3763,16117,6627, + 1,3,1,3,7,51,91,145,497,657,871,3707,5905,10449,14901, + 1,1,3,1,3,53,23,149,461,333,1809,1315,1815,8223,13297, + 1,1,1,7,15,31,3,47,443,829,1305,893,4191,9681,32661, + 1,3,1,3,27,43,51,221,295,825,649,2953,6203,8237,20253, + 1,3,1,3,9,35,41,195,249,225,387,3789,1499,2559,28413, + 1,1,5,15,19,29,13,115,333,787,787,723,2987,6227,10865, + 1,3,5,13,5,59,5,251,79,387,11,3167,6619,13317,18979, + 1,1,7,11,31,51,43,1,189,519,1945,2129,4365,14059,3139, + 1,1,7,5,31,9,43,19,151,533,1061,3849,6871,6941,14935, + 1,3,7,5,19,57,7,129,25,353,17,1739,6513,399,28835, + 1,3,5,15,25,15,37,125,39,239,271,65,2189,10449,11815, + 1,3,7,15,19,57,47,245,509,945,385,3987,3585,14711,9655, + 1,1,3,13,21,31,13,81,9,489,1321,63,1363,2219,19541, + 1,1,5,7,3,57,25,147,23,553,889,307,6429,15807,12861, + 1,1,3,15,29,21,99,237,151,881,675,3625,1159,11759,21347, + 1,1,7,1,9,13,111,239,235,609,1569,3271,2837,13807,7301, + 1,3,1,15,7,59,27,81,129,9,647,3595,1877,1067,1859, + 1,3,7,1,3,25,119,57,145,441,1045,789,215,1265,9369, + 1,3,7,3,17,25,87,211,441,229,223,2795,7241,7007,20575, + 1,1,3,1,13,1,55,227,389,141,1097,2487,7603,4161,5025, + 1,1,3,5,15,29,29,145,233,209,891,89,8097,2897,26685, + 1,1,3,1,29,53,19,95,161,359,435,3313,4955,7965,21015, + 1,3,5,9,19,3,109,77,29,937,1663,125,2453,1069,20639, + 1,3,7,13,5,23,43,231,347,591,1963,2491,4045,16029,8149, + 1,1,5,1,13,3,75,211,419,929,901,3453,8121,799,8897, + 1,1,7,15,11,11,123,111,309,415,1071,975,2009,12945,19617, + 1,1,1,7,31,35,81,255,89,643,451,513,497,11751,24215, + 1,3,5,5,25,17,5,165,139,929,1927,1353,7427,9719,17087, + 1,3,5,1,21,55,79,85,333,847,1305,851,5057,8361,18269, + 1,3,7,15,27,17,55,125,395,223,271,781,1639,10569,11143, + 1,1,7,9,7,33,127,85,209,339,483,241,2523,14951,6855, + 1,1,3,9,5,19,9,183,435,343,1105,3139,7617,1311,267, + 1,1,5,1,15,53,11,63,113,241,855,3123,4777,3495,23345, + 1,3,1,5,19,29,119,205,167,683,289,1629,4977,8981,6867, + 1,3,1,1,31,63,95,159,267,231,863,3385,5315,7267,13757, + 1,3,5,11,19,21,53,41,125,179,533,1279,3759,7073,13905, + 1,3,5,9,17,7,27,67,97,809,1423,2743,2859,16121,329, + 1,3,1,15,1,41,59,155,509,51,1827,3739,3879,13369,30821, + 1,3,3,7,21,31,7,13,347,919,1225,497,5051,3769,20211, + 1,3,7,13,31,9,127,195,123,387,3,3593,6623,9827,29319, + 1,1,3,9,7,27,95,211,287,189,1683,1999,7641,14983,4699, + 1,1,5,3,7,21,29,189,101,423,885,3275,6569,11023,22265, + 1,3,5,3,9,33,79,75,327,975,287,3025,2157,7301,24447, + 1,3,3,15,31,27,63,1,71,119,1151,517,6131,11055,179, + 1,3,7,11,23,15,101,247,349,735,673,997,6451,229,32103, + 1,3,5,15,7,1,51,135,207,741,1831,1235,4747,11915,22009, + 1,3,1,13,9,31,19,221,465,681,627,2595,5617,14201,30355, + 1,1,3,1,13,49,55,155,11,885,1275,3591,2217,6659,30885, + 1,1,7,11,27,57,93,95,243,63,1405,2049,7689,15943,18503, + 1,1,7,7,5,11,47,189,467,631,1665,2717,4285,2087,1435, + 1,1,3,11,7,27,127,3,231,757,435,2545,3537,9127,19915, + 1,1,5,13,5,29,85,127,339,875,497,1573,6553,11983,18029, + 1,3,1,1,21,3,15,91,231,683,1529,2651,4147,13437,23861, + 1,3,1,7,27,17,19,179,243,223,1037,1501,5935,2259,25185, + 1,1,3,15,11,19,127,27,483,219,583,2555,531,3451,17875, + 1,1,1,13,31,39,89,149,363,741,1355,4067,3171,6783,1799, + 1,1,3,11,25,51,45,235,379,123,1701,725,1991,7471,9833, + 1,1,5,13,15,47,13,201,263,57,375,2963,7475,15929,13775, + 1,1,3,1,29,29,11,161,345,253,97,255,7267,2379,3933, + 1,3,1,15,3,47,11,69,347,747,795,2401,3367,2383,6125, + 1,1,7,3,1,49,101,47,71,761,1503,2619,191,8895,873, + 1,3,3,5,25,41,93,85,427,109,1675,2409,4317,9233,30283, + 1,1,3,9,11,3,67,159,425,751,887,1415,403,15977,10739, + 1,1,5,13,9,1,9,103,481,601,931,1957,5763,7095,27141, + 1,1,3,15,29,13,43,33,297,269,1041,1411,3461,12043,10045, + 1,3,5,3,3,3,5,7,185,753,133,1561,5595,13777,25795, + 1,3,5,5,1,19,29,145,163,149,619,2603,7757,10035,10189, + 1,3,7,15,27,15,111,173,135,117,157,2601,7919,12111,22795, + 1,3,1,1,29,27,65,31,101,715,289,3643,2335,6789,23397, + 1,3,1,3,11,45,71,109,321,423,1695,169,3075,12423,11391, + 1,1,3,9,13,51,35,121,203,279,433,2725,7951,2105,27333, + 1,1,1,15,23,31,25,105,501,441,1511,3133,2811,10595,21779, + 1,1,5,13,7,1,97,193,121,993,1347,1903,1883,6583,24535, + 1,1,7,9,7,29,17,41,101,447,1289,387,1891,2723,26091, + 1,1,3,3,3,53,81,81,177,165,195,3413,8177,3817,8453, + 1,3,7,15,15,31,23,31,337,439,1773,63,5351,5491,1767, + 1,3,1,11,5,15,23,75,437,553,429,2705,3625,13851,19865, + 1,3,3,9,13,15,33,235,215,415,1737,1409,2101,14623,14717, + 1,3,7,7,13,51,101,217,175,813,1639,4009,1625,4991,17525, + 1,1,5,13,23,33,29,175,39,673,557,3239,5129,11049,27227, + 1,3,7,13,1,37,33,139,493,891,1883,2525,5741,15795,5875, + 1,3,1,15,15,27,127,111,147,363,725,3077,4341,9131,24635, + 1,1,7,3,17,25,59,135,177,635,73,3455,3083,6009,13033, + 1,1,1,5,15,53,93,161,215,459,1087,179,2235,8885,15309, + 1,1,7,13,7,17,75,173,449,855,103,2739,3421,11811,18805, + 1,1,7,9,5,11,53,75,247,249,1201,953,2455,4589,6027, + 1,1,5,13,27,51,119,39,137,11,1435,3773,3889,6081,11829, + 1,1,5,5,5,35,1,197,501,185,1039,1563,6421,14373,25655, + 1,1,3,13,31,55,115,183,483,655,1351,3203,725,3299,22579, + 1,3,5,11,31,31,83,59,395,21,1881,2821,2251,11781,26265, + 1,3,7,13,21,19,103,21,403,443,1951,55,985,15983,15087, + 1,1,5,15,29,11,51,53,255,183,1475,1491,259,387,10303, + 1,3,5,7,21,37,45,39,479,637,1325,3753,3319,7403,31759, + 1,1,3,5,7,43,89,53,269,187,995,141,119,8139,29699, + 1,1,1,5,1,53,3,23,379,223,1889,4035,1437,12425,9051, + 1,3,1,13,3,31,61,43,249,449,901,1921,3495,8599,5263, + 1,1,3,5,3,25,35,133,25,597,915,3663,5147,11831,24269, + 1,1,1,9,21,27,93,93,217,299,1881,3647,4825,7989,24121, + 1,3,1,15,5,15,49,129,315,631,2037,1567,4043,15589,30905, + 1,3,3,7,25,5,123,51,47,471,1563,3947,7975,3681,9611, + 1,3,7,15,1,17,73,245,465,95,95,1159,1319,4675,8841, + 1,1,3,15,5,51,35,71,423,651,753,173,2131,15799,29601, + 1,1,1,1,3,53,83,187,445,827,1549,979,5363,1701,2149, + 1,1,7,9,3,15,65,161,37,233,771,3749,727,6857,17175, + 1,1,7,7,27,29,107,247,249,353,773,3677,7273,5419,29397, + 1,3,3,7,31,49,87,159,145,497,1715,2115,5035,6431,7245, + 1,3,3,5,7,31,51,117,101,617,557,2551,6589,13295,31975, + 1,1,3,3,15,27,125,163,169,893,1771,25,5787,10267,10297, + 1,1,1,5,9,47,85,65,289,783,1105,4035,4111,2589,24575, + 1,3,3,13,23,33,7,49,301,531,1713,2755,5543,8153,24099, + 1,1,5,9,7,39,101,67,417,923,757,1537,5553,12233,20881, + 1,1,5,1,19,7,25,123,125,183,573,3317,6867,871,17631, + 1,1,3,15,19,13,117,41,129,715,1525,2257,2179,10807,23271, + 1,3,1,5,25,53,19,169,289,569,1135,1967,7001,15883,15113, + 1,3,7,15,7,37,127,147,415,313,1541,1889,3763,16199,12681, + 1,1,3,9,1,35,95,137,237,951,899,3177,6073,10655,31687, + 1,1,5,5,29,57,45,253,297,529,1553,467,8035,15675,21691, + 1,3,7,15,25,41,59,81,87,985,1001,2369,661,7551,11829, + 1,1,7,9,27,21,7,233,309,67,701,2737,4261,2467,15691, + 1,3,7,1,19,55,47,155,333,101,517,1991,4619,10435,27241, + 1,1,7,3,23,35,7,125,157,537,933,3281,4975,8969,27581, + 1,1,3,7,19,53,81,103,461,435,777,335,5261,12249,9695, + 1,3,1,7,19,9,75,245,355,37,1855,1339,3107,7251,16543, + 1,1,1,3,5,35,39,223,113,423,1423,713,6113,349,24147, + 1,3,1,1,15,31,11,75,499,345,1253,2629,2551,7483,25395, + 1,1,3,11,25,25,3,211,185,45,1865,1805,3303,11091,529, + 1,3,1,1,9,21,7,165,107,641,1083,2805,2099,5855,18477, + 1,3,5,3,9,21,77,103,505,277,335,797,3869,2957,1979, + 1,3,5,15,31,23,77,247,303,891,1261,3233,3495,13111,13185, + 1,3,5,11,11,35,49,229,149,931,881,775,2949,3141,29157, + 1,1,3,5,19,57,23,95,347,221,195,3561,1481,2063,3979, + 1,3,5,3,13,1,23,173,431,29,421,3235,2751,4447,28283, + 1,1,5,13,23,3,1,9,327,855,1251,2997,6129,4223,11555, + 1,3,7,13,29,21,37,229,217,353,1239,3955,491,12183,14777, + 1,1,5,5,1,33,103,187,183,939,1873,2633,6143,15405,17353, + 1,1,1,9,21,27,71,129,499,279,1181,4053,2485,1961,30603, + 1,1,3,15,21,37,45,201,221,187,727,1241,6171,1383,22277, + 1,3,7,5,21,17,67,177,323,601,633,865,6131,10329,8689, + 1,3,5,9,15,45,71,43,359,651,103,403,3249,11769,6567, + 1,3,3,13,3,23,101,145,367,999,1489,3673,2959,10855,16029, + 1,3,7,3,13,43,123,87,55,1015,141,2917,6567,16025,25555, + 1,3,1,3,17,7,21,161,41,889,1315,1897,639,15451,3049, + 1,3,5,15,27,33,55,17,81,431,325,909,3547,10121,17815, + 1,1,3,1,15,37,43,137,203,191,1129,1585,435,3177,769, + 1,3,7,11,21,23,125,41,17,951,465,3691,3465,13247,13779, + 1,3,3,1,31,23,43,101,405,739,1061,2955,5643,16137,8763, + 1,1,5,1,19,33,99,109,203,65,395,2775,1373,2557,5875, + 1,3,3,3,27,51,79,63,331,365,1071,1661,4549,8561,1719, + 1,3,3,9,3,17,53,161,141,489,1325,1709,1381,5093,171, + 1,1,7,15,9,3,95,237,197,949,7,1837,729,10111,6637, + 1,1,3,3,19,31,57,173,483,861,1001,1919,3389,11777,20693, + 1,3,1,9,27,13,113,177,75,925,949,119,4759,7775,23033, + 1,1,7,15,23,15,65,61,137,653,1843,323,379,15157,29885, + 1,3,3,7,29,3,11,205,347,745,1477,3929,5749,4735,29435, + 1,3,5,9,1,11,111,15,7,69,45,3607,1099,9203,21301, + 1,3,3,3,23,3,83,173,73,485,681,1867,3839,11823,13339, + 1,1,3,11,31,43,107,127,465,389,1595,427,1571,5885,29569, + 1,1,7,9,27,25,117,27,287,391,279,3247,35,12973,5483, + 1,3,7,11,19,55,45,127,245,945,305,3907,2455,3163,31, + 1,1,7,11,15,17,65,15,37,207,1447,3027,2281,6557,16717, + 1,1,1,13,5,27,33,213,29,603,1171,3235,2255,2017,30999, + 1,3,1,5,11,1,73,233,69,125,397,297,3337,6191,31055, + 1,1,1,15,1,1,65,145,201,917,1891,2999,4069,10413,15819, + 1,3,5,13,15,51,115,167,311,375,1069,2595,3337,753,11903, + 1,1,3,1,1,23,69,125,147,915,1945,411,979,13863,30443, + 1,3,1,11,5,1,93,23,135,93,1689,23,3519,4491,24673, + 1,1,7,3,11,59,93,153,487,475,1191,1455,5963,8259,18811, + 1,1,3,1,13,15,55,71,433,33,491,1835,5695,10509,347, + 1,1,1,15,19,1,23,47,235,101,1057,901,5477,7079,30885, + 1,1,5,13,11,43,119,77,441,121,783,827,1757,12751,31593, + 1,3,7,11,19,17,37,225,329,231,515,1541,7371,6355,10905, + 1,1,5,13,7,11,35,215,345,577,147,2803,3291,4631,5329, + 1,1,3,9,21,55,113,251,25,221,1445,3385,1589,4109,29897, + 1,1,5,7,9,45,5,33,331,285,1101,3131,2713,5653,3823, + 1,3,7,7,5,39,43,167,481,629,777,1827,4653,403,4781, + 1,3,3,7,31,33,31,159,313,673,1425,663,5819,1297,26627, + 1,3,3,1,19,61,117,93,373,491,1031,757,4185,771,7265, + 1,1,7,9,3,45,65,223,437,41,1139,2733,5963,2709,25429, + 1,3,5,11,21,27,31,127,255,761,1865,1319,6583,9235,10717, + 1,1,1,5,21,1,63,43,413,557,567,2893,8017,2307,29525, + 1,1,7,3,31,1,15,235,215,395,1971,469,5275,431,5349, + 1,1,1,13,25,59,71,245,389,279,1293,89,6551,10285,14495, + 1,1,5,5,9,63,17,229,425,939,877,3689,7229,6707,30771, + 1,3,7,7,11,29,43,41,25,237,1585,3735,2617,7541,26243, + 1,1,7,9,21,5,69,231,361,39,1695,3043,2973,5487,12857, + 1,1,5,3,17,63,91,217,407,133,1373,4021,1737,10043,4561, + 1,3,7,9,31,13,101,231,175,457,89,2167,2725,8505,375, + 1,1,3,15,31,11,27,211,347,291,1881,3091,3307,5117,13341, + 1,3,5,5,13,25,5,197,237,135,635,1175,5085,14737,10807, + 1,3,3,9,7,63,107,127,147,477,1813,2619,8089,2651,26549, + 1,1,5,11,15,45,27,133,45,621,707,2679,5929,19,9599, + 1,3,7,9,21,37,41,255,69,1009,1999,367,6177,10017,3549, + 1,1,1,15,19,55,73,189,423,983,1811,2551,4765,12077,18205, + 1,1,5,7,17,13,25,225,463,471,631,1811,5797,3235,32253, + 1,3,7,1,29,7,123,187,331,735,1757,1115,2077,15725,2183, + 1,3,7,9,17,61,111,93,21,1003,1905,3719,2111,11845,6427, + 1,3,7,7,17,21,51,59,115,723,2039,2833,5969,5737,18407, + 1,3,3,13,9,47,95,233,13,281,1049,619,405,16205,20097, + 1,3,7,13,9,41,11,171,453,713,587,1669,2489,10277,18599, + 1,3,3,13,21,41,123,173,511,399,859,1515,5773,12535,26289, + 1,1,7,15,11,3,113,111,73,7,1191,2573,7713,465,27615, + 1,1,7,15,5,5,39,11,489,13,1041,1639,7879,11899,6899, + 1,1,5,9,27,31,15,237,401,795,1675,2361,7333,12507,14627, + 1,3,1,7,21,53,31,81,189,683,1283,419,7585,9207,15053, + 1,3,5,11,21,1,49,251,403,489,1235,429,4855,4081,17575, + 1,3,1,15,29,33,77,53,105,731,749,2677,3967,7967,18723, + 1,3,3,11,9,47,11,95,137,923,599,1585,1969,9625,19171, + 1,1,1,5,7,7,85,49,339,883,261,2125,3831,9797,16395, + 1,3,3,3,5,9,33,99,75,889,101,2099,6635,11511,21573, + 1,1,5,11,1,11,79,49,7,131,471,1235,3287,14777,12053, + 1,1,5,15,9,9,83,15,21,899,1785,2349,3471,6723,1405, + 1,3,5,11,1,7,121,223,509,859,1037,491,5529,481,17029, + 1,1,7,5,17,35,91,171,113,65,423,2371,5105,12827,31087, + 1,1,3,3,21,47,55,11,159,51,263,2113,661,9147,28929, + 1,1,1,9,19,7,43,223,207,787,543,2141,4247,7369,29031, + 1,1,7,11,11,51,121,9,211,905,687,889,1827,13395,3507, + 1,3,1,7,15,23,5,139,469,569,33,3477,5391,13665,17011, + 1,1,1,15,29,29,29,201,63,1019,97,1671,9,4617,19833, + 1,1,5,15,25,5,67,225,189,919,1471,1451,5017,16189,31555, + 1,3,5,5,15,51,89,221,149,863,43,2381,1767,8037,5319, + 1,3,3,1,15,17,5,77,69,27,1883,63,5987,1497,3723, + 1,3,7,11,7,5,113,229,123,709,1531,641,6655,14923,22947, + 1,3,1,13,21,15,45,175,81,499,1113,587,7573,11689,15651, + 1,3,1,1,29,43,101,37,131,757,465,743,2737,8063,23967, + 1,1,7,13,9,21,39,177,51,691,2047,1519,6137,5271,8703, + 1,1,3,3,5,55,63,21,3,317,461,527,2673,16211,6721, + 1,3,5,5,5,47,7,241,387,589,323,203,7241,14761,13287, + 1,3,5,3,23,63,55,61,231,1023,1315,1181,243,7389,25639, + 1,1,7,13,31,43,41,81,127,887,1513,4055,1361,2443,6963, + 1,1,1,5,7,43,43,33,323,911,1373,3053,6503,513,6457, + 1,1,7,11,25,61,21,149,205,349,1433,1587,149,7275,5465, + 1,3,5,5,11,9,31,217,119,511,209,3325,2023,2877,463, + 1,3,5,15,21,47,89,41,347,849,1375,3311,807,11443,27643, + 1,1,5,7,29,43,123,191,321,373,447,2145,1221,2071,12689, + 1,3,5,15,1,21,43,141,461,779,1109,2915,909,8585,19859, + 1,3,3,11,5,17,57,13,393,661,1761,2455,43,8593,20505, + 1,3,5,1,31,47,65,249,77,513,851,2381,3447,693,7729, + 1,3,5,15,31,19,83,47,369,697,1815,819,7573,9245,8013, + 1,3,5,5,11,25,27,151,107,339,299,3869,3393,5661,2947, + 1,1,3,1,1,59,85,57,175,465,239,3115,7157,7035,11463, + 1,1,7,5,31,41,53,149,121,743,189,159,5289,2945,1179, + 1,3,3,15,23,51,83,25,159,163,61,713,4529,5253,1603, + 1,3,5,11,7,29,15,177,507,695,1305,1863,7525,3063,27433, + 1,1,3,11,5,41,115,227,409,951,591,4003,7717,4369,15637, + 1,1,7,11,23,55,71,135,51,411,2003,2375,6823,1711,4443, + 1,3,1,3,31,47,31,233,243,3,313,1649,6955,13679,32327, + 1,1,3,11,29,9,1,79,247,677,685,3107,5987,9675,29523, + 1,1,1,7,25,31,39,241,483,839,1143,437,2317,2437,173, + 1,1,5,1,17,19,83,57,39,479,715,1911,1091,10937,22145, + 1,1,7,1,27,45,35,55,477,719,217,3349,7717,6853,9699, + 1,3,1,11,9,39,25,223,303,713,151,2611,4629,5855,31729, + 1,1,1,11,13,35,53,39,167,779,1673,1221,6281,15113,32027, + 1,1,5,9,19,63,89,113,199,107,1015,835,2879,9499,25597, + 1,1,7,3,19,37,15,23,449,641,1811,3407,6775,6283,31157, + 1,1,3,1,19,15,31,99,511,897,1693,2093,955,15897,26693, + 1,1,5,1,5,15,47,19,441,541,1621,3877,6407,15991,1931, + 1,3,5,9,21,61,15,77,265,351,879,3835,6555,2349,23235, + 1,1,5,11,25,37,29,181,341,641,1213,1319,6359,6231,32573, + 1,1,1,7,1,37,87,123,33,913,111,2613,4895,12595,26633, + 1,3,5,3,27,11,45,89,183,241,1355,783,3343,239,8643, + 1,3,7,7,9,35,67,187,233,577,1445,3063,6039,16233,1453, + 1,1,3,13,27,11,23,15,95,63,1931,911,8149,6833,3051, + 1,3,3,5,29,49,125,117,47,143,423,3215,3605,3677,17155, + 1,3,1,1,31,1,123,195,83,893,1947,339,2927,7183,15443, + 1,1,7,13,31,15,91,207,39,275,439,2617,3093,11041,24997, + 1,1,5,3,3,41,13,67,361,497,25,3807,3551,9681,21043, + 1,3,3,3,11,27,103,59,427,327,1705,29,8127,1641,20847, + 1,3,7,5,3,37,81,137,225,101,187,3067,2491,12687,16227, + 1,3,5,15,15,33,69,223,225,771,1917,2293,2889,12083,23971, + 1,1,3,5,11,9,121,81,203,425,1189,2011,3041,3247,739, + 1,3,1,1,13,9,39,169,437,571,1481,3355,3895,8975,31031, + 1,3,1,11,1,43,35,35,293,11,657,1415,5021,14463,17945, + 1,1,5,5,13,47,91,15,159,23,971,3575,757,13477,31757, + 1,1,7,1,5,63,69,27,71,129,123,3767,89,7865,1189, + 1,3,3,5,23,1,83,3,487,491,217,2583,3889,15009,9227, + 1,3,5,15,25,1,73,107,245,191,1449,571,1403,6953,17457, + 1,3,3,3,27,19,25,105,207,857,1161,3657,2107,7955,517, + 1,3,3,9,21,29,5,103,219,35,3,1635,4815,15797,29839, + 1,1,7,7,3,63,75,77,13,57,603,2333,7761,14397,10875, + 1,3,7,13,3,11,5,255,1,947,1695,1927,7447,7407,20797, + 1,1,5,1,1,21,105,73,429,973,1801,3943,6161,1309,3359, + 1,1,3,15,27,9,9,129,117,545,9,1983,6351,10925,27337, + 1,3,3,5,5,5,13,155,503,875,1243,2259,3445,11953,6517, + 1,1,7,3,29,21,121,147,413,423,1887,2429,2765,16335,3071, + 1,1,7,9,5,53,41,137,463,583,1627,1731,6675,3703,8177, + 1,3,5,11,31,29,67,159,425,25,1457,139,5019,701,7357, + 1,3,1,5,25,15,123,123,245,859,249,2175,2137,5765,4873, + 1,1,3,5,23,1,111,111,111,469,1473,1777,3579,13503,2569, + 1,1,7,3,17,23,51,23,499,135,713,3317,807,9589,11349, + 1,1,1,15,9,51,75,159,359,773,1521,2913,5901,3047,14649, + 1,1,3,1,13,61,117,195,49,267,57,1769,3621,9415,29443, + 1,3,7,11,3,25,33,31,315,191,359,3399,2481,13831,20205, + 1,3,3,5,31,43,35,125,291,51,1469,3857,1707,2641,32137, + 1,3,5,1,25,11,113,137,211,159,1667,939,6439,5337,32059, + 1,3,3,11,31,61,99,49,383,343,395,51,6931,16039,5901, + 1,1,3,5,9,63,63,49,405,915,1505,2141,6749,7799,17313, + 1,3,7,11,15,11,49,161,155,869,121,301,6561,4279,15233, + 1,1,5,13,19,13,103,59,503,293,701,2527,5327,13927,5025, + 1,1,7,1,1,37,55,155,485,399,855,2677,5927,9657,2795, + 1,1,1,5,19,15,121,69,385,75,1567,2649,5601,12981,15903, + 1,1,1,11,19,21,45,59,505,737,15,1383,1177,8375,15557, + 1,1,7,13,29,19,123,127,469,773,733,3289,8087,5803,27897, + 1,3,3,11,19,55,101,67,485,939,607,1521,6161,12235,16499, + 1,3,5,13,29,31,31,9,453,151,1055,3873,405,12877,29829, + 1,3,5,1,17,1,17,131,107,1003,1749,1849,6207,2153,21275, + 1,3,7,15,7,25,51,143,51,517,1841,1771,5389,4633,11123, + 1,3,7,11,23,7,89,95,403,361,835,585,2783,8091,5141, + 1,3,1,9,1,53,115,11,493,587,305,3605,1711,4169,20013, + 1,3,7,3,17,59,55,251,49,759,1227,3685,7765,1445,20385, + 1,1,5,7,29,55,19,157,129,927,893,1235,1955,8153,2865, + 1,3,1,15,21,35,81,53,175,939,1635,3597,747,14011,12867, + 1,3,7,1,27,61,91,73,405,677,603,2715,7099,941,24523, + 1,3,5,9,13,45,35,167,57,483,735,2777,7847,6257,13109, + 1,3,5,7,1,3,97,13,159,533,1791,1061,981,10795,26165, + 1,1,5,13,27,5,125,25,251,221,1909,197,6987,11537,15287, + 1,3,5,5,27,15,1,131,375,923,81,3153,6071,2515,23729, + 1,3,3,9,9,23,71,13,465,261,937,1549,5993,11325,15065, + 1,3,1,3,7,63,17,129,435,23,215,2251,1561,9703,26483, + 1,1,3,1,5,53,77,109,9,605,371,2081,6023,7145,15837, + 1,3,7,11,27,39,115,47,259,337,1857,3465,1549,7747,8525, + 1,3,7,7,29,29,75,77,29,661,899,3137,2661,15271,28093, + 1,1,1,3,3,3,11,219,39,757,1465,249,7445,7013,15187, + 1,3,7,15,15,1,39,245,427,1003,1493,1913,6435,14787,13481, + 1,1,7,3,3,37,5,97,343,833,1379,1551,5403,1843,5877, + 1,3,1,1,3,17,17,163,339,691,1707,1845,5941,4259,24531, + 1,1,1,1,27,21,85,221,71,949,1753,391,6349,15901,20811, + 1,1,1,5,31,19,45,99,469,783,1747,3807,5889,9485,13715, + 1,3,1,9,23,21,39,25,421,713,461,2857,5023,5341,6409, + 1,3,7,5,25,19,59,147,387,857,375,3103,1261,13697,25675, + 1,3,5,5,31,21,49,251,463,441,473,3487,3915,11151,17721, + 1,1,3,9,15,47,81,219,143,141,81,1705,5847,3437,30521, + 1,1,7,3,25,19,97,41,77,105,1337,695,7589,8587,7509, + 1,1,5,13,3,11,61,19,139,667,963,1567,5715,7079,15967, + 1,1,5,5,5,29,67,57,477,173,1163,727,823,15635,17705, + 1,3,7,11,13,39,57,193,73,617,535,1623,4581,4451,2589, + 1,1,5,5,9,27,75,127,325,413,1669,1749,8045,16199,12237, + 1,1,3,1,17,23,27,189,319,953,347,909,4401,12791,25077, + 1,1,3,3,17,51,37,79,301,607,885,1169,3275,3327,20013, + 1,3,5,3,21,9,99,213,387,889,575,3591,5377,2981,23989, + 1,3,3,13,11,7,23,255,279,853,453,2377,8123,15393,9669, + 1,3,1,7,11,9,109,35,405,449,1967,2943,3485,5031,14273, + 1,3,3,1,25,27,43,115,435,675,1937,1477,4831,9417,7017, + 1,1,7,13,19,45,83,241,487,215,1453,209,4061,1765,15623, + 1,1,7,7,21,31,95,9,287,1005,1933,3405,6913,7733,18975, + 1,1,1,11,13,11,25,39,283,57,255,2809,5767,6127,6705, + 1,3,1,11,1,51,73,181,261,215,385,2777,5169,12431,23563, + 1,3,3,9,9,39,123,197,501,679,109,3369,4817,8855,7997, + 1,1,5,1,29,61,15,183,453,999,1211,3217,8035,5153,19975, + 1,3,7,11,11,21,51,45,379,793,289,309,1229,7159,581, + 1,1,3,9,17,11,75,67,289,191,1083,2949,6063,6611,21595, + 1,3,7,3,27,45,59,193,485,277,27,1219,2389,15875,6273, + 1,1,5,3,31,29,65,197,115,163,9,783,5573,2833,12603, + 1,1,3,7,5,53,115,181,175,749,1335,1151,2131,12467,15811, + 1,1,1,9,27,39,11,1,443,677,777,1857,7459,3177,3875, + 1,1,7,7,17,3,23,161,105,603,1991,3845,465,11467,2077, + 1,1,3,13,5,23,39,35,399,795,265,207,1823,15069,31839, + 1,1,1,1,29,61,89,193,41,99,315,1021,6109,12507,19973, + 1,1,5,3,13,57,119,251,215,695,1521,4081,2481,657,855, + 1,1,7,3,25,5,3,133,111,385,773,1027,4327,3031,3537, + 1,3,7,5,5,27,43,117,479,83,1421,2791,6551,6231,10353, + 1,1,1,13,3,29,35,71,85,821,1671,3057,797,13683,7025, + 1,3,7,1,1,47,117,233,141,993,1381,2551,1031,11765,18429, + 1,3,1,3,13,3,77,29,35,807,1109,695,5605,5477,449, + 1,1,1,15,21,37,117,105,273,311,1287,1415,1221,1847,19487, + 1,3,1,11,21,61,107,225,335,501,1995,2399,5475,12613,18877, + 1,3,3,1,31,41,27,205,103,837,639,2007,2759,12471,1457, + 1,1,7,13,29,39,71,245,105,235,1277,1515,6129,15947,26653, + 1,1,7,5,7,13,87,251,315,1017,587,2917,5911,2919,29715, + 1,1,1,3,7,19,81,243,177,917,2023,2365,7465,4901,29841, + 1,3,5,15,1,31,15,147,285,1003,1757,47,6925,1197,19633, + 1,1,5,7,27,25,47,209,85,403,1399,2331,3663,595,13407, + 1,3,5,9,7,25,7,139,389,817,1153,1421,5735,9577,10269, + 1,1,1,9,5,61,49,117,389,541,433,1405,2575,223,7265, + 1,1,5,7,15,1,81,207,435,843,835,3797,7637,5333,31115, + 1,3,7,11,13,3,47,249,301,715,2015,3049,8155,10989,26051, + 1,1,7,7,3,33,119,113,381,575,367,41,3317,11727,4351, + 1,3,3,13,9,3,51,37,173,137,533,1827,631,10047,6267, + 1,3,3,11,17,39,61,245,13,139,1281,1319,1233,13629,32269, + 1,1,1,7,15,17,91,109,163,609,11,3251,7653,14035,31755, + 1,3,3,15,13,21,55,231,385,133,1833,2637,6935,14303,26745, + 1,1,1,7,17,41,125,141,89,823,1411,3637,6211,13323,6111, + 1,1,1,11,1,21,9,43,97,685,1223,1491,121,1793,2397, + 1,3,5,5,17,17,5,223,129,865,1839,1137,6391,4377,9233, + 1,3,7,15,21,55,5,77,341,637,1853,1435,1195,9283,21257, + 1,3,5,1,9,49,43,211,127,655,1397,1235,5279,2351,24229, + 1,3,5,3,25,29,13,229,25,675,837,2753,2125,9863,11293, + 1,3,5,7,23,43,127,1,163,237,337,3019,7747,16227,2881, + 1,3,5,5,25,9,43,171,421,521,1885,337,7873,6347,13181, + 1,3,5,5,7,47,107,173,163,191,625,3389,2833,7945,24787, + 1,1,7,3,27,57,27,209,253,815,301,1633,3945,5051,28851, + 1,3,7,9,9,51,103,213,437,189,1857,1331,5551,10641,27405, + 1,1,5,5,15,1,25,105,117,347,161,3369,3589,12903,23559, + 1,1,1,5,3,61,93,51,81,281,1383,745,4137,2005,3635, + 1,3,7,5,13,57,111,211,303,477,359,4019,6779,5129,22035, + 1,1,1,7,17,29,113,113,201,531,749,739,2879,3315,18733, + 1,3,7,13,21,55,21,183,359,75,377,2211,4281,14317,28307, + 1,3,7,1,21,1,49,213,317,75,113,1741,7963,12785,11571, + 1,3,7,9,11,31,29,101,261,141,715,2727,8187,2075,32433, + 1,3,7,3,23,9,17,143,385,211,593,241,6567,10777,6677, + 1,1,3,15,3,17,117,99,91,793,989,2421,5643,16103,9759, + 1,3,7,11,23,43,107,35,421,431,743,853,7939,12169,4199, + 1,1,1,11,21,53,17,203,123,395,59,929,255,7585,10945, + 1,3,3,15,17,57,57,133,67,71,1685,903,4079,15423,26495, + 1,1,1,15,3,47,95,39,405,407,1557,3001,6225,15187,5663, + 1,3,5,5,13,47,33,61,375,1023,1981,2773,2375,11321,17731, + 1,3,5,9,17,59,117,95,493,149,1269,2865,369,2109,24601, + 1,3,5,13,17,63,67,247,95,721,67,305,6179,15399,32559, + 1,1,5,1,3,21,41,15,453,475,2017,3193,5903,897,4237, + 1,1,5,3,15,41,1,141,441,575,155,3791,7711,11231,24611, + 1,3,7,1,17,53,27,169,31,437,963,1793,7777,1917,29311, + 1,3,3,13,9,27,77,87,329,885,749,1713,6013,6921,629, + 1,3,5,13,3,7,53,27,353,267,925,2141,439,15175,30851, + 1,3,3,13,17,57,35,101,265,901,1825,2159,6149,5967,24023, + 1,1,5,11,13,51,99,111,193,415,1541,2929,5045,3147,12587, + 1,3,7,11,15,9,33,17,511,815,299,1077,6171,10451,15039, + 1,1,1,15,25,63,51,137,449,951,1051,1101,4725,2463,7355, + 1,1,1,7,27,63,29,179,317,521,1459,827,6599,13459,15439, + 1,3,3,15,17,31,37,191,229,245,181,941,5761,1849,31599, + 1,1,1,9,27,45,67,239,481,615,1667,3751,8141,10013,2125, + 1,1,1,1,13,51,117,135,73,151,1291,2541,1411,3767,26949, + 1,3,1,9,7,11,21,187,243,857,1951,865,7273,2041,8155, + 1,1,3,3,19,33,89,115,455,137,707,1867,4221,2433,9119, + 1,1,3,11,5,3,121,1,71,951,603,3873,723,3285,19289, + 1,3,7,15,21,1,117,17,455,519,731,3003,5741,9557,29163, + 1,1,3,13,25,5,43,147,209,895,255,1231,241,487,15593, + 1,1,3,13,7,1,89,187,217,927,2029,3521,2777,8103,22819, + 1,1,7,11,7,33,3,73,5,489,227,2259,7031,6425,26135, + 1,3,3,7,31,19,97,201,455,819,945,2771,8083,8711,2835, + 1,1,1,5,15,45,43,157,245,967,877,2289,4499,9891,18827, + 1,3,1,7,21,59,123,63,231,485,1781,1211,4597,5269,1607, + 1,1,1,13,23,39,105,55,249,991,1625,3089,3825,4275,29139, + 1,3,3,1,29,29,55,169,13,895,1355,1101,6063,12935,23215, + 1,1,5,5,31,49,99,137,209,1017,1179,3931,637,14131,19285, + 1,1,1,1,3,11,119,11,215,337,243,3883,3807,7335,11901, + 1,3,7,3,7,27,71,225,219,367,1213,2739,1185,10175,21313, + 1,3,7,13,7,49,23,223,61,1011,797,1335,6711,5961,5605, + 1,3,3,11,19,37,1,149,39,661,929,2125,2299,5181,28083, + 1,3,3,13,13,9,67,21,463,279,529,523,6705,11011,31695, + 1,3,1,5,13,1,123,3,291,625,1949,2713,5917,10343,13627, + 1,1,3,9,27,41,3,207,103,265,811,549,6109,313,8889, + 1,3,3,13,23,43,99,33,279,463,955,793,4113,10615,16957, + 1,1,5,7,11,49,79,45,17,937,359,1037,1099,3003,31561, + 1,1,1,7,3,45,111,35,109,983,53,4057,7349,3599,2209, + 1,3,7,11,9,43,27,9,85,529,1497,347,759,12449,11373, + 1,1,3,9,17,1,49,31,367,813,1385,2025,773,4679,4543, + 1,1,5,15,15,9,43,97,239,995,1037,841,4167,12113,23765, + 1,3,5,9,29,53,123,49,221,113,1157,73,6087,1363,11029, + 1,3,1,13,3,15,69,199,279,919,5,161,4817,15031,121, + 1,3,1,9,3,31,117,77,393,241,645,3181,1067,15879,2037, + 1,3,3,15,3,63,57,33,117,789,941,1301,5865,12693,3523, + 1,1,5,13,3,61,51,151,175,305,95,1557,6567,7841,13903, + 1,3,3,5,15,25,127,79,245,767,645,3933,1357,12579,4067, + 1,3,5,11,21,31,13,251,127,231,1795,2627,1191,3363,23543, + 1,1,3,5,7,49,121,57,131,481,1879,525,5225,337,1957, + 1,1,5,13,9,55,27,37,211,125,119,3373,251,12357,13975, + 1,3,3,15,1,51,91,119,233,993,203,1635,1167,6327,29119, + 1,1,7,1,13,5,23,253,121,989,1105,3321,3221,6073,21185, + 1,1,3,15,13,49,121,247,247,133,485,1067,7875,411,7647, + 1,3,7,13,31,37,127,241,145,133,53,267,2029,3703,16123, + 1,3,1,15,15,9,15,89,35,367,401,61,1953,7873,17861, + 1,1,1,1,1,41,71,249,213,779,1385,1767,999,15151,16647, + 1,3,7,13,31,23,123,235,343,949,309,3777,3587,853,19779, + 1,1,3,13,29,35,5,37,63,757,303,1579,3443,243,11873, + 1,3,1,9,19,49,81,53,11,901,1857,147,3103,14019,21, + 1,3,7,13,3,39,99,99,45,91,1567,551,3129,4809,29057, + 1,3,7,3,3,27,17,231,377,381,1479,2525,2595,2799,25737, + 1,3,5,15,15,25,103,215,301,59,1417,981,7579,12731,22329, + 1,1,1,13,5,31,61,31,349,925,1301,685,435,11567,10715, + 1,1,7,9,19,57,109,1,37,377,1015,2273,6741,3191,15949, + 1,3,3,13,3,23,103,127,11,59,1847,1175,425,3423,20643, + 1,3,3,7,3,11,105,141,55,217,1427,477,667,9403,11905, + 1,3,3,5,3,27,11,187,495,907,1925,445,6639,8159,15225, + 1,3,1,5,27,31,77,213,73,343,1123,3609,2431,15329,32165, + 1,1,7,5,1,11,105,139,485,1007,709,3509,5231,11717,31433, + 1,1,3,15,23,49,95,169,399,1019,19,2013,5311,7951,22609, + 1,3,1,7,13,3,29,203,209,701,1791,2615,5351,4237,12565, + 1,3,1,15,27,11,91,31,205,205,1683,901,5129,6049,11865, + 1,1,7,7,27,59,21,3,209,79,769,4013,2041,2645,11561, + 1,3,7,11,5,45,39,243,185,871,795,1845,8043,6285,20991, + 1,1,5,7,13,7,15,165,349,179,789,1269,3787,5429,26567, + 1,3,3,13,31,23,75,41,177,735,1889,4039,3519,15003,965, + 1,3,1,7,15,57,15,139,27,469,1003,691,7893,9643,30983, + 1,3,1,13,23,27,3,237,233,875,99,883,6167,5463,6245, + 1,1,5,13,25,57,79,51,147,619,1147,279,6583,1939,477, + 1,3,5,5,31,61,125,163,213,699,583,3865,615,9707,11651, + 1,1,5,1,5,21,93,239,31,641,777,27,5247,8993,21053, + 1,3,7,9,1,13,61,57,503,453,83,3271,2845,1121,18639, + 1,1,7,5,29,53,13,219,379,441,821,3179,4877,2535,7557, + 1,1,7,13,9,53,17,183,265,393,587,2753,6453,7135,24737, + 1,1,1,13,11,23,73,109,393,1013,559,755,7291,6631,26509, + 1,3,1,5,5,15,107,103,355,307,1559,837,5413,5285,17489, + 1,1,5,7,17,21,21,23,109,709,1947,3585,3629,4669,949, + 1,3,7,1,9,33,85,147,467,259,1913,199,7399,9551,22387, + 1,3,5,11,15,53,23,41,249,515,1161,2467,1299,7449,2613, + 1,1,5,5,5,29,91,139,487,545,321,3035,4545,6747,21673, + 1,1,3,13,23,49,95,103,25,119,469,2515,2551,841,25089, + 1,1,5,7,11,31,31,197,245,715,257,4043,8099,11531,5617, + 1,1,3,3,19,7,9,179,103,995,191,179,3843,5215,27639, + 1,3,1,7,23,59,25,65,399,211,1453,3511,7203,16015,32197, + 1,3,3,5,9,35,109,67,197,449,643,519,5751,15551,11331, + 1,3,5,3,1,17,53,201,265,351,467,911,1117,7183,20371, + 1,1,7,7,27,17,93,81,227,619,1191,735,815,12615,2719, + 1,3,1,15,19,3,83,75,343,297,1019,3469,4383,13299,29755, + 1,1,5,3,13,55,119,169,85,595,299,2469,5625,2877,16117, + 1,1,3,5,15,17,61,161,47,393,143,867,5517,9495,12795, + 1,3,5,1,27,31,113,125,251,687,969,1473,2245,6355,13655, + 1,1,1,5,5,37,29,133,443,899,277,2353,7223,4459,19159, + 1,1,3,9,19,27,53,145,195,167,2045,447,1803,1895,8431, + 1,1,3,9,5,27,91,147,233,451,475,27,4629,16181,16437, + 1,3,5,3,29,17,53,167,433,689,1131,2985,1553,11697,6993, + 1,3,3,13,21,43,69,229,399,525,179,237,7017,5703,17653, + 1,1,3,15,13,39,75,163,229,875,197,477,3667,15501,15801, + 1,1,7,15,15,51,81,187,487,673,865,1915,1009,5935,8097, + 1,3,5,5,7,3,63,77,495,815,391,2321,1007,15661,30715, + 1,1,7,3,17,25,83,173,173,911,1373,2957,4549,15977,17695, + 1,1,7,13,13,23,77,147,497,1003,1687,1795,1393,1881,8479, + 1,3,7,11,27,43,97,25,61,457,203,2573,5943,15021,4003, + 1,3,3,13,9,37,37,25,219,889,1535,2791,4531,13679,12663, + 1,1,3,1,17,7,51,123,89,887,1467,1645,3767,6383,30837, + 1,3,3,1,21,47,5,151,83,257,569,2711,637,12569,16893, + 1,3,7,1,31,37,73,3,115,919,1817,2483,4811,15245,4375, + 1,1,1,5,1,39,39,231,9,733,455,3383,4777,7235,12631, + 1,1,7,9,13,25,55,25,73,59,1699,929,755,1279,5583, + 1,3,5,3,9,49,79,55,479,179,1159,4079,3503,11603,12361, + 1,1,5,9,21,45,31,163,377,817,219,147,2581,12769,30783, + 1,3,1,7,15,27,39,189,493,259,1663,1213,961,11089,16079, + 1,1,5,9,5,41,13,153,313,337,1027,1267,4249,13071,27043, + 1,3,7,3,13,11,23,255,51,527,317,3217,5037,12723,17411, + 1,1,5,1,25,57,83,97,233,513,1283,2675,4111,4111,32141, + 1,3,3,15,25,33,103,81,155,189,139,1179,2691,15119,13959, + 1,3,3,1,25,55,67,19,19,9,437,579,4273,10733,7125, + 1,1,1,7,23,41,47,5,435,749,595,199,3941,7199,4795, + 1,3,1,15,5,49,35,9,199,703,1769,3269,5689,13063,22771, + 1,1,5,5,21,55,125,55,63,149,1167,3577,1051,3921,20545, + 1,3,7,13,29,53,107,193,163,339,1335,1573,5809,5681,29487, + 1,1,1,9,17,9,91,177,211,453,1807,1881,6051,225,6021, + 1,1,1,13,15,1,29,43,181,105,1945,2313,6429,2901,6221, + 1,3,5,11,29,55,115,115,187,1013,697,1885,121,12387,32443, + 1,1,1,7,19,51,21,107,55,125,1655,2281,3293,15749,27521, + 1,1,7,9,19,9,81,93,139,401,193,73,5159,9323,6019, + 1,1,7,9,15,51,115,69,247,599,1163,2251,1211,8827,15581, + 1,1,7,9,5,39,75,185,321,911,849,843,6791,10407,10513, + 1,1,5,5,15,9,21,47,459,681,2001,1545,5939,7073,29043, + 1,3,1,11,13,25,53,97,487,797,567,3757,5597,6313,18531, + 1,1,3,3,29,55,11,219,325,591,2015,383,2595,11855,22501, + 1,1,1,5,15,57,33,125,323,749,1843,4019,2075,6673,6957, + 1,1,5,7,19,7,47,239,51,107,1081,467,5493,7617,10355, + 1,3,1,1,11,3,67,199,175,421,935,309,4449,6363,9183, + 1,1,1,7,9,33,3,219,481,513,417,1267,2863,765,18431, + 1,3,1,1,19,1,89,109,415,105,487,3241,7465,9233,16307, + 1,1,3,13,9,43,25,231,383,789,1855,691,3465,2387,11715, + 1,3,3,3,13,39,63,107,33,265,437,117,3179,5543,28179, + 1,3,3,13,21,5,31,111,321,425,253,3501,3209,15429,18383, + 1,3,5,9,1,27,117,187,433,459,1999,1069,4857,8591,26343, + 1,1,7,3,15,43,11,193,391,341,1203,1259,7265,1783,13161, + 1,1,7,1,5,15,45,143,193,985,1105,3483,2421,9687,22347, + 1,3,7,13,21,17,79,231,487,663,1101,1025,5779,14681,29181, + 1,1,3,9,15,19,55,219,27,963,1513,1017,3907,12279,32655, + 1,3,7,3,31,27,17,1,51,861,529,1225,6395,15787,5231, + 1,3,3,11,27,7,101,143,21,191,1437,2393,4097,14319,6977, + 1,3,3,3,25,35,105,141,433,269,1469,2939,5387,7373,7863, + 1,3,7,5,5,21,23,11,217,357,1847,101,1161,5297,14879, + 1,3,1,3,25,23,81,217,505,161,1667,1343,1751,2463,26431, + 1,1,3,1,17,51,125,205,385,351,731,2911,2749,2689,27031, + 1,1,5,5,5,17,31,171,477,671,167,1797,8047,10123,4325, + 1,1,7,1,11,23,123,161,99,1007,765,1965,5395,16193,17751, + 1,3,1,9,13,11,111,217,31,753,377,2267,7893,7195,24999, + 1,3,1,9,21,53,127,121,151,395,1447,1411,5179,12043,27607, + 1,1,5,3,11,37,97,139,113,835,229,3741,827,5527,5779, + 1,1,7,7,27,55,11,55,429,269,1179,233,1053,10225,16703, + 1,1,1,3,15,9,67,119,95,753,511,2507,3953,6403,27635, + 1,3,3,7,27,57,25,27,249,515,193,4043,2017,751,10949, + 1,3,1,9,31,57,67,21,177,573,1835,2015,6201,2383,31087, + 1,1,5,1,19,3,89,243,69,387,1905,3465,2775,7713,30081, + 1,1,3,3,9,59,15,89,85,605,881,263,2551,797,16541, + 1,3,7,11,25,41,59,139,405,571,1147,2963,4175,12901,6309, + 1,3,1,5,29,29,11,243,183,281,807,1,7079,10079,13865, + 1,3,7,5,5,1,89,55,423,157,675,1849,241,6467,15459, + 1,1,7,11,15,63,89,109,501,549,317,3043,1151,3895,19851, + 1,3,1,15,7,23,97,97,225,737,1117,3325,209,14169,10813, + 1,3,7,13,13,39,91,153,395,879,1041,3753,5577,1985,25247, + 1,1,1,3,17,15,113,143,101,901,1119,1819,3577,3441,31511, + 1,3,1,11,15,27,21,37,287,121,451,1353,2173,299,18791, + 1,3,3,5,23,1,49,145,315,769,99,1385,5961,9121,1465, + 1,3,3,13,21,39,39,233,271,113,615,2257,3765,5921,313, + 1,3,7,7,25,45,11,237,83,203,929,1819,2679,11583,30091, + 1,1,1,7,21,63,85,251,133,991,1515,2547,6051,7279,3569, + 1,3,7,15,11,19,87,17,313,283,1021,2743,4855,13741,17955, + 1,1,7,13,29,13,61,93,81,91,995,907,4847,2599,20041, + 1,1,3,11,13,45,103,33,243,109,2029,121,231,16179,13741, + 1,3,5,9,9,5,73,225,199,723,611,1909,2345,10257,9909, + 1,1,3,11,7,5,33,89,431,899,803,3173,6131,16097,20561, + 1,3,3,7,7,47,23,47,411,69,239,661,5591,10457,24245, + 1,1,5,15,25,35,87,23,115,939,1579,119,4001,13791,9729, + 1,3,5,11,25,45,29,195,369,237,735,155,123,4415,32255, + 1,3,3,9,13,53,15,77,313,75,529,925,5679,14585,19889, + 1,1,7,15,15,27,105,13,31,669,563,1809,4321,7797,4177, + 1,1,5,9,3,29,111,177,33,235,1951,1561,141,4803,16327, + 1,1,1,7,9,41,1,149,95,933,115,1619,771,8189,8781, + 1,1,5,3,13,41,33,159,355,159,1243,1439,6571,14397,31321, + 1,1,7,11,9,15,91,145,457,255,1449,611,1449,2521,28949, + 1,3,7,5,27,57,35,99,447,287,743,1163,4379,7361,3831, + 1,3,3,7,15,53,41,83,133,571,1739,531,2921,11527,21941, + 1,1,1,13,9,27,39,113,429,447,595,3171,5245,4095,14847, + 1,1,3,7,19,19,21,101,489,1011,265,3899,3225,11701,5193, + 1,3,7,3,15,25,103,213,441,215,1483,263,3561,7915,7969, + 1,3,3,3,11,47,97,29,489,867,1347,2155,4871,8001,18305, + 1,3,1,9,25,15,61,17,343,775,1765,3803,4577,8437,12605, + 1,1,5,3,11,39,69,23,23,65,1967,2429,1703,6671,14981, + 1,1,5,15,23,59,125,51,225,439,2019,2589,7781,13111,2911, + 1,1,1,3,1,31,37,245,203,305,821,367,5211,9791,21777, + 1,1,5,9,9,31,97,25,271,83,343,2461,1805,14383,10059, + 1,1,5,13,15,33,127,109,137,963,961,1647,7881,8133,22359, + 1,1,3,7,25,31,123,241,283,1,1781,23,971,6485,127, + 1,1,5,15,15,27,25,145,395,679,979,571,1585,14787,7465, + 1,1,5,7,13,11,7,131,511,597,379,1513,6267,16039,1503, + 1,1,1,13,15,49,73,217,353,577,1913,1127,961,11557,24993, + 1,3,3,9,7,3,105,141,377,687,1917,485,983,11149,23303, + 1,1,3,15,11,7,117,179,505,67,1817,913,5757,1981,1637, + 1,1,1,7,5,29,3,43,223,295,1895,3425,5355,5155,17197, + 1,1,7,9,21,59,121,245,73,233,1527,869,4145,7995,6473, + 1,1,5,13,17,21,89,179,495,669,453,2603,5969,6161,4743, + 1,1,7,11,25,21,103,131,391,249,1633,2603,2207,8987,15487, + 1,3,7,9,13,45,99,251,115,597,1505,2421,1231,10015,24295, + 1,1,5,5,31,49,17,67,463,813,1491,3309,7881,8109,7289, + 1,3,1,15,23,35,123,21,169,499,95,603,1829,7865,26313, + 1,1,7,1,9,29,45,65,95,97,673,3673,2969,2317,22209, + 1,1,3,7,29,33,121,17,331,487,1901,1951,5383,9375,4029, + 1,3,7,9,25,43,91,147,141,401,1647,2697,4645,7179,31857, + 1,3,5,11,9,31,127,105,39,883,1635,919,5069,2875,24519, + 1,1,5,9,1,63,73,135,95,503,385,3903,545,12635,27569, + 1,1,3,11,27,31,47,173,55,339,1255,1947,793,14133,13963, + 1,1,3,15,17,33,113,249,401,743,1307,3123,627,1253,13285, + 1,1,3,1,9,7,39,65,281,107,833,193,2987,12267,31335, + 1,1,7,3,15,21,99,211,39,179,587,1169,6455,8225,2049, + 1,3,5,13,5,13,123,1,223,273,731,2967,4793,4229,26031, + 1,1,1,1,3,17,7,23,225,757,743,1257,2047,12509,25467, + 1,1,7,15,29,3,15,113,227,675,1295,2777,2921,5485,2577, + 1,3,7,13,19,21,85,129,45,599,317,1513,4953,10383,25253, + 1,1,7,11,13,47,127,67,219,131,905,2005,851,15243,5777, + 1,1,5,3,23,57,57,189,153,37,955,2049,1295,15119,27213, + 1,3,7,11,13,61,3,241,269,789,1595,2369,4843,11347,21543, + 1,1,5,5,25,21,19,237,3,605,1343,3965,3511,7889,27759, + 1,3,1,15,21,15,123,5,345,945,283,1313,335,2085,19505, + 1,1,3,3,5,21,123,89,67,11,1247,1155,287,13455,5693, + 1,3,3,13,1,53,101,27,387,379,19,751,2445,11737,975, + 1,3,3,3,9,29,81,117,443,145,1619,1813,8125,5829,28617, + 1,1,5,15,27,15,83,83,61,715,1655,1631,3457,2727,2163, + 1,3,1,5,11,11,121,7,135,883,927,1817,6839,12361,24119, + 1,3,7,11,23,59,39,165,109,355,1303,381,5697,275,3771, + 1,3,5,11,11,5,81,157,55,435,613,127,4087,3791,21627, + 1,3,7,15,13,37,83,195,207,771,51,3685,6389,1229,11101, + 1,3,7,13,31,3,9,13,487,95,77,809,5809,12887,29933, + 1,1,3,7,25,9,13,29,353,659,1785,3825,3729,13109,12973, + 1,1,1,5,21,3,97,1,245,917,29,1429,8141,7569,32493, + 1,3,1,9,19,13,13,109,377,1007,1737,1939,1419,1145,5065, + 1,1,7,9,27,57,53,69,423,43,1629,1003,1473,10809,5659, + 1,1,1,9,1,45,11,231,351,155,663,2783,3491,5725,25207, + 1,1,1,3,15,25,77,89,231,813,657,2603,4885,1383,14499, + 1,3,5,5,9,21,101,181,449,491,737,803,659,11771,545, + 1,3,7,9,7,19,27,199,265,329,1031,1235,3191,10071,16281, + 1,1,7,11,27,55,3,127,503,1003,1041,1953,5835,4851,13485, + 1,1,7,15,5,45,97,61,221,497,1949,3163,4707,8441,1437, + 1,3,5,1,3,35,107,9,473,971,227,2225,3999,3095,18879, + 1,1,1,9,21,59,21,1,41,435,575,491,1839,1095,9727, + 1,3,5,9,13,29,123,251,465,701,1105,829,573,11503,11861, + 1,3,3,13,27,59,29,111,225,973,561,1481,835,9261,13831, + 1,1,1,7,17,3,97,211,333,315,571,3523,7305,6461,20139, + 1,3,7,11,31,21,105,247,113,863,1767,381,4623,8935,7911, + 1,1,5,7,29,45,17,155,69,17,655,1983,6385,6177,7961, + 1,3,3,15,31,15,63,81,309,115,393,3445,689,13963,18887, + 1,1,5,1,19,39,127,61,357,53,195,2745,7853,5753,3669, + 1,3,7,7,17,51,57,145,451,365,1517,909,4265,10737,9579, + 1,1,3,13,3,37,121,103,257,47,1685,2951,5753,15379,8899, + 1,1,5,7,31,63,61,197,97,773,133,1517,3093,14879,22941, + 1,1,5,1,3,9,27,53,97,663,1915,409,471,1391,24853, + 1,1,1,7,21,53,69,5,187,571,2023,997,323,12059,7071, + 1,3,3,1,7,59,55,157,101,123,1301,3709,4673,3897,28791, + 1,3,7,5,5,23,39,139,365,415,1481,3415,6323,11109,5719, + 1,3,5,3,5,11,23,143,243,229,183,3367,3187,8151,28351, + 1,3,7,9,5,37,29,23,437,827,985,2879,7611,1391,19087, + 1,3,3,5,7,9,5,143,217,757,1697,2459,453,8679,4513, + 1,3,5,5,11,33,3,143,293,921,185,2461,5547,12247,28591, + 1,3,7,5,3,53,43,179,235,417,1307,1367,3695,12809,1807, + 1,3,1,11,15,43,115,229,157,25,687,3347,271,5777,8557, + 1,3,7,5,27,37,55,135,209,47,1603,957,5785,11141,10407, + 1,1,1,15,17,17,103,29,489,493,119,1707,3463,1815,32055, + 1,3,7,11,17,13,115,145,77,515,1911,477,5997,8731,3143, + 1,3,1,13,31,41,73,91,231,1,455,2023,4691,3613,16329, + 1,1,5,15,15,39,17,117,131,657,1939,2245,2575,195,25209, + 1,3,7,15,5,51,69,141,499,931,1165,2119,1703,10867,28443, + 1,1,1,15,13,45,45,103,115,177,651,2545,1417,5349,3385, + 1,3,3,1,1,41,117,15,225,861,843,2775,4543,6275,14671, + 1,3,5,15,5,35,87,193,341,55,1131,945,6865,11271,18705, + 1,3,5,9,13,35,71,197,79,351,3,3939,1105,12455,28921, + 1,3,1,13,9,23,89,165,59,257,1369,161,6255,2997,19175, + 1,3,5,3,5,41,107,231,111,207,1865,2079,5891,2487,5863, + 1,3,7,15,3,3,105,235,263,991,367,1885,1769,7805,11909, + 1,3,3,5,15,59,67,247,77,367,1641,1959,1921,5939,17355, + 1,1,7,1,3,53,37,5,221,779,1353,1633,2769,6355,8505, + 1,1,7,13,11,13,73,227,115,523,355,3127,7545,8409,22335, + 1,1,5,11,21,15,91,115,427,683,461,2433,6313,4595,24401, + 1,3,7,5,29,21,57,215,423,717,1455,705,6835,4503,26077, + 1,1,1,15,3,33,25,227,381,477,1023,2751,2229,631,16903, + 1,3,1,11,9,17,59,73,53,671,251,1729,7593,12473,22533, + 1,3,3,1,3,35,37,173,459,143,135,3871,2689,8007,4379, + 1,3,5,9,23,19,43,45,493,509,1851,1615,5675,13793,6973, + 1,3,3,15,5,17,77,85,451,753,579,1057,4851,6017,4195, + 1,3,3,5,31,29,81,159,103,391,15,899,4623,5957,31961, + 1,1,1,7,17,57,81,17,177,633,49,2793,5229,5995,9491, + 1,1,7,15,17,19,65,57,189,239,1229,929,2681,12845,29311, + 1,3,1,11,13,47,61,203,383,875,943,139,4217,8279,1047, + 1,3,7,13,23,7,1,69,47,537,1325,3101,685,14057,19953, + 1,3,3,1,1,7,39,77,47,755,527,2985,5433,15095,27741, + 1,1,7,5,23,57,79,155,81,937,1071,3929,1655,3831,17351, + 1,3,7,1,3,41,13,235,207,487,1883,2247,1231,2751,15615, + 1,1,7,1,21,57,95,191,119,483,283,2221,5665,14819,26097, + 1,3,1,1,9,59,27,51,393,31,925,715,7705,14885,28767, + 1,1,3,3,3,61,109,131,113,249,1331,2521,2973,6375,20093, + 1,3,7,9,31,37,125,245,237,245,111,379,7495,15531,2325, + 1,3,7,13,21,21,57,21,449,969,417,2999,509,639,7797, + 1,3,7,7,7,29,11,175,55,705,891,863,3021,10071,10267, + 1,1,3,13,19,17,127,57,449,579,337,899,1235,11269,4245, + 1,1,1,11,29,61,35,75,249,683,287,45,3277,7521,2073, + 1,3,5,5,15,25,77,63,63,801,1387,1533,2185,10899,28381, + 1,3,1,1,21,49,3,249,419,575,87,3749,2523,16125,9483, + 1,1,1,11,21,43,85,211,449,439,1495,1841,4765,15253,1467, + 1,3,3,15,3,37,31,243,187,995,1103,2723,1523,15967,28649, + 1,1,5,11,9,11,17,87,335,125,1079,1657,1237,8059,29833, + 1,3,1,3,3,41,35,37,33,61,505,3203,5,101,8571, + 1,1,3,11,9,11,85,235,261,473,109,2127,5745,6389,7431, + 1,1,5,15,3,55,77,97,17,193,1267,3063,6531,9797,8639, + 1,1,5,5,25,41,79,83,485,697,149,1023,89,6115,15227, + 1,1,3,15,1,9,73,251,33,599,1017,353,4305,16033,29663, + 1,3,7,15,3,1,89,39,125,337,1445,3131,3685,9849,25829, + 1,3,7,3,19,1,63,179,349,135,185,2977,2527,15087,18133, + 1,1,3,3,23,7,91,221,325,723,345,81,8077,5501,8453, + 1,1,3,9,7,3,13,173,479,161,1989,3255,2069,6717,559, + 1,3,3,5,9,61,93,203,277,367,1141,981,4745,12625,21003, + 1,3,5,5,27,17,5,211,403,701,5,3091,4611,5615,23667, + 1,1,3,1,21,61,125,77,57,463,1499,791,2087,2805,18829, + 1,3,5,3,11,41,125,231,119,837,831,1331,7439,2381,3759, + 1,3,1,11,19,59,117,107,443,699,315,1491,2581,15871,17159, + 1,3,5,11,5,9,121,35,209,877,527,3493,4657,16093,17589, + 1,1,7,15,9,43,119,29,381,479,1443,3171,5053,9625,21161, + 1,1,3,5,15,21,31,223,83,399,1529,3605,6343,10469,10099, + 1,1,3,5,5,45,23,123,353,971,85,3069,3245,6569,13241, + 1,1,1,3,25,49,5,77,491,881,993,1195,7677,5709,10807, + 1,3,3,3,5,49,127,255,183,583,1599,987,7281,7149,28507, + 1,1,5,1,13,55,55,157,197,25,1971,3161,3903,8919,13563, + 1,3,7,9,3,37,79,193,25,103,843,2651,6341,2653,24337, + 1,1,7,3,25,49,99,139,45,211,2033,2331,7037,7177,1755, + 1,3,7,3,5,19,127,135,403,221,141,1065,3935,2745,25979, + 1,1,3,3,31,23,111,37,261,7,835,2379,7927,8181,23751, + 1,3,7,15,1,39,79,3,103,427,1917,809,5039,689,1939, + 1,1,1,15,29,37,39,243,149,353,763,3405,5751,9441,6653, + 1,3,3,11,1,57,125,151,445,423,841,2265,5017,15863,13057, + 1,3,5,13,11,49,61,159,211,917,561,1903,3985,11117,28969, + 1,3,5,13,29,5,35,51,91,291,9,3713,3341,4551,12085, + 1,3,3,1,1,39,111,141,319,179,1709,1605,5063,13279,10003, + 1,1,3,9,7,59,91,41,343,475,1669,2311,5141,12661,25847, + 1,3,5,9,9,11,49,221,1,243,791,229,503,373,19189, + 1,1,5,11,17,13,45,57,215,491,1601,2183,3713,429,22007, + 1,1,3,11,31,61,23,237,261,955,1085,1541,2601,909,7749, + 1,1,3,9,13,11,121,173,177,551,1757,2745,2265,4611,743, + 1,1,3,15,23,43,107,239,463,369,1857,1073,1247,1029,22557, + 1,1,3,11,23,35,89,93,41,941,1141,2339,1423,8007,28685, + 1,3,5,13,29,7,79,15,59,145,1237,2215,1257,12621,31101, + 1,1,3,7,13,55,57,229,205,1009,341,3901,5189,957,32587, + 1,3,7,11,1,1,41,7,365,407,1609,1423,6483,5171,32519, + 1,3,7,3,17,31,125,27,125,335,1395,2639,329,2549,14449, + 1,3,3,7,19,45,11,73,123,179,1685,3385,2379,3387,16793, + 1,3,7,5,31,25,47,153,121,453,935,3953,2081,12145,24979, + 1,1,7,13,25,11,65,3,277,237,1129,1801,4165,9065,18747, + 1,1,7,7,13,5,37,253,507,645,1355,3401,6707,6329,11237, + 1,1,3,15,17,49,3,233,407,451,69,3859,3171,12303,21031, + 1,1,3,3,9,53,119,117,401,903,1449,3639,4083,2095,22085, + 1,3,7,15,5,61,117,193,137,431,195,4019,3047,5049,14281, + 1,1,1,15,17,19,29,83,449,257,1105,1949,1749,3459,6343, + 1,1,1,15,23,39,61,219,109,365,863,1813,6673,15999,5101, + 1,1,5,5,13,11,37,151,365,719,1233,2425,1285,1721,1205, + 1,3,3,3,7,53,109,153,45,425,1741,1229,4405,8071,25155, + 1,3,1,1,1,13,39,49,413,77,1367,2553,5563,7659,3467, + 1,1,5,9,3,49,23,11,445,121,1505,877,4137,1809,2429, + 1,1,1,11,21,13,93,33,493,805,775,2939,2961,13625,31879, + 1,1,7,5,1,59,63,131,373,23,337,2107,5315,4889,22851, + 1,1,3,13,21,47,15,131,353,793,1891,1757,5793,1147,23697, + 1,3,5,13,7,59,25,135,259,109,1835,429,8153,7355,145, + 1,3,3,13,9,47,121,89,89,635,1079,2353,4803,11369,12653, + 1,3,5,9,23,39,49,231,105,603,613,2021,6073,11819,10595, + 1,3,7,7,7,19,19,155,347,387,1459,3793,619,14437,2455, + 1,1,1,15,21,35,19,185,483,425,479,3429,5403,10791,14219, + 1,1,3,11,5,51,105,63,493,677,1457,2865,5619,9321,19583, + 1,1,3,3,23,1,77,177,263,289,1567,3837,5359,3269,16023, + 1,1,7,3,13,61,79,77,51,953,1417,795,4467,2981,25131, + 1,1,5,13,23,13,29,185,337,7,149,3609,8119,9545,16579, + 1,3,1,5,23,9,123,15,99,55,1021,3709,1521,15189,22193, + 1,3,7,9,13,41,39,45,49,181,1587,3213,1037,14775,3333, + 1,1,1,7,29,55,59,31,411,601,191,283,3211,7951,7919, + 1,1,7,7,21,47,7,193,343,831,1267,3289,1015,13093,2717, + 1,3,7,1,17,9,97,19,279,827,1699,3573,3137,3535,17791, + 1,1,5,11,27,15,103,135,35,625,1575,97,7013,13353,19333, + 1,3,3,7,17,13,49,135,435,743,1799,2655,4839,2893,31153, + 1,1,5,1,3,41,1,195,53,803,1575,2939,3873,10495,5211, + 1,3,1,15,19,19,37,59,355,483,685,3899,4645,15127,3479, + 1,1,5,3,25,9,9,229,101,631,1165,4091,3723,10655,9463, + 1,3,5,15,5,13,91,61,19,469,1675,3331,3121,3435,4111, + 1,1,7,1,31,61,23,83,165,551,1097,3825,5385,4723,3635, + 1,3,7,15,9,31,11,121,503,855,561,1647,1229,1147,15997, + 1,3,7,13,21,47,41,195,197,719,1263,3609,7515,2659,30713, + 1,1,1,7,31,61,101,101,479,571,605,301,6633,15587,23665, + 1,3,7,3,25,39,35,225,135,463,53,709,5129,4135,10421, + 1,1,5,13,19,55,107,15,163,287,673,899,5197,4619,3465, + 1,3,3,5,21,49,15,105,283,877,1875,1079,3431,13053,26599, + 1,1,7,1,1,1,95,113,119,575,1159,2325,6895,12177,4369, + 1,1,1,11,25,25,83,207,301,729,1947,2321,3621,15707,11303, + 1,1,5,5,7,63,83,105,211,175,1817,2883,5385,7437,24865, + 1,3,7,5,23,39,19,211,151,295,573,223,5065,6345,23187, + 1,1,7,11,15,31,89,123,57,695,685,1799,659,9929,22933, + 1,1,7,7,19,17,27,137,117,141,1481,869,7061,3073,19671, + 1,3,3,11,9,19,123,93,39,517,883,3769,2267,8089,6617, + 1,3,1,7,9,61,51,241,319,853,1239,899,105,1677,29351, + 1,1,7,15,13,59,85,175,223,87,905,3175,3405,3489,18475, + 1,1,1,15,1,55,79,97,315,605,851,4015,3689,9371,31523, + 1,1,5,15,1,39,91,27,211,881,1375,2307,5791,10185,23093, + 1,3,1,5,3,17,59,219,105,623,21,2843,3427,4799,3793, + 1,3,3,7,21,55,17,29,397,93,1981,4047,935,5971,14589, + 1,1,3,9,5,57,63,27,373,815,167,205,367,4945,30041, + 1,1,5,9,7,3,69,35,197,309,1729,3735,1523,10427,26253, + 1,1,3,7,7,49,35,189,297,311,2025,305,3863,14393,2533, + 1,3,3,9,17,31,5,17,167,601,909,3149,2533,12123,25325, + 1,3,5,3,11,41,69,199,79,611,133,3519,5955,4609,27403, + 1,3,3,13,3,17,53,165,361,797,1447,869,6707,6541,32249, + 1,3,1,1,29,47,17,45,473,199,1595,3095,3635,6965,21859, + 1,1,3,9,1,15,59,163,91,811,1087,1707,6743,12643,29901, + 1,1,1,3,19,21,7,209,121,821,709,1085,5333,7689,28355, + 1,3,1,15,5,27,115,31,37,79,1347,155,3709,13251,32151, + 1,3,7,15,27,27,127,231,137,205,1665,1461,299,2797,879, + 1,1,1,7,13,3,127,13,253,481,1435,1895,2665,7611,17761, + 1,1,3,7,7,21,71,247,301,183,1785,331,4835,2251,4493, + 1,3,7,9,9,1,77,169,103,647,1959,1847,5803,3421,15915, + 1,3,1,7,19,17,81,45,263,549,1607,2177,1117,14427,16451, + 1,1,7,15,27,25,27,27,33,813,1667,253,2749,927,29707, + 1,1,7,3,17,29,13,67,417,303,19,3809,7225,12775,3933, + 1,1,1,11,13,41,77,217,281,659,1099,3047,1619,525,4313, + 1,3,3,9,23,47,5,33,219,531,77,2307,1893,8335,8281, + 1,3,7,3,3,35,27,249,159,495,431,3001,1475,11505,15693, + 1,1,5,9,21,49,43,159,465,959,179,993,121,11569,21027, + 1,3,1,5,1,61,9,221,231,55,191,2829,3331,8911,15109, + 1,1,7,1,7,35,67,97,159,191,935,3151,6397,10751,1835, + 1,1,1,7,15,39,127,163,437,333,829,753,8151,13239,523, + 1,1,3,13,9,25,73,155,445,239,2035,15,5243,15531,1733, + 1,3,7,15,5,25,3,55,117,57,783,1509,7043,13159,8557, + 1,3,5,1,21,55,89,119,199,79,161,1597,3263,3335,5757, + 1,3,7,5,27,23,85,113,111,211,389,1513,2759,7945,931, + 1,1,1,7,1,5,17,177,357,619,5,2583,621,2973,28845, + 1,3,7,13,11,21,47,99,421,279,1541,1305,4571,6127,20735, + 1,3,5,5,23,43,19,137,425,409,1625,2671,4385,3197,25753, + 1,1,7,5,27,17,57,15,383,181,951,2115,5237,1495,9671, + 1,3,3,11,9,1,53,127,375,499,1487,121,1465,3175,24337 + }; + + return sobol_minit[max_degree * dim + degree]; + } +}; + +} // namespace qrng_tables +} // namespace detail + +} // namespace random + +} // namespace boost + +#endif // BOOST_RANDOM_DETAIL_SOBOL_TABLE_HPP diff --git a/include/boost/random/faure.hpp b/include/boost/random/faure.hpp index a923063..5347636 100644 --- a/include/boost/random/faure.hpp +++ b/include/boost/random/faure.hpp @@ -1,6 +1,6 @@ /* boost random/faure.hpp header file * - * Copyright Justinas Vygintas Daugmaudis 2010-2017 + * Copyright Justinas Vygintas Daugmaudis 2010-2018 * 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) @@ -11,31 +11,26 @@ #include +#include #include #include -#include - #include -#include - -//!\file -//!Describes the quasi-random number generator class template faure. - namespace boost { namespace random { /** @cond */ namespace detail { -namespace fr { + +namespace qrng_tables { // There is no particular reason why 187 first primes were chosen // to be put into this table. The only reason was, perhaps, that // the number of dimensions for Faure generator would be around -// the same number as the number of dimensions supported by the -// Sobol qrng. -struct prime_table +// the same order of magnitude as the number of dimensions supported +// by the Sobol qrng. +struct primes { typedef unsigned short value_type; @@ -62,56 +57,58 @@ struct prime_table 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117 }; - if (n > prim_a[number_of_primes - 1]) - { - std::ostringstream os; - os << "The Faure quasi-random number generator only supports up to " - << prim_a[number_of_primes - 1] << " dimensions."; - throw std::invalid_argument(os.str()); - } + dimension_assert("Faure", n, prim_a[number_of_primes - 1]); return *std::lower_bound(prim_a, prim_a + number_of_primes, n); } }; +} // namespace qrng_tables + + +namespace fr { + // Returns the integer part of the logarithm base Base of arg. // In erroneous situations, e.g., integer_log(base, 0) the function // returns 0 and does not report the error. This is the intended // behavior. -inline std::size_t integer_log(std::size_t base, std::size_t arg) +template +inline T integer_log(T base, T arg) { - std::size_t ilog = 0; - while( base <= arg ) + T ilog = T(); + while (base <= arg) { arg /= base; ++ilog; } return ilog; } -// Perform exponentiation by squaring -inline std::size_t integer_pow(std::size_t base, std::size_t exp) +// Perform exponentiation by squaring (potential for code reuse in multiprecision::powm) +template +inline T integer_pow(T base, T e) { - std::size_t result = 1; - while (exp) + T result = static_cast(1); + while (e) { - if (exp & 1) + if (e & static_cast(1)) result *= base; - exp >>= 1; + e >>= 1; base *= base; } return result; } // Computes a table of binomial coefficients modulo qs. -template +template struct binomial_coefficients { typedef RealType value_type; + typedef SeqSizeT size_type; // Binomial values modulo qs_base will never be bigger than qs_base. // We can choose an appropriate integer type to hold modulo values and // shave off memory footprint. - typedef prime_table::value_type packed_uint_t; + typedef typename PrimeTable::value_type packed_uint_t; // default copy c-tor is fine @@ -122,60 +119,57 @@ struct binomial_coefficients void resize(std::size_t dimension) { - qs_base = fr::prime_table::lower_bound(dimension); - inv_qs_base = static_cast(1) / static_cast(qs_base); + qs_base = PrimeTable::lower_bound(dimension); // Throw away previously computed coefficients. // This will trigger recomputation on next update coeff.clear(); } - void update(std::size_t seq, std::vector& quasi) + template + void update(size_type seq, Iterator first, Iterator last) { - if (!quasi.empty()) + if (first != last) { - const std::size_t hisum = n_elements(seq); - if( coeff.size() != size_hint(hisum) ) - recompute_tables(hisum); - - typename std::vector::iterator it = quasi.begin(); - - *it = compute_recip(seq, hisum, ytemp.rbegin()); - + const size_type ilog = integer_log(static_cast(qs_base), seq); + const size_type hisum = ilog + 1; + if (coeff.size() != size_hint(hisum)) { + ytemp.resize(hisum); + compute_coefficients(hisum); + qs_pow = integer_pow(static_cast(qs_base), ilog); + } + + *first = compute_recip(seq, ytemp.rbegin()); + // Find other components using the Faure method. - ++it; - for ( ; it != quasi.end(); ++it) + ++first; + for ( ; first != last; ++first) { - *it = RealType(); - RealType r = inv_qs_base; - - for (std::size_t i = 0; i != hisum; ++i) + *first = RealType(); + RealType r = static_cast(1); + + for (size_type i = 0; i != hisum; ++i) { - RealType ztemp = RealType(); - for (std::size_t j = i; j != hisum; ++j) + RealType ztemp = ytemp[i] * upper_element(i, i, hisum); + for (size_type j = i + 1; j != hisum; ++j) ztemp += ytemp[j] * upper_element(i, j, hisum); - + // Sum ( J <= I <= HISUM ) ( old ytemp(i) * binom(i,j) ) mod QS. ytemp[i] = std::fmod(ztemp, static_cast(qs_base)); - *it += ytemp[i] * r; - r *= inv_qs_base; + r *= static_cast(qs_base); + *first += ytemp[i] / r; } } } } private: - inline std::size_t n_elements(std::size_t seq) const - { - return integer_log(qs_base, seq) + 1; - } - - inline static std::size_t size_hint(std::size_t n) + inline static size_type size_hint(size_type n) { return n * (n + 1) / 2; } - packed_uint_t& upper_element(std::size_t i, std::size_t j, std::size_t dim) + packed_uint_t& upper_element(size_type i, size_type j, size_type dim) { BOOST_ASSERT( i < dim ); BOOST_ASSERT( j < dim ); @@ -184,26 +178,26 @@ private: } template - RealType compute_recip(std::size_t seq, std::size_t n, Iterator out) const + RealType compute_recip(size_type seq, Iterator out) const { // Here we do // Sum ( 0 <= J <= HISUM ) YTEMP(J) * QS**J // Sum ( 0 <= J <= HISUM ) YTEMP(J) / QS**(J+1) // in one go RealType r = RealType(); - std::size_t m, k = integer_pow(qs_base, n - 1); - for( ; n != 0; --n, ++out, seq = m, k /= qs_base ) + size_type m, k = qs_pow; + for( ; k != 0; ++out, seq = m, k /= qs_base ) { m = seq % k; - RealType v = (seq - m) / k; // RealType <- IntType + RealType v = (seq - m) / k; // RealType <- size type r += v; - r *= inv_qs_base; + r /= static_cast(qs_base); *out = v; // saves double dereference } return r; } - void compute_coefficients(const std::size_t n) + void compute_coefficients(const size_type n) { // Resize and initialize to zero coeff.resize(size_hint(n)); @@ -211,16 +205,16 @@ private: // The first row and the diagonal is assigned to 1 upper_element(0, 0, n) = 1; - for (std::size_t i = 1; i < n; ++i) + for (size_type i = 1; i < n; ++i) { upper_element(0, i, n) = 1; upper_element(i, i, n) = 1; } // Computes binomial coefficients MOD qs_base - for (std::size_t i = 1; i < n; ++i) + for (size_type i = 1; i < n; ++i) { - for (std::size_t j = i + 1; j < n; ++j) + for (size_type j = i + 1; j < n; ++j) { upper_element(i, j, n) = ( upper_element(i, j-1, n) + upper_element(i-1, j-1, n) ) % qs_base; @@ -228,27 +222,25 @@ private: } } - void recompute_tables(std::size_t n) - { - ytemp.resize(n); - compute_coefficients(n); - } - private: packed_uint_t qs_base; - RealType inv_qs_base; // here we cache precomputed data; note that binomial coefficients have // to be recomputed iff the integer part of the logarithm of seq changes, // which happens relatively rarely. std::vector coeff; // packed upper (!) triangular matrix std::vector ytemp; + size_type qs_pow; }; }} // namespace detail::fr + +typedef detail::qrng_tables::primes default_faure_prime_table; + /** @endcond */ -//!class template faure implements a quasi-random number generator as described in +//!Instantiations of class template faure_engine model a \quasi_random_number_generator. +//!The faure_engine uses the algorithm described in //! \blockquote //!Henri Faure, //!Discrepance de suites associees a un systeme de numeration (en dimension s), @@ -265,102 +257,106 @@ private: //!Volume 12, Number 4, December 1986, pages 362-376. //! \endblockquote //! -//!\attention\b Important: This implementation supports up to 229 dimensions. -//! //!In the following documentation @c X denotes the concrete class of the template -//!faure returning objects of type @c RealType, u and v are the values of @c X. +//!faure_engine returning objects of type @c RealType, u and v are the values of @c X. //! //!Some member functions may throw exceptions of type @c std::bad_alloc. -//! -//! \copydoc friendfunctions -template -class faure : public detail::qrng_base< - faure - , detail::fr::binomial_coefficients - > +template +class faure_engine + : public detail::qrng_base< + faure_engine + , detail::fr::binomial_coefficients + , SeqSizeT + > { - typedef faure self_t; + typedef faure_engine self_t; - typedef detail::fr::binomial_coefficients lattice_t; - typedef detail::qrng_base base_t; + typedef detail::fr::binomial_coefficients lattice_t; + typedef detail::qrng_base base_t; - friend class detail::qrng_base; + friend class detail::qrng_base; public: typedef RealType result_type; - /** @copydoc boost::random::niederreiter_base2::min() */ - static result_type min /** @cond */ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ () { return static_cast(0); } + /** @copydoc boost::random::niederreiter_base2_engine::min() */ + static BOOST_CONSTEXPR result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () + { return static_cast(0); } - /** @copydoc boost::random::niederreiter_base2::max() */ - static result_type max /** @cond */ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ () { return static_cast(1); } + /** @copydoc boost::random::niederreiter_base2_engine::max() */ + static BOOST_CONSTEXPR result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () + { return static_cast(1); } - //!Effects: Constructs the s-dimensional default Faure quasi-random number generator. + //!Effects: Constructs the `s`-dimensional default Faure quasi-random number generator. //! //!Throws: bad_alloc, invalid_argument. - explicit faure(std::size_t s) + explicit faure_engine(std::size_t s) : base_t(s) // initialize the binomial table here {} - /** @copydetails boost::random::niederreiter_base2::seed() + /** @copydetails boost::random::niederreiter_base2_engine::seed(UIntType) * Throws: bad_alloc. */ - void seed() - { - seed(0); - } - - /** @copydetails boost::random::niederreiter_base2::seed(std::size_t) - * Throws: bad_alloc. - */ - void seed(std::size_t init) + void seed(SeqSizeT init = 0) { compute_seq(init); - this->curr_elem = 0; - this->seq_count = init; + base_t::reset_seq(init); } +#ifdef BOOST_RANDOM_DOXYGEN //=========================Doxygen needs this!============================== - //!Requirements: *this is mutable. - //! - //!Returns: Returns a successive element of an s-dimensional - //!(s = X::dimension()) vector at each invocation. When all elements are - //!exhausted, X::operator() begins anew with the starting element of a - //!subsequent s-dimensional vector. - //! - //!Throws: bad_alloc. + /** @copydoc boost::random::niederreiter_base2_engine::dimension() */ + std::size_t dimension() const { return base_t::dimension(); } - // Fixed in Doxygen 1.7.0 -- id 612458: Fixed problem handling @copydoc for function operators. + /** @copydoc boost::random::niederreiter_base2_engine::operator()() */ result_type operator()() { return base_t::operator()(); } - /** @copydoc boost::random::niederreiter_base2::discard(std::size_t) + /** @copydoc boost::random::niederreiter_base2_engine::discard(boost::uintmax_t) * Throws: bad_alloc. */ - void discard(std::size_t z) + void discard(boost::uintmax_t z) { base_t::discard(z); } + /** Returns true if the two generators will produce identical sequences of outputs. */ + BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(faure_engine, x, y) + { return static_cast(x) == y; } + + /** Returns true if the two generators will produce different sequences of outputs. */ + BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(faure_engine) + + /** Writes the textual representation of the generator to a @c std::ostream. */ + BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, faure_engine, s) + { return os << static_cast(s); } + + /** Reads the textual representation of the generator from a @c std::istream. */ + BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, faure_engine, s) + { return is >> static_cast(s); } + +#endif // BOOST_RANDOM_DOXYGEN + private: /** @cond hide_private_members */ - void compute_seq(std::size_t seq) + void compute_seq(SeqSizeT seq) { - this->lattice.update(seq, this->quasi_state); - } - void compute_next() - { - compute_seq(++this->seq_count); + this->lattice.update(seq, this->state_begin(), this->state_end()); } /** @endcond */ }; -} // namespace random +/** + * @attention This specialization of \faure_engine supports up to 1117 dimensions. + * + * However, it is possible to provide your own prime table to \faure_engine should the default one be insufficient. + */ +typedef faure_engine faure; -typedef random::faure faure; +} // namespace random } // namespace boost diff --git a/include/boost/random/niederreiter_base2.hpp b/include/boost/random/niederreiter_base2.hpp index 4e19d07..9dcb2aa 100644 --- a/include/boost/random/niederreiter_base2.hpp +++ b/include/boost/random/niederreiter_base2.hpp @@ -1,6 +1,6 @@ /* boost random/nierderreiter_base2.hpp header file * - * Copyright Justinas Vygintas Daugmaudis 2010-2017 + * Copyright Justinas Vygintas Daugmaudis 2010-2018 * 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) @@ -9,20 +9,10 @@ #ifndef BOOST_RANDOM_NIEDERREITER_BASE2_HPP #define BOOST_RANDOM_NIEDERREITER_BASE2_HPP -#include -#include -#include - -#include -#include +#include +#include #include -#include - -//!\file -//!Describes the quasi-random number generator class template niederreiter_base2. -//! -//!\b Note: it is especially useful in conjunction with class template uniform_real. namespace boost { namespace random { @@ -31,134 +21,64 @@ namespace random { namespace detail { namespace nb2 { -/* - Primitive polynomials in binary encoding - { - { 1, 0, 0, 0, 0, 0 }, 1 - { 0, 1, 0, 0, 0, 0 }, x - { 1, 1, 0, 0, 0, 0 }, 1 + x - { 1, 1, 1, 0, 0, 0 }, 1 + x + x^2 - { 1, 1, 0, 1, 0, 0 }, 1 + x + x^3 - { 1, 0, 1, 1, 0, 0 }, 1 + x^2 + x^3 - { 1, 1, 0, 0, 1, 0 }, 1 + x + x^4 - { 1, 0, 0, 1, 1, 0 }, 1 + x^3 + x^4 - { 1, 1, 1, 1, 1, 0 }, 1 + x + x^2 + x^3 + x^4 - { 1, 0, 1, 0, 0, 1 }, 1 + x^2 + x^5 - { 1, 0, 0, 1, 0, 1 }, 1 + x^3 + x^5 - { 1, 1, 1, 1, 0, 1 }, 1 + x + x^2 + x^3 + x^5 - { 1, 1, 1, 0, 1, 1 } 1 + x + x^2 + x^4 + x^5 - }; -*/ - -// Maximum allowed space dimension -#define BOOST_RANDOM_NIEDERREITER_BASE2_MAX_DIMENSION 54 - -struct niederreiter_tables -{ - BOOST_STATIC_CONSTANT(int, max_dimension = BOOST_RANDOM_NIEDERREITER_BASE2_MAX_DIMENSION); - - // Binary irreducible polynomials (primes in the ring GF(2)[X]), evaluated at X=2. - static unsigned short polynomial(std::size_t n) - { - static const unsigned short nb2_a[max_dimension] = { - 2, 3, 7, 11, 13, 19, 25, 31, 37, 41, - 47, 55, 59, 61, 67, 73, 87, 91, 97, 103, - 109, 115, 117, 131, 137, 143, 145, 157, - 167, 171, 185, 191, 193, 203, 211, 213, - 229, 239, 241, 247, 253, 283, 285, 299, - 301, 313, 319, 333, 351, 355, 357, 361, 369, - 375 - }; - - return nb2_a[n]; - } -}; - // Return the base 2 logarithm for a given bitset v -template -inline typename boost::dynamic_bitset::size_type -bitset_log2(const boost::dynamic_bitset& v) +template +inline typename DynamicBitset::size_type +bitset_log2(const DynamicBitset& v) { - typedef boost::dynamic_bitset bitset_t; - typedef typename bitset_t::size_type size_type; - if (v.none()) - throw std::invalid_argument("bitset_log2"); + boost::throw_exception( std::invalid_argument("bitset_log2") ); - size_type up = v.size() - 1; - size_type low = v.find_next(0); - - // Binary lookup for the most significant set bit - while (low < up) - { - size_type m = low + (up - low) / 2; - - // Check if any bit is present after mid - size_type p = v.find_next(m); - if (p != bitset_t::npos) - low = p; - else - up = m; - } - - return low; + typename DynamicBitset::size_type hibit = v.size() - 1; + while (!v.test(hibit)) + --hibit; + return hibit; } // Multiply polynomials over Z_2. -template -inline boost::dynamic_bitset -modulo2_multiply(int P, boost::dynamic_bitset v) +template +inline void modulo2_multiply(unsigned P, DynamicBitset& v, DynamicBitset& pt) { - boost::dynamic_bitset pt (v.size()); + pt.reset(); // pt == 0 for (; P; P >>= 1, v <<= 1) if (P & 1) pt ^= v; - return pt; + pt.swap(v); } // Calculate the values of the constants V(J,R) as // described in BFN section 3.3. // -// px = appropriate irreducible polynomial for current dimension // pb = polynomial defined in section 2.3 of BFN. -// pb is modified -template -inline void calculate_v(const boost::dynamic_bitset& pb, - int& pb_degree, std::vector& v) +template +inline void calculate_v(const DynamicBitset& pb, + typename DynamicBitset::size_type kj, + typename DynamicBitset::size_type pb_degree, + DynamicBitset& v) { - const T arbitrary_element = static_cast(1); // arbitray element of Z_2 - - // Now choose a value of Kj as defined in section 3.3. - // We must have 0 <= Kj < E*J = M. - // The limit condition on Kj does not seem very relevant - // in this program. - int kj = pb_degree; - - pb_degree = bitset_log2(pb); + typedef typename DynamicBitset::size_type size_type; // Now choose values of V in accordance with // the conditions in section 3.3. - std::fill(v.begin(), v.begin() + kj, T()); + size_type r = 0; + for ( ; r != kj; ++r) + v.reset(r); // Quoting from BFN: "Our program currently sets each K_q // equal to eq. This has the effect of setting all unrestricted // values of v to 1." - // Actually, it sets them to the arbitrary chosen value. - // Whatever. - for (int r = kj; r < pb_degree; ++r) - v[r] = arbitrary_element; + for ( ; r < pb_degree; ++r) + v.set(r); // Calculate the remaining V's using the recursion of section 2.3, // remembering that the B's have the opposite sign. - for (int r = pb_degree; r < v.size(); ++r) + for ( ; r != v.size(); ++r) { - T term = T /*zero*/ (); - boost::dynamic_bitset<> pb_c = pb; - for (int k = -pb_degree; k < 0; ++k, pb_c >>= 1) + bool term = false; + for (int k = -pb_degree; k < 0; ++k) { - if( pb_c.test(0) ) - term ^= v[r + k]; + term ^= pb.test(k + pb_degree) & v[r + k]; } v[r] = term; } @@ -166,12 +86,13 @@ inline void calculate_v(const boost::dynamic_bitset& pb, } // namespace nb2 -template +template struct niederreiter_base2_lattice { - typedef IntType value_type; + typedef UIntType value_type; - BOOST_STATIC_CONSTANT(int, bit_count = std::numeric_limits::digits); + BOOST_STATIC_ASSERT(w > 0u); + BOOST_STATIC_CONSTANT(unsigned, bit_count = w); explicit niederreiter_base2_lattice(std::size_t dimension) { @@ -180,157 +101,179 @@ struct niederreiter_base2_lattice void resize(std::size_t dimension) { - if (dimension > nb2::niederreiter_tables::max_dimension) - { - throw std::invalid_argument("The Niederreiter base 2 quasi-random number generator only supports up to " - BOOST_PP_STRINGIZE(BOOST_RANDOM_NIEDERREITER_BASE2_MAX_DIMENSION) " dimensions."); - } + typedef boost::dynamic_bitset<> bitset_type; + + dimension_assert("Niederreiter base 2", dimension, Nb2Table::max_dimension); // Initialize the bit array - bits.resize(boost::extents[bit_count][dimension]); - - // Reserve temporary space for lattice computation - boost::multi_array ci(boost::extents[bit_count][bit_count]); + cj.resize(bit_count * dimension); - std::vector v; + // Reserve temporary space for lattice computation + bitset_type v, pb, tmp; // Compute Niedderreiter base 2 lattice for (std::size_t dim = 0; dim != dimension; ++dim) { - const int poly = nb2::niederreiter_tables::polynomial(dim); - if (static_cast(poly) > - static_cast(std::numeric_limits::max())) { - boost::throw_exception( std::range_error("niederreiter_base2: polynomial value outside the given IntType range") ); + const unsigned int poly = Nb2Table::polynomial(dim); + if (poly > std::numeric_limits::max()) { + boost::throw_exception( std::range_error("niederreiter_base2: polynomial value outside the given value type range") ); } - const int degree = multiprecision::detail::find_msb(poly); // integer log2(poly) - const int max_degree = degree * ((bit_count / degree) + 1); + const unsigned degree = multiprecision::msb(poly); // integer log2(poly) + const unsigned space_required = degree * ((bit_count / degree) + 1); // ~ degree + bit_count + + v.resize(degree + bit_count - 1); - v.resize(degree + max_degree); - // For each dimension, we need to calculate powers of an // appropriate irreducible polynomial, see Niederreiter // page 65, just below equation (19). // Copy the appropriate irreducible polynomial into PX, - // and its degree into E. Set polynomial B = PX ** 0 = 1. - // M is the degree of B. Subsequently B will hold higher + // and its degree into E. Set polynomial B = PX ** 0 = 1. + // M is the degree of B. Subsequently B will hold higher // powers of PX. - int pb_degree = 0; - boost::dynamic_bitset<> pb(max_degree, 1); - - int j = 0; - while (j < bit_count) + pb.resize(space_required); tmp.resize(space_required); + + typename bitset_type::size_type kj, pb_degree = 0; + pb.reset(); // pb == 0 + pb.set(pb_degree); // set the proper bit for the pb_degree + + value_type j = static_cast(1) << (bit_count - 1); + do { + // Now choose a value of Kj as defined in section 3.3. + // We must have 0 <= Kj < E*J = M. + // The limit condition on Kj does not seem to be very relevant + // in this program. + kj = pb_degree; + // Now multiply B by PX so B becomes PX**J. // In section 2.3, the values of Bi are defined with a minus sign : // don't forget this if you use them later! - nb2::modulo2_multiply(poly, boost::move(pb)).swap(pb); + nb2::modulo2_multiply(poly, pb, tmp); + pb_degree += degree; + if (pb_degree >= pb.size()) { + // Note that it is quite possible for kj to become bigger than + // the new computed value of pb_degree. + pb_degree = nb2::bitset_log2(pb); + } // If U = 0, we need to set B to the next power of PX // and recalculate V. - nb2::calculate_v(pb, pb_degree, v); - + nb2::calculate_v(pb, kj, pb_degree, v); + // Niederreiter (page 56, after equation (7), defines two // variables Q and U. We do not need Q explicitly, but we // do need U. - + // Advance Niederreiter's state variables. - for (int u = 0; u < degree && j < bit_count; ++u, ++j) + for (unsigned u = 0; j && u != degree; ++u, j >>= 1) { - // Now C is obtained from V. Niederreiter + // Now C is obtained from V. Niederreiter // obtains A from V (page 65, near the bottom), and then gets // C from A (page 56, equation (7)). However this can be done // in one step. Here CI(J,R) corresponds to - // Niederreiter's C(I,J,R). - for (int r = 0; r < bit_count; ++r) { - ci[r][j] = v[r + u]; + // Niederreiter's C(I,J,R), whose values we pack into array + // CJ so that CJ(I,R) holds all the values of C(I,J,R) for J from 1 to NBITS. + for (unsigned r = 0; r != bit_count; ++r) { + value_type& num = cj[dimension * r + dim]; + // set the jth bit in num + num = (num & ~j) | (-v[r + u] & j); } } - } - - // The array CI now holds the values of C(I,J,R) for this value - // of I. We pack them into array CJ so that CJ(I,R) holds all - // the values of C(I,J,R) for J from 1 to NBITS. - for (int r = 0; r < bit_count; ++r) - { - IntType term = 0; - for (int j = 0; j < bit_count; ++j) - term = 2*term + ci[r][j]; - bits[r][dim] = term; - } + } while (j != 0); } } - value_type operator()(int i, int j) const + typename std::vector::const_iterator iter_at(std::size_t n) const { - return bits[i][j]; + BOOST_ASSERT(!(n > cj.size())); + return cj.begin() + n; } private: - boost::multi_array bits; + std::vector cj; }; } // namespace detail + +typedef detail::qrng_tables::niederreiter_base2 default_niederreiter_base2_table; + /** @endcond */ -//!class template niederreiter_base2 implements a quasi-random number generator as described in +//!Instantiations of class template niederreiter_base2_engine model a \quasi_random_number_generator. +//!The niederreiter_base2_engine uses the algorithm described in //! \blockquote //!Bratley, Fox, Niederreiter, ACM Trans. Model. Comp. Sim. 2, 195 (1992). //! \endblockquote //! -//!\attention \b Important: This implementation supports up to 20 dimensions. +//!\attention niederreiter_base2_engine skips trivial zeroes at the start of the sequence. For example, +//!the beginning of the 2-dimensional Niederreiter base 2 sequence in @c uniform_01 distribution will look +//!like this: +//!\code{.cpp} +//!0.5, 0.5, +//!0.75, 0.25, +//!0.25, 0.75, +//!0.375, 0.375, +//!0.875, 0.875, +//!... +//!\endcode //! //!In the following documentation @c X denotes the concrete class of the template -//!niederreiter_base2 returning objects of type @c IntType, u and v are the values of @c X. +//!niederreiter_base2_engine returning objects of type @c UIntType, u and v are the values of @c X. //! -//!Some member functions may throw exceptions of type std::overflow_error. This +//!Some member functions may throw exceptions of type std::range_error. This //!happens when the quasi-random domain is exhausted and the generator cannot produce //!any more values. The length of the low discrepancy sequence is given by -//! \f$L=Dimension \times 2^{digits}\f$, where digits = std::numeric_limits::digits. -template -class niederreiter_base2 : public detail::gray_coded_qrng_base< - niederreiter_base2, - detail::niederreiter_base2_lattice > +//! \f$L=Dimension \times (2^{w} - 1)\f$. +template +class niederreiter_base2_engine + : public detail::gray_coded_qrng< + detail::niederreiter_base2_lattice + > { - typedef niederreiter_base2 self_t; - typedef detail::niederreiter_base2_lattice lattice_t; - typedef detail::gray_coded_qrng_base base_t; + typedef detail::niederreiter_base2_lattice lattice_t; + typedef detail::gray_coded_qrng base_t; public: - typedef IntType result_type; + //!Effects: Constructs the default `s`-dimensional Niederreiter base 2 quasi-random number generator. + //! + //!Throws: bad_alloc, invalid_argument, range_error. + explicit niederreiter_base2_engine(std::size_t s) + : base_t(s) // initialize lattice here + {} + +#ifdef BOOST_RANDOM_DOXYGEN + //=========================Doxygen needs this!============================== + typedef UIntType result_type; //!Returns: Tight lower bound on the set of values returned by operator(). //! //!Throws: nothing. - static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return 0; } + static BOOST_CONSTEXPR result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () + { return (base_t::min)(); } //!Returns: Tight upper bound on the set of values returned by operator(). //! //!Throws: nothing. - static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () { return std::numeric_limits::max(); } + static BOOST_CONSTEXPR result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () + { return (base_t::max)(); } - //!Effects: Constructs the default s-dimensional Niederreiter base 2 quasi-random number generator. + //!Returns: The dimension of of the quasi-random domain. //! - //!Throws: bad_alloc, invalid_argument, range_error. - explicit niederreiter_base2(std::size_t s) - : base_t(s) // initialize lattice here - {} + //!Throws: nothing. + std::size_t dimension() const { return base_t::dimension(); } - //!Requirements: *this is mutable. - //! //!Effects: Resets the quasi-random number generator state to //!the one given by the default construction. Equivalent to u.seed(0). //! //!\brief Throws: nothing. void seed() { - base_t::reset_state(); + base_t::seed(); } - //!Requirements: *this is mutable. - //! - //!Effects: Effectively sets the quasi-random number generator state to the init-th - //!vector in the s-dimensional quasi-random domain, where s == X::dimension(). + //!Effects: Effectively sets the quasi-random number generator state to the `init`-th + //!vector in the `s`-dimensional quasi-random domain, where `s` == X::dimension(). //!\code //!X u, v; //!for(int i = 0; i < N; ++i) @@ -340,30 +283,24 @@ public: //!assert(u() == v()); //!\endcode //! - //!\brief Throws: overflow_error. - void seed(std::size_t init) + //!\brief Throws: range_error. + void seed(UIntType init) { - base_t::seed(init, "niederreiter_base2::seed"); + base_t::seed(init); } - //=========================Doxygen needs this!============================== - - //!Requirements: *this is mutable. - //! - //!Returns: Returns a successive element of an s-dimensional + //!Returns: Returns a successive element of an `s`-dimensional //!(s = X::dimension()) vector at each invocation. When all elements are //!exhausted, X::operator() begins anew with the starting element of a - //!subsequent s-dimensional vector. + //!subsequent `s`-dimensional vector. //! - //!Throws: overflow_error. + //!Throws: range_error. result_type operator()() { return base_t::operator()(); } - //!Requirements: *this is mutable. - //! - //!Effects: Advances *this state as if z consecutive + //!Effects: Advances *this state as if `z` consecutive //!X::operator() invocations were executed. //!\code //!X u = v; @@ -373,16 +310,44 @@ public: //!assert(u() == v()); //!\endcode //! - //!Throws: overflow_error. - void discard(std::size_t z) + //!Throws: range_error. + void discard(boost::uintmax_t z) { base_t::discard(z); } + + //!Returns true if the two generators will produce identical sequences of outputs. + BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(niederreiter_base2_engine, x, y) + { return static_cast(x) == y; } + + //!Returns true if the two generators will produce different sequences of outputs. + BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(niederreiter_base2_engine) + + //!Writes the textual representation of the generator to a @c std::ostream. + BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, niederreiter_base2_engine, s) + { return os << static_cast(s); } + + //!Reads the textual representation of the generator from a @c std::istream. + BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, niederreiter_base2_engine, s) + { return is >> static_cast(s); } + +#endif // BOOST_RANDOM_DOXYGEN }; -} // namespace random -typedef random::niederreiter_base2 niederreiter_base2; +/** + * @attention This specialization of \niederreiter_base2_engine supports up to 4720 dimensions. + * + * Binary irreducible polynomials (primes in the ring `GF(2)[X]`, evaluated at `X=2`) were generated + * while condition `max(prime)` < 216 was satisfied. + * + * There are exactly 4720 such primes, which yields a Niederreiter base 2 table for 4720 dimensions. + * + * However, it is possible to provide your own table to \niederreiter_base2_engine should the default one be insufficient. + */ +typedef niederreiter_base2_engine niederreiter_base2; + +} // namespace random } // namespace boost diff --git a/include/boost/random/sobol.hpp b/include/boost/random/sobol.hpp index b688a1f..0027ddc 100644 --- a/include/boost/random/sobol.hpp +++ b/include/boost/random/sobol.hpp @@ -1,6 +1,6 @@ /* boost random/sobol.hpp header file * - * Copyright Justinas Vygintas Daugmaudis 2010-2017 + * Copyright Justinas Vygintas Daugmaudis 2010-2018 * 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) @@ -9,941 +9,14 @@ #ifndef BOOST_RANDOM_SOBOL_HPP #define BOOST_RANDOM_SOBOL_HPP -#include - -#include - -#include -#include - -#include - -#include - -//!\file -//!Describes the quasi-random number generator class template sobol. -//! -//!\b Note: it is especially useful in conjunction with class template uniform_real. +#include +#include namespace boost { namespace random { /** @cond */ namespace detail { -namespace sbl { - -// Maximum allowed space dimension -#define BOOST_RANDOM_SOBOL_MAX_DIMENSION 1111 - -// Data on the primitive binary polynomials (a) and the corresponding -// starting values m, for Sobol sequences in up to 1111 dimensions, -// taken from: -// P. Bratley and B. L. Fox, Algorithm 659, ACM Trans. -// Math. Soft. 14 (1), 88-100 (1988), -// as modified by: -// S. Joe and F. Y. Kuo, ACM Trans. Math. Soft 29 (1), 49-57 (2003). -struct sobol_tables -{ - BOOST_STATIC_CONSTANT(int, max_dimension = BOOST_RANDOM_SOBOL_MAX_DIMENSION); - BOOST_STATIC_CONSTANT(int, num_polynomials = max_dimension - 1); - - // log2(polynomial(num_polynomials - 1)), i.e., integer log2 of the last polynomial in the table - BOOST_STATIC_CONSTANT(int, max_degree = 13); - - static unsigned short polynomial(std::size_t n) - { - // successive primitive binary-coefficient polynomials p(z) - // = a_0 + a_1 z + a_2 z^2 + ... a_31 z^31, where a_i is the - // i-th bit of sobol_a[j] for the j-th polynomial. - static const unsigned short sobol_a[num_polynomials] = { - 3,7,11,13,19,25,37,59,47,61,55,41,67,97,91, - 109,103,115,131,193,137,145,143,241,157,185,167,229,171,213, - 191,253,203,211,239,247,285,369,299,301,333,351,355,357,361, - 391,397,425,451,463,487,501,529,539,545,557,563,601,607,617, - 623,631,637,647,661,675,677,687,695,701,719,721,731,757,761, - 787,789,799,803,817,827,847,859,865,875,877,883,895,901,911, - 949,953,967,971,973,981,985,995,1001,1019,1033,1051,1063, - 1069,1125,1135,1153,1163,1221,1239,1255,1267,1279,1293,1305, - 1315,1329,1341,1347,1367,1387,1413,1423,1431,1441,1479,1509, - 1527,1531,1555,1557,1573,1591,1603,1615,1627,1657,1663,1673, - 1717,1729,1747,1759,1789,1815,1821,1825,1849,1863,1869,1877, - 1881,1891,1917,1933,1939,1969,2011,2035,2041,2053,2071,2091, - 2093,2119,2147,2149,2161,2171,2189,2197,2207,2217,2225,2255, - 2257,2273,2279,2283,2293,2317,2323,2341,2345,2363,2365,2373, - 2377,2385,2395,2419,2421,2431,2435,2447,2475,2477,2489,2503, - 2521,2533,2551,2561,2567,2579,2581,2601,2633,2657,2669, - 2681,2687,2693,2705,2717,2727,2731,2739, - 2741,2773,2783,2793,2799,2801,2811,2819,2825,2833,2867,2879, - 2881,2891,2905,2911,2917,2927,2941,2951,2955,2963,2965,2991, - 2999,3005,3017,3035,3037,3047,3053,3083,3085,3097,3103,3159, - 3169,3179,3187,3205,3209,3223,3227,3229,3251,3263,3271,3277, - 3283,3285,3299,3305,3319,3331,3343,3357,3367,3373,3393,3399, - 3413,3417,3427,3439,3441,3475,3487,3497,3515,3517,3529,3543, - 3547,3553,3559,3573,3589,3613,3617,3623,3627,3635,3641,3655, - 3659,3669,3679,3697,3707,3709,3713,3731,3743,3747,3771,3791, - 3805,3827,3833,3851,3865,3889,3895,3933,3947,3949,3957,3971, - 3985,3991,3995,4007,4013,4021,4045,4051,4069,4073,4179,4201, - 4219,4221,4249,4305,4331,4359,4383,4387,4411,4431,4439,4449, - 4459,4485,4531,4569,4575,4621,4663,4669,4711,4723,4735,4793, - 4801,4811,4879,4893,4897,4921,4927,4941,4977,5017,5027,5033, - 5127,5169,5175,5199,5213,5223,5237,5287,5293,5331,5391,5405, - 5453,5523,5573,5591,5597,5611,5641,5703,5717,5721,5797,5821, - 5909,5913, - 5955,5957,6005,6025,6061,6067,6079,6081, - 6231,6237,6289,6295,6329,6383,6427,6453,6465,6501,6523,6539, - 6577,6589,6601,6607,6631,6683,6699,6707,6761,6795,6865,6881, - 6901,6923,6931,6943,6999,7057,7079,7103,7105,7123,7173,7185, - 7191,7207,7245,7303,7327,7333,7355,7365,7369,7375,7411,7431, - 7459,7491,7505,7515,7541,7557,7561,7701,7705,7727,7749,7761, - 7783,7795,7823,7907,7953,7963,7975,8049,8089,8123,8125,8137, - 8219,8231,8245,8275,8293,8303,8331,8333,8351,8357,8367,8379, - 8381,8387,8393,8417,8435,8461,8469,8489,8495,8507,8515,8551, - 8555,8569,8585,8599,8605,8639,8641,8647,8653,8671,8675,8689, - 8699,8729,8741,8759,8765,8771,8795,8797,8825,8831,8841,8855, - 8859,8883,8895,8909,8943,8951,8955,8965,8999,9003,9031,9045, - 9049,9071,9073,9085,9095,9101,9109,9123,9129,9137,9143,9147, - 9185,9197,9209,9227,9235,9247,9253,9257,9277,9297,9303,9313, - 9325,9343,9347,9371,9373,9397,9407,9409,9415,9419,9443,9481, - 9495,9501,9505,9517,9529,9555,9557,9571,9585,9591,9607,9611, - 9621,9625, - 9631,9647,9661,9669,9679,9687,9707,9731, - 9733,9745,9773,9791,9803,9811,9817,9833,9847,9851,9863,9875, - 9881,9905,9911,9917,9923,9963,9973,10003,10025,10043,10063, - 10071,10077,10091,10099,10105,10115,10129,10145,10169,10183, - 10187,10207,10223,10225,10247,10265,10271,10275,10289,10299, - 10301,10309,10343,10357,10373,10411,10413,10431,10445,10453, - 10463,10467,10473,10491,10505,10511,10513,10523,10539,10549, - 10559,10561,10571,10581,10615,10621,10625,10643,10655,10671, - 10679,10685,10691,10711,10739,10741,10755,10767,10781,10785, - 10803,10805,10829,10857,10863,10865,10875,10877,10917,10921, - 10929,10949,10967,10971,10987,10995,11009,11029,11043,11045, - 11055,11063,11075,11081,11117,11135,11141,11159,11163,11181, - 11187,11225,11237,11261,11279,11297,11307,11309,11327,11329, - 11341,11377,11403,11405,11413,11427,11439,11453,11461,11473, - 11479,11489,11495,11499,11533,11545,11561,11567,11575,11579, - 11589,11611,11623,11637,11657,11663,11687,11691,11701,11747, - 11761,11773,11783,11795,11797,11817,11849,11855,11867,11869, - 11873,11883,11919, - 11921,11927,11933,11947,11955,11961, - 11999,12027,12029,12037,12041,12049,12055,12095,12097,12107, - 12109,12121,12127,12133,12137,12181,12197,12207,12209,12239, - 12253,12263,12269,12277,12287,12295,12309,12313,12335,12361, - 12367,12391,12409,12415,12433,12449,12469,12479,12481,12499, - 12505,12517,12527,12549,12559,12597,12615,12621,12639,12643, - 12657,12667,12707,12713,12727,12741,12745,12763,12769,12779, - 12781,12787,12799,12809,12815,12829,12839,12857,12875,12883, - 12889,12901,12929,12947,12953,12959,12969,12983,12987,12995, - 13015,13019,13031,13063,13077,13103,13137,13149,13173,13207, - 13211,13227,13241,13249,13255,13269,13283,13285,13303,13307, - 13321,13339,13351,13377,13389,13407,13417,13431,13435,13447, - 13459,13465,13477,13501,13513,13531,13543,13561,13581,13599, - 13605,13617,13623,13637,13647,13661,13677,13683,13695,13725, - 13729,13753,13773,13781,13785,13795,13801,13807,13825,13835, - 13855,13861,13871,13883,13897,13905,13915,13939,13941,13969, - 13979,13981,13997,14027,14035,14037,14051,14063,14085,14095, - 14107,14113,14125,14137,14145, - 14151,14163,14193,14199,14219,14229, - 14233,14243,14277,14287,14289,14295,14301,14305,14323,14339, - 14341,14359,14365,14375,14387,14411,14425,14441,14449,14499, - 14513,14523,14537,14543,14561,14579,14585,14593,14599,14603, - 14611,14641,14671,14695,14701,14723,14725,14743,14753,14759, - 14765,14795,14797,14803,14831,14839,14845,14855,14889,14895, - 14909,14929,14941,14945,14951,14963,14965,14985,15033,15039, - 15053,15059,15061,15071,15077,15081,15099,15121,15147,15149, - 15157,15167,15187,15193,15203,15205,15215,15217,15223,15243, - 15257,15269,15273,15287,15291,15313,15335,15347,15359,15373, - 15379,15381,15391,15395,15397,15419,15439,15453,15469,15491, - 15503,15517,15527,15531,15545,15559,15593,15611,15613,15619, - 15639,15643,15649,15661,15667,15669,15681,15693,15717,15721, - 15741,15745,15765,15793,15799,15811,15825,15835,15847,15851, - 15865,15877,15881,15887,15899,15915,15935,15937,15955,15973, - 15977,16011,16035,16061,16069,16087,16093,16097,16121,16141, - 16153,16159,16165,16183,16189,16195,16197,16201,16209,16215, - 16225,16259,16265,16273,16299, - 16309,16355,16375,16381, - }; - - return sobol_a[n]; - } - - static unsigned short vinit(std::size_t degree, std::size_t dim) - { - // starting direction #'s m[i] = sobol_minit[i][j] for i=0..d of the - // degree-d primitive polynomial sobol_a[j]. - static const unsigned short sobol_minit[max_degree][num_polynomials] = { - /* [0][*] */ - { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1 }, - /* [1][*] */ - { 0, - 1,3,1,3,1,3,3,1,3,1,3,1,3,1,1,3,1,3,1,3, - 1,3,3,1,1,1,3,1,3,1,3,3,1,3,1,1,1,3,1,3,1,1,1,3,3,1,3,3,1,1, - 3,3,1,3,3,3,1,3,1,3,1,1,3,3,1,1,1,1,3,1,1,3,1,1,1,3,3,1,3,3, - 1,3,3,3,1,3,3,3,1,3,3,1,3,3,3,1,3,1,3,1,1,3,3,1,3,3,1,1,1,3, - 3,1,3,3,1,3,1,1,3,3,3,1,1,1,3,1,1,3,1,1,3,3,1,3,1,3,3,3,3,1, - 1,1,3,3,1,1,3,1,1,1,1,1,1,3,1,3,1,1,1,3,1,3,1,3,3,3,1,1,3,3, - 1,3,1,3,1,1,3,1,3,1,3,1,3,1,1,1,3,3,1,3,3,1,3,1,1,1,3,1,3,1, - 1,3,1,1,3,3,1,1,3,3,3,1,3,3,3,1,3,1,3,1,1,1,3,1,1,1,3,1,1,1, - 1,1,3,3,3,1,1,1,1,3,3,3,1,3,3,1,1,1,1,3,1,1,3,1,3,3,1,1,3,3, - 1,1,1,1,3,1,3,3,1,3,3,1,1,1,3,3,3,1,3,3,1,3,3,1,3,1,3,3,3,1, - 3,1,1,3,1,3,1,1,1,3,3,3,1,1,3,1,3,1,1,1,1,1,1,3,1,1,3,1,3,3, - 1,1,1,1,3,1,3,1,3,1,1,1,1,3,3,1,1,1,1,1,3,3,3,1,1,3,3,3,3,3, - 1,3,3,1,3,3,3,3,1,1,1,1,1,1,3,1,1,3,1,1,1,3,1,1,1,3,3,3,1,3, - 1,1,3,3,3,1,3,3,1,3,1,3,3,1,3,3,3,1,1, - 3,3,1,3,1,3,1,1,1,3,3,3,3,1,3,1,1,3,1, - 3,1,1,1,3,1,3,1,3,1,3,3,3,3,3,3,3,3,1,3,3,3,3,3,1,3,1,3,3,3, - 1,3,1,3,1,3,3,1,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,3,3,1,1,3,3,1, - 1,1,3,3,1,1,3,3,3,3,1,1,3,1,3,3,1,3,3,1,1,1,3,3,3,1,1,3,3,3, - 3,3,1,1,1,3,1,3,3,1,3,3,3,3,1,1,3,1,1,3,1,3,1,3,1,3,3,1,1,3, - 3,1,3,3,1,3,3,1,1,3,1,3,3,1,1,3,1,3,1,3,1,1,3,3,1,1,1,3,3,1, - 3,1,1,3,3,1,1,3,1,3,1,1,1,1,1,3,1,1,1,1,3,1,3,1,1,3,3,1,1,3, - 1,3,1,3,3,3,1,3,3,3,1,1,3,3,3,1,1,1,1,3,1,3,1,3,1,1,3,3,1,1, - 1,3,3,1,3,1,3,1,1,1,1,1,1,3,1,3,3,1,3,3,3,1,3,1,1,3,3,1,1,3, - 3,1,1,1,3,1,3,3,1,1,3,1,1,3,1,3,1,1,1,3,3,3,3,1,1,3,3,1,1,1, - 1,3,1,1,3,3,3,1,1,3,3,1,3,3,1,1,3,3,3,3,3,3,3,1,3,3,1,3,1,3, - 1,1,3,3,1,1,1,3,1,3,3,1,3,3,1,3,1,1,3,3,3,1,1,1,3,1,1,1,3,3, - 3,1,3,3,1,3,1,1,3,3,3,1,3,3,1,1,1,3,1,3,3,3,3,3,3,3,3,1,3,3, - 1,3,1,1,3,3,3,1,3,3,3,3,3,1,3,3,3,1,1,1, - 3,3,1,3,3,1,3,1,3,1,3,1,3,3,3,3,3,3, - 1,1,3,1,3,1,1,1,1,1,3,1,1,1,3,1,3,1,1,3,3,3,1,3,1,3,1,1,3,1, - 3,3,1,3,1,3,3,1,3,3,1,3,3,3,3,3,3,1,3,1,1,3,3,3,1,1,3,3,3,3, - 3,3,3,1,3,3,3,3,1,3,1,3,3,3,1,3,1,3,1,1,1,3,3,1,3,1,1,3,3,1, - 3,1,1,1,1,3,1,3,1,1,3,1,3,1,3,3,3,3,3,3,1,3,3,3,3,1,3,3,1,3, - 3,3,3,3,1,1,1,1,3,3,3,1,3,3,1,1,3,3,1,1,3,3,1,3,1,1,3,1,3,3, - 3,3,3,1,3,1,1,3,3,3,3,1,3,1,1,3,3,3,3,3,3,1,1,3,1,3,1,1,3,1, - 1,1,1,3,3,1,1,3,1,1,1,3,1,3,1,1,3,3,1,3,1,1,3,3,3,3,3,1,3,1, - 1,1,3,1,1,1,3,1,1,3,1,3,3,3,3,3,1,1,1,3,3,3,3,1,3,3,3,3,1,1, - 3,3,3,1,3,1,1,3,3,1,3,3,1,1,1,1,1,3,1,1,3,3,1,1,1,3,1,1,3,3, - 1,3,3,3,3,3,3,3,3,1,1,3,3,1,1,3,1,3,3,3,3,3,1}, - /* [2][*] */ - { 0,0, - 7,5,1,3,3,7,5,5,7,7,1,3,3,7,5,1,1,5,3,7, - 1,7,5,1,3,7,7,1,1,1,5,7,7,5,1,3,3,7,5,5,5,3,3,3,1,1,5,1,1,5, - 3,3,3,3,1,3,7,5,7,3,7,1,3,3,5,1,3,5,5,7,7,7,1,1,3,3,1,1,5,1, - 5,7,5,1,7,5,3,3,1,5,7,1,7,5,1,7,3,1,7,1,7,3,3,5,7,3,3,5,1,3, - 3,1,3,5,1,3,3,3,7,1,1,7,3,1,3,7,5,5,7,5,5,3,1,3,3,3,1,3,3,7, - 3,3,1,7,5,1,7,7,5,7,5,1,3,1,7,3,7,3,5,7,3,1,3,3,3,1,5,7,3,3, - 7,7,7,5,3,1,7,1,3,7,5,3,3,3,7,1,1,3,1,5,7,1,3,5,3,5,3,3,7,5, - 5,3,3,1,3,7,7,7,1,5,7,1,3,1,1,7,1,3,1,7,1,5,3,5,3,1,1,5,5,3, - 3,5,7,1,5,3,7,7,3,5,3,3,1,7,3,1,3,5,7,1,3,7,1,5,1,3,1,5,3,1, - 7,1,5,5,5,3,7,1,1,7,3,1,1,7,5,7,5,7,7,3,7,1,3,7,7,3,5,1,1,7, - 1,5,5,5,1,5,1,7,5,5,7,1,1,7,1,7,7,1,1,3,3,3,7,7,5,3,7,3,1,3, - 7,5,3,3,5,7,1,1,5,5,7,7,1,1,1,1,5,5,5,7,5,7,1,1,3,5,1,3,3,7, - 3,7,5,3,5,3,1,7,1,7,7,1,1,7,7,7,5,5,1,1,7,5,5,7,5,1,1,5,5,5, - 5,5,5,1,3,1,5,7,3,3,5,7,3,7,1,7,7,1,3, - 5,1,5,5,3,7,3,7,7,5,7,5,7,1,1,5,3,5,1, - 5,3,7,1,5,7,7,3,5,1,3,5,1,5,3,3,3,7,3,5,1,3,7,7,3,7,5,3,3,1, - 7,5,1,1,3,7,1,7,1,7,3,7,3,5,7,3,5,3,1,1,1,5,7,7,3,3,1,1,1,5, - 5,7,3,1,1,3,3,7,3,3,5,1,3,7,3,3,7,3,5,7,5,7,7,3,3,5,1,3,5,3, - 1,3,5,1,1,3,7,7,1,5,1,3,7,3,7,3,5,1,7,1,1,3,5,3,7,1,5,5,1,1, - 3,1,3,3,7,1,7,3,1,7,3,1,7,3,5,3,5,7,3,3,3,5,1,7,7,1,3,1,3,7, - 7,1,3,7,3,1,5,3,1,1,1,5,3,3,7,1,5,3,5,1,3,1,3,1,5,7,7,1,1,5, - 3,1,5,1,1,7,7,3,5,5,1,7,1,5,1,1,3,1,5,7,5,7,7,1,5,1,1,3,5,1, - 5,5,3,1,3,1,5,5,3,3,3,3,1,1,3,1,3,5,5,7,5,5,7,5,7,1,3,7,7,3, - 5,5,7,5,5,3,3,3,1,7,1,5,5,5,3,3,5,1,3,1,3,3,3,7,1,7,7,3,7,1, - 1,5,7,1,7,1,7,7,1,3,7,5,1,3,5,5,5,1,1,7,1,7,1,7,7,3,1,1,5,1, - 5,1,5,3,5,5,5,5,5,3,3,7,3,3,5,5,3,7,1,5,7,5,1,5,5,3,5,5,7,5, - 3,5,5,5,1,5,5,5,5,1,3,5,3,1,7,5,5,7,1,5,3,3,1,5,3,7,1,7,5,1, - 1,3,1,1,7,1,5,5,3,7,3,7,5,3,1,1,3,1,3,5, - 5,7,5,3,7,7,7,3,7,3,7,1,3,1,7,7,1,7, - 3,7,3,7,3,7,3,5,1,1,7,3,1,5,5,7,1,5,5,5,7,1,5,5,1,5,5,3,1,3, - 1,7,3,1,3,5,7,7,7,1,1,7,3,1,5,5,5,1,1,1,1,1,5,3,5,1,3,5,3,1, - 1,1,1,3,7,3,7,5,7,1,5,5,7,5,3,3,7,5,3,1,1,3,1,3,1,1,3,7,1,7, - 1,1,5,1,7,5,3,7,3,5,3,1,1,5,5,1,7,7,3,7,3,7,1,5,1,5,3,7,3,5, - 7,7,7,3,3,1,1,5,5,3,7,1,1,1,3,5,3,1,1,3,3,7,5,1,1,3,7,1,5,7, - 3,7,5,5,7,3,5,3,1,5,3,1,1,7,5,1,7,3,7,5,1,7,1,7,7,1,1,7,1,5, - 5,1,1,7,5,7,1,5,3,5,3,3,7,1,5,1,1,5,5,3,3,7,5,5,1,1,1,3,1,5, - 7,7,1,7,5,7,3,7,3,1,3,7,3,1,5,5,3,5,1,3,5,5,5,1,1,7,7,1,5,5, - 1,3,5,1,5,3,5,3,3,7,5,7,3,7,3,1,3,7,7,3,3,1,1,3,3,3,3,3,5,5, - 3,3,3,1,3,5,7,7,1,5,7,3,7,1,1,3,5,7,5,3,3,3}, - /* [3][*] */ - { 0,0,0,0, - 1,7,9,13,11,1,3,7,9,5,13,13,11,3,15,5,3, - 15,7,9,13,9,1,11,7,5,15,1,15,11,5,11,1,7,9,7,7,1,15,15,15,13, - 3,3,15,5,9,7,13,3,7,5,11,9,1,9,1,5,7,13,9,9,1,7,3,5,1,11,11, - 13,7,7,9,9,1,1,3,9,15,1,5,13,1,9,9,9,9,9,13,11,3,5,11,11,13, - 5,3,15,1,11,11,7,13,15,11,13,9,11,15,15,13,3,15,7,9,11,13,11, - 9,9,5,13,9,1,13,7,7,7,7,7,5,9,7,13,11,9,11,15,3,13,11,1,11,3, - 3,9,11,1,7,1,15,15,3,1,9,1,7,13,11,3,13,11,7,3,3,5,13,11,5, - 11,1,3,9,7,15,7,5,13,7,9,13,15,13,9,7,15,7,9,5,11,11,13,13,9, - 3,5,13,9,11,15,11,7,1,7,13,3,13,3,13,9,15,7,13,13,3,13,15,15, - 11,9,13,9,15,1,1,15,11,11,7,1,11,13,9,13,3,5,11,13,9,9,13,1, - 11,15,13,3,13,7,15,1,15,3,3,11,7,13,7,7,9,7,5,15,9,5,5,7,15, - 13,15,5,15,5,3,1,11,7,1,5,7,9,3,11,1,15,1,3,15,11,13,5,13,1, - 7,1,15,7,5,1,1,15,13,11,11,13,5,11,7,9,7,1,5,3,9,5,5,11,5,1, - 7,1,11,7,9,13,15,13,3,1,11,13,15,1,1,11,9,13,3,13,11,15,13,9, - 9,9,5,5,5,5,1,15,5,9, - 11,7,15,5,3,13,5,3,11,5,1,11,13,9,11, - 3,7,13,15,1,7,11,1,13,1,15,1,9,7,3,9,11,1,9,13,13,3,11,7,9,1, - 7,15,9,1,5,13,5,11,3,9,15,11,13,5,1,7,7,5,13,7,7,9,5,11,11,1, - 1,15,3,13,9,13,9,9,11,5,5,13,15,3,9,15,3,11,11,15,15,3,11,15, - 15,3,1,3,1,3,3,1,3,13,1,11,5,15,7,15,9,1,7,1,9,11,15,1,13,9, - 13,11,7,3,7,3,13,7,9,7,7,3,3,9,9,7,5,11,13,13,7,7,15,9,5,5,3, - 3,13,3,9,3,1,11,1,3,11,15,11,11,11,9,13,7,9,15,9,11,1,3,3,9, - 7,15,13,13,7,15,9,13,9,15,13,15,9,13,1,11,7,11,3,13,5,1,7,15, - 3,13,7,13,13,11,3,5,3,13,11,9,9,3,11,11,7,9,13,11,7,15,13,7, - 5,3,1,5,15,15,3,11,1,7,3,15,11,5,5,3,5,5,1,15,5,1,5,3,7,5,11, - 3,13,9,13,15,5,3,5,9,5,3,11,1,13,9,15,3,5,11,9,1,3,15,9,9,9, - 11,7,5,13,1,15,3,13,9,13,5,1,5,1,13,13,7,7,1,9,5,11,9,11,13, - 3,15,15,13,15,7,5,7,9,7,9,9,9,11,9,3,11,15,13,13,5,9,15,1,1, - 9,5,13,3,13,15,3,1,3,11,13,1,15,9,9,3,1,9,1,9,1,13,11,15,7, - 11,15,13,15,1,9,9,7, - 3,5,11,7,3,9,5,15,7,5,3,13,7,1,1,9, - 15,15,15,11,3,5,15,13,7,15,15,11,11,9,5,15,9,7,3,13,1,1,5,1, - 3,1,7,1,1,5,1,11,11,9,9,5,13,7,7,7,1,1,9,9,11,11,15,7,5,5,3, - 11,1,3,7,13,7,7,7,3,15,15,11,9,3,9,3,15,13,5,3,3,3,5,9,15,9, - 9,1,5,9,9,15,5,15,7,9,1,9,9,5,11,5,15,15,11,7,7,7,1,1,11,11, - 13,15,3,13,5,1,7,1,11,3,13,15,3,5,3,5,7,3,9,9,5,1,7,11,9,3,5, - 11,13,13,13,9,15,5,7,1,15,11,9,15,15,13,13,13,1,11,9,15,9,5, - 15,5,7,3,11,3,15,7,13,11,7,3,7,13,5,13,15,5,13,9,1,15,11,5,5, - 1,11,3,3,7,1,9,7,15,9,9,3,11,15,7,1,3,1,1,1,9,1,5,15,15,7,5, - 5,7,9,7,15,13,13,11,1,9,11,1,13,1,7,15,15,5,5,1,11,3,9,11,9, - 9,9,1,9,3,5,15,1,1,9,7,3,3,1,9,9,11,9,9,13,13,3,13,11,13,5,1, - 5,5,9,9,3,13,13,9,15,9,11,7,11,9,13,9,1,15,9,7,7,1,7,9,9,15, - 1,11,1,13,13,15,9,13,7,15,3,9,3,1,13,7,5,9,3,1,7,1,1,13,3,3, - 11,1,7,13,15,15,5,7,13,13,15,11,13,1,13,13,3,9,15,15,11,15,9, - 15,1,13,15,1,1,5, - 11,5,1,11,11,5,3,9,1,3,5,13,9,7,7,1, - 9,9,15,7,5,5,15,13,9,7,13,3,13,11,13,7,9,13,13,13,15,9,5,5,3, - 3,3,1,3,15}, - /* [4][*] */ - { 0,0,0,0,0,0, - 9,3,27,15,29,21,23,19,11,25,7,13,17,1, - 25,29,3,31,11,5,23,27,19,21,5,1,17,13,7,15,9,31,25,3,5,23,7, - 3,17,23,3,3,21,25,25,23,11,19,3,11,31,7,9,5,17,23,17,17,25, - 13,11,31,27,19,17,23,7,5,11,19,19,7,13,21,21,7,9,11,1,5,21, - 11,13,25,9,7,7,27,15,25,15,21,17,19,19,21,5,11,3,5,29,31,29, - 5,5,1,31,27,11,13,1,3,7,11,7,3,23,13,31,17,1,27,11,25,1,23, - 29,17,25,7,25,27,17,13,17,23,5,17,5,13,11,21,5,11,5,9,31,19, - 17,9,9,27,21,15,15,1,1,29,5,31,11,17,23,19,21,25,15,11,5,5,1, - 19,19,19,7,13,21,17,17,25,23,19,23,15,13,5,19,25,9,7,3,21,17, - 25,1,27,25,27,25,9,13,3,17,25,23,9,25,9,13,17,17,3,15,7,7,29, - 3,19,29,29,19,29,13,15,25,27,1,3,9,9,13,31,29,31,5,15,29,1, - 19,5,9,19,5,15,3,5,7,15,17,17,23,11,9,23,19,3,17,1,27,9,9,17, - 13,25,29,23,29,11,31,25,21,29,19,27,31,3,5,3,3,13,21,9,29,3, - 17,11,11,9,21,19,7,17,31,25,1,27,5,15,27,29,29,29,25,27,25,3, - 21,17,25,13,15,17,13,23,9,3,11,7,9,9,7,17,7,1, - 27,1,9,5,31,21,25,25,21,11,1,23,19,27, - 15,3,5,23,9,25,7,29,11,9,13,5,11,1,3,31,27,3,17,27,11,13,15, - 29,15,1,15,23,25,13,21,15,3,29,29,5,25,17,11,7,15,5,21,7,31, - 13,11,23,5,7,23,27,21,29,15,7,27,27,19,7,15,27,27,19,19,9,15, - 1,3,29,29,5,27,31,9,1,7,3,19,19,29,9,3,21,31,29,25,1,3,9,27, - 5,27,25,21,11,29,31,27,21,29,17,9,17,13,11,25,15,21,11,19,31, - 3,19,5,3,3,9,13,13,3,29,7,5,9,23,13,21,23,21,31,11,7,7,3,23, - 1,23,5,9,17,21,1,17,29,7,5,17,13,25,17,9,19,9,5,7,21,19,13,9, - 7,3,9,3,15,31,29,29,25,13,9,21,9,31,7,15,5,31,7,15,27,25,19, - 9,9,25,25,23,1,9,7,11,15,19,15,27,17,11,11,31,13,25,25,9,7, - 13,29,19,5,19,31,25,13,25,15,5,9,29,31,9,29,27,25,27,11,17,5, - 17,3,23,15,9,9,17,17,31,11,19,25,13,23,15,25,21,31,19,3,11, - 25,7,15,19,7,5,3,13,13,1,23,5,25,11,25,15,13,21,11,23,29,5, - 17,27,9,19,15,5,29,23,19,1,27,3,23,21,19,27,11,17,13,27,11, - 31,23,5,9,21,31,29,11,21,17,15,7,15,7,9,21,27,25, - 29,11,3,21,13,23,19,27,17,29,25,17,9, - 1,19,23,5,23,1,17,17,13,27,23,7,7,11,13,17,13,11,21,13,23,1, - 27,13,9,7,1,27,29,5,13,25,21,3,31,15,13,3,19,13,1,27,15,17,1, - 3,13,13,13,31,29,27,7,7,21,29,15,17,17,21,19,17,3,15,5,27,27, - 3,31,31,7,21,3,13,11,17,27,25,1,9,7,29,27,21,23,13,25,29,15, - 17,29,9,15,3,21,15,17,17,31,9,9,23,19,25,3,1,11,27,29,1,31, - 29,25,29,1,23,29,25,13,3,31,25,5,5,11,3,21,9,23,7,11,23,11,1, - 1,3,23,25,23,1,23,3,27,9,27,3,23,25,19,29,29,13,27,5,9,29,29, - 13,17,3,23,19,7,13,3,19,23,5,29,29,13,13,5,19,5,17,9,11,11, - 29,27,23,19,17,25,13,1,13,3,11,1,17,29,1,13,17,9,17,21,1,11, - 1,1,25,5,7,29,29,19,19,1,29,13,3,1,31,15,13,3,1,11,19,5,29, - 13,29,23,3,1,31,13,19,17,5,5,1,29,23,3,19,25,19,27,9,27,13, - 15,29,23,13,25,25,17,19,17,15,27,3,25,17,27,3,27,31,23,13,31, - 11,15,7,21,19,27,19,21,29,7,31,13,9,9,7,21,13,11,9,11,29,19, - 11,19,21,5,29,13,7,19,19,27,23,31,1,27,21,7,3,7,11, - 23,13,29,11,31,19,1,5,5,11,5,3,27,5, - 7,11,31,1,27,31,31,23,5,21,27,9,25,3,15,19,1,19,9,5,25,21,15, - 25,29,15,21,11,19,15,3,7,13,11,25,17,1,5,31,13,29,23,9,5,29, - 7,17,27,7,17,31,9,31,9,9,7,21,3,3,3,9,11,21,11,31,9,25,5,1, - 31,13,29,9,29,1,11,19,7,27,13,31,7,31,7,25,23,21,29,11,11,13, - 11,27,1,23,31,21,23,21,19,31,5,31,25,25,19,17,11,25,7,13,1, - 29,17,23,15,7,29,17,13,3,17}, - /* [5][*] */ - { 0,0,0,0,0,0,0,0,0,0,0,0, - 37,33,7,5,11,39,63,59,17,15,23,29,3,21, - 13,31,25,9,49,33,19,29,11,19,27,15,25,63,55,17,63,49,19,41, - 59,3,57,33,49,53,57,57,39,21,7,53,9,55,15,59,19,49,31,3,39,5, - 5,41,9,19,9,57,25,1,15,51,11,19,61,53,29,19,11,9,21,19,43,13, - 13,41,25,31,9,11,19,5,53,37,7,51,45,7,7,61,23,45,7,59,41,1, - 29,61,37,27,47,15,31,35,31,17,51,13,25,45,5,5,33,39,5,47,29, - 35,47,63,45,37,47,59,21,59,33,51,9,27,13,25,43,3,17,21,59,61, - 27,47,57,11,17,39,1,63,21,59,17,13,31,3,31,7,9,27,37,23,31,9, - 45,43,31,63,21,39,51,27,7,53,11,1,59,39,23,49,23,7,55,59,3, - 19,35,13,9,13,15,23,9,7,43,55,3,19,9,27,33,27,49,23,47,19,7, - 11,55,27,35,5,5,55,35,37,9,33,29,47,25,11,47,53,61,59,3,53, - 47,5,19,59,5,47,23,45,53,3,49,61,47,39,29,17,57,5,17,31,23, - 41,39,5,27,7,29,29,33,31,41,31,29,17,29,29,9,9,31,27,53,35,5, - 61,1,49,13,57,29,5,21,43,25,57,49,37,27,11,61,37,49,5,63,63, - 3,45,37,63,21,21,19,27,59,21,45,23,13,15,3,43,63,39,19, - 63,31,41,41,15,43,63,53,1,63,31,7,17, - 11,61,31,51,37,29,59,25,63,59,47,15,27,19,29,45,35,55,39,19, - 43,21,19,13,17,51,37,5,33,35,49,25,45,1,63,47,9,63,15,25,25, - 15,41,13,3,19,51,49,37,25,49,13,53,47,23,35,29,33,21,35,23,3, - 43,31,63,9,1,61,43,3,11,55,11,35,1,63,35,49,19,45,9,57,51,1, - 47,41,9,11,37,19,55,23,55,55,13,7,47,37,11,43,17,3,25,19,55, - 59,37,33,43,1,5,21,5,63,49,61,21,51,15,19,43,47,17,9,53,45, - 11,51,25,11,25,47,47,1,43,29,17,31,15,59,27,63,11,41,51,29,7, - 27,63,31,43,3,29,39,3,59,59,1,53,63,23,63,47,51,23,61,39,47, - 21,39,15,3,9,57,61,39,37,21,51,1,23,43,27,25,11,13,21,43,7, - 11,33,55,1,37,35,27,61,39,5,19,61,61,57,59,21,59,61,57,25,55, - 27,31,41,33,63,19,57,35,13,63,35,17,11,11,49,41,55,5,45,17, - 35,5,31,31,37,17,45,51,1,39,49,55,19,41,13,5,51,5,49,1,21,13, - 17,59,51,11,3,61,1,33,37,33,61,25,27,59,7,49,13,63,3,33,3,15, - 9,13,35,39,11,59,59,1,57,11,5,57,13,31,13,11,55,45,9,55,55, - 19,25,41,23,45,29,63,59,27,39,21,37,7, - 61,49,35,39,9,29,7,25,23,57,5,19,15,33,49,37,25,17,45,29,15, - 25,3,3,49,11,39,15,19,57,39,15,11,3,57,31,55,61,19,5,41,35, - 59,61,39,41,53,53,63,31,9,59,13,35,55,41,49,5,41,25,27,43,5, - 5,43,5,5,17,5,15,27,29,17,9,3,55,31,1,45,45,13,57,17,3,61,15, - 49,15,47,9,37,45,9,51,61,21,33,11,21,63,63,47,57,61,49,9,59, - 19,29,21,23,55,23,43,41,57,9,39,27,41,35,61,29,57,63,21,31, - 59,35,49,3,49,47,49,33,21,19,21,35,11,17,37,23,59,13,37,35, - 55,57,1,29,45,11,1,15,9,33,19,53,43,39,23,7,13,13,1,19,41,55, - 1,13,15,59,55,15,3,57,37,31,17,1,3,21,29,25,55,9,37,33,53,41, - 51,19,57,13,63,43,19,7,13,37,33,19,15,63,51,11,49,23,57,47, - 51,15,53,41,1,15,37,61,11,35,29,33,23,55,11,59,19,61,61,45, - 13,49,13,63,5,61,5,31,17,61,63,13,27,57,1,21,5,11,39,57,51, - 53,39,25,41,39,37,23,31,25,33,17,57,29,27,23,47,41,29,19,47, - 41,25,5,51,43,39,29,7,31,45,51,49,55,17,43,49,45,9,29,3,5,47, - 9,15,19, - 51,45,57,63,9,21,59,3,9,13,45,23,15, - 31,21,15,51,35,9,11,61,23,53,29,51,45,31,29,5,35,29,53,35,17, - 59,55,27,51,59,27,47,15,29,37,7,49,55,5,19,45,29,19,57,33,53, - 45,21,9,3,35,29,43,31,39,3,45,1,41,29,5,59,41,33,35,27,19,13, - 25,27,43,33,35,17,17,23,7,35,15,61,61,53,5,15,23,11,13,43,55, - 47,25,43,15,57,45,1,49,63,57,15,31,31,7,53,27,15,47,23,7,29, - 53,47,9,53,3,25,55,45,63,21,17,23,31,27,27,43,63,55,63,45,51, - 15,27,5,37,43,11,27,5,27,59,21,7,39,27,63,35,47,55,17,17,17, - 3,19,21,13,49,61,39,15}, - /* [6][*] */ - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 13,33,115,41,79,17,29,119,75,73,105,7, - 59,65,21,3,113,61,89,45,107,21,71,79,19,71,61,41,57,121,87, - 119,55,85,121,119,11,23,61,11,35,33,43,107,113,101,29,87,119, - 97,29,17,89,5,127,89,119,117,103,105,41,83,25,41,55,69,117, - 49,127,29,1,99,53,83,15,31,73,115,35,21,89,5,1,91,53,35,95, - 83,19,85,55,51,101,33,41,55,45,95,61,27,37,89,75,57,61,15, - 117,15,21,27,25,27,123,39,109,93,51,21,91,109,107,45,15,93, - 127,3,53,81,79,107,79,87,35,109,73,35,83,107,1,51,7,59,33, - 115,43,111,45,121,105,125,87,101,41,95,75,1,57,117,21,27,67, - 29,53,117,63,1,77,89,115,49,127,15,79,81,29,65,103,33,73,79, - 29,21,113,31,33,107,95,111,59,99,117,63,63,99,39,9,35,63,125, - 99,45,93,33,93,9,105,75,51,115,11,37,17,41,21,43,73,19,93,7, - 95,81,93,79,81,55,9,51,63,45,89,73,19,115,39,47,81,39,5,5,45, - 53,65,49,17,105,13,107,5,5,19,73,59,43,83,97,115,27,1,69,103, - 3,99,103,63,67,25,121,97,77,13,83,103,41,11,27,81,37,33,125, - 71,41,41,59,41,87,123, - 43,101,63,45,39,21,97,15,97,111,21,49, - 13,17,79,91,65,105,75,1,45,67,83,107,125,87,15,81,95,105,65, - 45,59,103,23,103,99,67,99,47,117,71,89,35,53,73,9,115,49,37, - 1,35,9,45,81,19,127,17,17,105,89,49,101,7,37,33,11,95,95,17, - 111,105,41,115,5,69,101,27,27,101,103,53,9,21,43,79,91,65, - 117,87,125,55,45,63,85,83,97,45,83,87,113,93,95,5,17,77,77, - 127,123,45,81,85,121,119,27,85,41,49,15,107,21,51,119,11,87, - 101,115,63,63,37,121,109,7,43,69,19,77,49,71,59,35,7,13,55, - 101,127,103,85,109,29,61,67,21,111,67,23,57,75,71,101,123,41, - 107,101,107,125,27,47,119,41,19,127,33,31,109,7,91,91,39,125, - 105,47,125,123,91,9,103,45,23,117,9,125,73,11,37,61,79,21,5, - 47,117,67,53,85,33,81,121,47,61,51,127,29,65,45,41,95,57,73, - 33,117,61,111,59,123,65,47,105,23,29,107,37,81,67,29,115,119, - 75,73,99,103,7,57,45,61,95,49,101,101,35,47,119,39,67,31,103, - 7,61,127,87,3,35,29,73,95,103,71,75,51,87,57,97,11,105,87,41, - 73,109,69,35,121,39,111,1,77, - 39,47,53,91,3,17,51,83,39,125,85,111, - 21,69,85,29,55,11,117,1,47,17,65,63,47,117,17,115,51,25,33, - 123,123,83,51,113,95,121,51,91,109,43,55,35,55,87,33,37,5,3, - 45,21,105,127,35,17,35,37,97,97,21,77,123,17,89,53,105,75,25, - 125,13,47,21,125,23,55,63,61,5,17,93,57,121,69,73,93,121,105, - 75,91,67,95,75,9,69,97,99,93,11,53,19,73,5,33,79,107,65,69, - 79,125,25,93,55,61,17,117,69,97,87,111,37,93,59,79,95,53,115, - 53,85,85,65,59,23,75,21,67,27,99,79,27,3,95,27,69,19,75,47, - 59,41,85,77,99,55,49,93,93,119,51,125,63,13,15,45,61,19,105, - 115,17,83,7,7,11,61,37,63,89,95,119,113,67,123,91,33,37,99, - 43,11,33,65,81,79,81,107,63,63,55,89,91,25,93,101,27,55,75, - 121,79,43,125,73,27,109,35,21,71,113,89,59,95,41,45,113,119, - 113,39,59,73,15,13,59,67,121,27,7,105,15,59,59,35,91,89,23, - 125,97,53,41,91,111,29,31,3,103,61,71,35,7,119,29,45,49,111, - 41,109,59,125,13,27,19,79,9,75,83,81,33,91,109,33,29,107,111, - 101,107,109,65,59,43,37, - 1,9,15,109,37,111,113,119,79,73,65, - 71,93,17,101,87,97,43,23,75,109,41,49,53,31,97,105,109,119, - 51,9,53,113,97,73,89,79,49,61,105,13,99,53,71,7,87,21,101,5, - 71,31,123,121,121,73,79,115,13,39,101,19,37,51,83,97,55,81, - 91,127,105,89,63,47,49,75,37,77,15,49,107,23,23,35,19,69,17, - 59,63,73,29,125,61,65,95,101,81,57,69,83,37,11,37,95,1,73,27, - 29,57,7,65,83,99,69,19,103,43,95,25,19,103,41,125,97,71,105, - 83,83,61,39,9,45,117,63,31,5,117,67,125,41,117,43,77,97,15, - 29,5,59,25,63,87,39,39,77,85,37,81,73,89,29,125,109,21,23, - 119,105,43,93,97,15,125,29,51,69,37,45,31,75,109,119,53,5, - 101,125,121,35,29,7,63,17,63,13,69,15,105,51,127,105,9,57,95, - 59,109,35,49,23,33,107,55,33,57,79,73,69,59,107,55,11,63,95, - 103,23,125,91,31,91,51,65,61,75,69,107,65,101,59,35,15}, - /* [7][*] */ - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 7,23,39,217,141,27,53,181,169,35,15, - 207,45,247,185,117,41,81,223,151,81,189,61,95,185,23,73,113, - 239,85,9,201,83,53,183,203,91,149,101,13,111,239,3,205,253, - 247,121,189,169,179,197,175,217,249,195,95,63,19,7,5,75,217, - 245,111,189,165,169,141,221,249,159,253,207,249,219,23,49, - 127,237,5,25,177,37,103,65,167,81,87,119,45,79,143,57,79,187, - 143,183,75,97,211,149,175,37,135,189,225,241,63,33,43,13,73, - 213,57,239,183,117,21,29,115,43,205,223,15,3,159,51,101,127, - 99,239,171,113,171,119,189,245,201,27,185,229,105,153,189,33, - 35,137,77,97,17,181,55,197,201,155,37,197,137,223,25,179,91, - 23,235,53,253,49,181,249,53,173,97,247,67,115,103,159,239,69, - 173,217,95,221,247,97,91,123,223,213,129,181,87,239,85,89, - 249,141,39,57,249,71,101,159,33,137,189,71,253,205,171,13, - 249,109,131,199,189,179,31,99,113,41,173,23,189,197,3,135,9, - 95,195,27,183,1,123,73,53,99,197,59,27,101,55,193,31,61,119, - 11,7,255,233,53,157,193,97,83,65,81,239,167,69,71,109, - 97,137,71,193,189,115,79,205,37,227, - 53,33,91,229,245,105,77,229,161,103,93,13,161,229,223,69,15, - 25,23,233,93,25,217,247,61,75,27,9,223,213,55,197,145,89,199, - 41,201,5,149,35,119,183,53,11,13,3,179,229,43,55,187,233,47, - 133,91,47,71,93,105,145,45,255,221,115,175,19,129,5,209,197, - 57,177,115,187,119,77,211,111,33,113,23,87,137,41,7,83,43, - 121,145,5,219,27,11,111,207,55,97,63,229,53,33,149,23,187, - 153,91,193,183,59,211,93,139,59,179,163,209,77,39,111,79,229, - 85,237,199,137,147,25,73,121,129,83,87,93,205,167,53,107,229, - 213,95,219,109,175,13,209,97,61,147,19,13,123,73,35,141,81, - 19,171,255,111,107,233,113,133,89,9,231,95,69,33,1,253,219, - 253,247,129,11,251,221,153,35,103,239,7,27,235,181,5,207,53, - 149,155,225,165,137,155,201,97,245,203,47,39,35,105,239,49, - 15,253,7,237,213,55,87,199,27,175,49,41,229,85,3,149,179,129, - 185,249,197,15,97,197,139,203,63,33,251,217,199,199,99,249, - 33,229,177,13,209,147,97,31,125,177,137, - 187,11,91,223,29,169,231,59,31,163,41, - 57,87,247,25,127,101,207,187,73,61,105,27,91,171,243,33,3,1, - 21,229,93,71,61,37,183,65,211,53,11,151,165,47,5,129,79,101, - 147,169,181,19,95,77,139,197,219,97,239,183,143,9,13,209,23, - 215,53,137,203,19,151,171,133,219,231,3,15,253,225,33,111, - 183,213,169,119,111,15,201,123,121,225,113,113,225,161,165,1, - 139,55,3,93,217,193,97,29,69,231,161,93,69,143,137,9,87,183, - 113,183,73,215,137,89,251,163,41,227,145,57,81,57,11,135,145, - 161,175,159,25,55,167,157,211,97,247,249,23,129,159,71,197, - 127,141,219,5,233,131,217,101,131,33,157,173,69,207,239,81, - 205,11,41,169,65,193,77,201,173,1,221,157,1,15,113,147,137, - 205,225,73,45,49,149,113,253,99,17,119,105,117,129,243,75, - 203,53,29,247,35,247,171,31,199,213,29,251,7,251,187,91,11, - 149,13,205,37,249,137,139,9,7,113,183,205,187,39,3,79,155, - 227,89,185,51,127,63,83,41,133,183,181,127,19,255,219,59,251, - 3,187,57,217,115,217,229,181,185,149,83,115,11, - 123,19,109,165,103,123,219,129,155, - 207,177,9,49,181,231,33,233,67,155,41,9,95,123,65,117,249,85, - 169,129,241,173,251,225,147,165,69,81,239,95,23,83,227,249, - 143,171,193,9,21,57,73,97,57,29,239,151,159,191,47,51,1,223, - 251,251,151,41,119,127,131,33,209,123,53,241,25,31,183,107, - 25,115,39,11,213,239,219,109,185,35,133,123,185,27,55,245,61, - 75,205,213,169,163,63,55,49,83,195,51,31,41,15,203,41,63,127, - 161,5,143,7,199,251,95,75,101,15,43,237,197,117,167,155,21, - 83,205,255,49,101,213,237,135,135,21,73,93,115,7,85,223,237, - 79,89,5,57,239,67,65,201,155,71,85,195,89,181,119,135,147, - 237,173,41,155,67,113,111,21,183,23,103,207,253,69,219,205, - 195,43,197,229,139,177,129,69,97,201,163,189,11,99,91,253, - 239,91,145,19,179,231,121,7,225,237,125,191,119,59,175,237, - 131,79,43,45,205,199,251,153,207,37,179,113,255,107,217,61,7, - 181,247,31,13,113,145,107,233,233,43,79,23,169,137,129,183, - 53,91,55,103,223,87,177,157,79,213,139, - 183,231,205,143,129,243,205,93,59, - 15,89,9,11,47,133,227,75,9,91,19,171,163,79,7,103,5,119,155, - 75,11,71,95,17,13,243,207,187}, - /* [8][*] */ - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 235,307,495,417,57,151,19,119,375,451, - 55,449,501,53,185,317,17,21,487,13,347,393,15,391,307,189, - 381,71,163,99,467,167,433,337,257,179,47,385,23,117,369,425, - 207,433,301,147,333,85,221,423,49,3,43,229,227,201,383,281, - 229,207,21,343,251,397,173,507,421,443,399,53,345,77,385,317, - 155,187,269,501,19,169,235,415,61,247,183,5,257,401,451,95, - 455,49,489,75,459,377,87,463,155,233,115,429,211,419,143,487, - 195,209,461,193,157,193,363,181,271,445,381,231,135,327,403, - 171,197,181,343,113,313,393,311,415,267,247,425,233,289,55, - 39,247,327,141,5,189,183,27,337,341,327,87,429,357,265,251, - 437,201,29,339,257,377,17,53,327,47,375,393,369,403,125,429, - 257,157,217,85,267,117,337,447,219,501,41,41,193,509,131,207, - 505,421,149,111,177,167,223,291,91,29,305,151,177,337,183, - 361,435,307,507,77,181,507,315,145,423,71,103,493,271,469, - 339,237,437,483,31,219,61,131,391,233,219,69,57,459,225,421, - 7,461,111,451,277,185,193,125,251,199,73,71,7,409,417,149, - 193,53,437,29,467,229,31,35,75,105, - 503,75,317,401,367,131,365,441,433,93,377,405,465,259,283, - 443,143,445,3,461,329,309,77,323,155,347,45,381,315,463,207, - 321,157,109,479,313,345,167,439,307,235,473,79,101,245,19, - 381,251,35,25,107,187,115,113,321,115,445,61,77,293,405,13, - 53,17,171,299,41,79,3,485,331,13,257,59,201,497,81,451,199, - 171,81,253,365,75,451,149,483,81,453,469,485,305,163,401,15, - 91,3,129,35,239,355,211,387,101,299,67,375,405,357,267,363, - 79,83,437,457,39,97,473,289,179,57,23,49,79,71,341,287,95, - 229,271,475,49,241,261,495,353,381,13,291,37,251,105,399,81, - 89,265,507,205,145,331,129,119,503,249,1,289,463,163,443,63, - 123,361,261,49,429,137,355,175,507,59,277,391,25,185,381,197, - 39,5,429,119,247,177,329,465,421,271,467,151,45,429,137,471, - 11,17,409,347,199,463,177,11,51,361,95,497,163,351,127,395, - 511,327,353,49,105,151,321,331,329,509,107,109,303,467,287, - 161,45,385,289,363,331,265,407,37,433,315,343,63,51,185,71, - 27,267, - 503,239,293,245,281,297,75,461,371, - 129,189,189,339,287,111,111,379,93,27,185,347,337,247,507, - 161,231,43,499,73,327,263,331,249,493,37,25,115,3,167,197, - 127,357,497,103,125,191,165,55,101,95,79,351,341,43,125,135, - 173,289,373,133,421,241,281,213,177,363,151,227,145,363,239, - 431,81,397,241,67,291,255,405,421,399,75,399,105,329,41,425, - 7,283,375,475,427,277,209,411,3,137,195,289,509,121,55,147, - 275,251,19,129,285,415,487,491,193,219,403,23,97,65,285,75, - 21,373,261,339,239,495,415,333,107,435,297,213,149,463,199, - 323,45,19,301,121,499,187,229,63,425,99,281,35,125,349,87, - 101,59,195,511,355,73,263,243,101,165,141,11,389,219,187,449, - 447,393,477,305,221,51,355,209,499,479,265,377,145,411,173, - 11,433,483,135,385,341,89,209,391,33,395,319,451,119,341,227, - 375,61,331,493,411,293,47,203,375,167,395,155,5,237,361,489, - 127,21,345,101,371,233,431,109,119,277,125,263,73,135,123,83, - 123,405,69,75,287,401,23,283,393,41,379,431,11,475,505,19, - 365,265,271, - 499,489,443,165,91,83,291,319,199, - 107,245,389,143,137,89,125,281,381,215,131,299,249,375,455, - 43,73,281,217,297,229,431,357,81,357,171,451,481,13,387,491, - 489,439,385,487,177,393,33,71,375,443,129,407,395,127,65,333, - 309,119,197,435,497,373,71,379,509,387,159,265,477,463,449, - 47,353,249,335,505,89,141,55,235,187,87,363,93,363,101,67, - 215,321,331,305,261,411,491,479,65,307,469,415,131,315,487, - 83,455,19,113,163,503,99,499,251,239,81,167,391,255,317,363, - 359,395,419,307,251,267,171,461,183,465,165,163,293,477,223, - 403,389,97,335,357,297,19,469,501,249,85,213,311,265,379,297, - 283,393,449,463,289,159,289,499,407,129,137,221,43,89,403, - 271,75,83,445,453,389,149,143,423,499,317,445,157,137,453, - 163,87,23,391,119,427,323,173,89,259,377,511,249,31,363,229, - 353,329,493,427,57,205,389,91,83,13,219,439,45,35,371,441,17, - 267,501,53,25,333,17,201,475,257,417,345,381,377,55,403,77, - 389,347,363,211,413,419,5,167,219,201,285,425,11,77,269,489, - 281,403,79, - 425,125,81,331,437,271,397,299,475, - 271,249,413,233,261,495,171,69,27,409,21,421,367,81,483,255, - 15,219,365,497,181,75,431,99,325,407,229,281,63,83,493,5,113, - 15,271,37,87,451,299,83,451,311,441,47,455,47,253,13,109,369, - 347,11,409,275,63,441,15}, - /* [9][*] */ - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 519,307,931,1023,517,771,151,1023, - 539,725,45,927,707,29,125,371,275,279,817,389,453,989,1015, - 29,169,743,99,923,981,181,693,309,227,111,219,897,377,425, - 609,227,19,221,143,581,147,919,127,725,793,289,411,835,921, - 957,443,349,813,5,105,457,393,539,101,197,697,27,343,515,69, - 485,383,855,693,133,87,743,747,475,87,469,763,721,345,479, - 965,527,121,271,353,467,177,245,627,113,357,7,691,725,355, - 889,635,737,429,545,925,357,873,187,351,677,999,921,477,233, - 765,495,81,953,479,89,173,473,131,961,411,291,967,65,511,13, - 805,945,369,827,295,163,835,259,207,331,29,315,999,133,967, - 41,117,677,471,717,881,755,351,723,259,879,455,721,289,149, - 199,805,987,851,423,597,129,11,733,549,153,285,451,559,377, - 109,357,143,693,615,677,701,475,767,85,229,509,547,151,389, - 711,785,657,319,509,99,1007,775,359,697,677,85,497,105,615, - 891,71,449,835,609,377,693,665,627,215,911,503,729,131,19, - 895,199,161,239,633,1013,537,255,23,149,679,1021,595,199,557, - 659,251,829,727,439,495,647,223, - 949,625,87,481,85,799,917,769,949, - 739,115,499,945,547,225,1015,469,737,495,353,103,17,665,639, - 525,75,447,185,43,729,577,863,735,317,99,17,477,893,537,519, - 1017,375,297,325,999,353,343,729,135,489,859,267,141,831,141, - 893,249,807,53,613,131,547,977,131,999,175,31,341,739,467, - 675,241,645,247,391,583,183,973,433,367,131,467,571,309,385, - 977,111,917,935,473,345,411,313,97,149,959,841,839,669,431, - 51,41,301,247,1015,377,329,945,269,67,979,581,643,823,557,91, - 405,117,801,509,347,893,303,227,783,555,867,99,703,111,797, - 873,541,919,513,343,319,517,135,871,917,285,663,301,15,763, - 89,323,757,317,807,309,1013,345,499,279,711,915,411,281,193, - 739,365,315,375,809,469,487,621,857,975,537,939,585,129,625, - 447,129,1017,133,83,3,415,661,53,115,903,49,79,55,385,261, - 345,297,199,385,617,25,515,275,849,401,471,377,661,535,505, - 939,465,225,929,219,955,659,441,117,527,427,515,287,191,33, - 389,197,825,63,417,949,35,571,9,131,609,439,95,19,569,893, - 451,397,971,801, - 125,471,187,257,67,949,621,453,411, - 621,955,309,783,893,597,377,753,145,637,941,593,317,555,375, - 575,175,403,571,555,109,377,931,499,649,653,329,279,271,647, - 721,665,429,957,803,767,425,477,995,105,495,575,687,385,227, - 923,563,723,481,717,111,633,113,369,955,253,321,409,909,367, - 33,967,453,863,449,539,781,911,113,7,219,725,1015,971,1021, - 525,785,873,191,893,297,507,215,21,153,645,913,755,371,881, - 113,903,225,49,587,201,927,429,599,513,97,319,331,833,325, - 887,139,927,399,163,307,803,169,1019,869,537,907,479,335,697, - 479,353,769,787,1023,855,493,883,521,735,297,1011,991,879, - 855,591,415,917,375,453,553,189,841,339,211,601,57,765,745, - 621,209,875,639,7,595,971,263,1009,201,23,77,621,33,535,963, - 661,523,263,917,103,623,231,47,301,549,337,675,189,357,1005, - 789,189,319,721,1005,525,675,539,191,813,917,51,167,415,579, - 755,605,721,837,529,31,327,799,961,279,409,847,649,241,285, - 545,407,161,591,73,313,811,17,663,269,261,37,783,127,917,231, - 577,975,793, - 921,343,751,139,221,79,817,393,545, - 11,781,71,1,699,767,917,9,107,341,587,903,965,599,507,843, - 739,579,397,397,325,775,565,925,75,55,979,931,93,957,857,753, - 965,795,67,5,87,909,97,995,271,875,671,613,33,351,69,811,669, - 729,401,647,241,435,447,721,271,745,53,775,99,343,451,427, - 593,339,845,243,345,17,573,421,517,971,499,435,769,75,203, - 793,985,343,955,735,523,659,703,303,421,951,405,631,825,735, - 433,841,485,49,749,107,669,211,497,143,99,57,277,969,107,397, - 563,551,447,381,187,57,405,731,769,923,955,915,737,595,341, - 253,823,197,321,315,181,885,497,159,571,981,899,785,947,217, - 217,135,753,623,565,717,903,581,955,621,361,869,87,943,907, - 853,353,335,197,771,433,743,195,91,1023,63,301,647,205,485, - 927,1003,987,359,577,147,141,1017,701,273,89,589,487,859,343, - 91,847,341,173,287,1003,289,639,983,685,697,35,701,645,911, - 501,705,873,763,745,657,559,699,315,347,429,197,165,955,859, - 167,303,833,531,473,635,641,195,589,821,205,3,635,371,891, - 249,123, - 77,623,993,401,525,427,71,655,951, - 357,851,899,535,493,323,1003,343,515,859,1017,5,423,315,1011, - 703,41,777,163,95,831,79,975,235,633,723,297,589,317,679,981, - 195,399,1003,121,501,155}, - /* [10][*] */ - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 7,2011,1001,49,825,415,1441,383,1581, - 623,1621,1319,1387,619,839,217,75,1955,505,281,1629,1379,53, - 1111,1399,301,209,49,155,1647,631,129,1569,335,67,1955,1611, - 2021,1305,121,37,877,835,1457,669,1405,935,1735,665,551,789, - 1543,1267,1027,1,1911,163,1929,67,1975,1681,1413,191,1711, - 1307,401,725,1229,1403,1609,2035,917,921,1789,41,2003,187,67, - 1635,717,1449,277,1903,1179,363,1211,1231,647,1261,1029,1485, - 1309,1149,317,1335,171,243,271,1055,1601,1129,1653,205,1463, - 1681,1621,197,951,573,1697,1265,1321,1805,1235,1853,1307,945, - 1197,1411,833,273,1517,1747,1095,1345,869,57,1383,221,1713, - 335,1751,1141,839,523,1861,1105,389,1177,1877,805,93,1591, - 423,1835,99,1781,1515,1909,1011,303,385,1635,357,973,1781, - 1707,1363,1053,649,1469,623,1429,1241,1151,1055,503,921,3, - 349,1149,293,45,303,877,1565,1583,1001,663,1535,395,1141, - 1481,1797,643,1507,465,2027,1695,367,937,719,545,1991,83,819, - 239,1791,1461,1647,1501,1161,1629,139,1595,1921,1267,1415, - 509,347,777,1083,363,269,1015, - 1809,1105,1429,1471,2019,381,2025, - 1223,827,1733,887,1321,803,1951,1297,1995,833,1107,1135,1181, - 1251,983,1389,1565,273,137,71,735,1005,933,67,1471,551,457, - 1667,1729,919,285,1629,1815,653,1919,1039,531,393,1411,359, - 221,699,1485,471,1357,1715,595,1677,153,1903,1281,215,781, - 543,293,1807,965,1695,443,1985,321,879,1227,1915,839,1945, - 1993,1165,51,557,723,1491,817,1237,947,1215,1911,1225,1965, - 1889,1503,1177,73,1767,303,177,1897,1401,321,921,217,1779, - 327,1889,333,615,1665,1825,1639,237,1205,361,129,1655,983, - 1089,1171,401,677,643,749,303,1407,1873,1579,1491,1393,1247, - 789,763,49,5,1607,1891,735,1557,1909,1765,1777,1127,813,695, - 97,731,1503,1751,333,769,865,693,377,1919,957,1359,1627,1039, - 1783,1065,1665,1917,1947,991,1997,841,459,221,327,1595,1881, - 1269,1007,129,1413,475,1105,791,1983,1359,503,691,659,691, - 343,1375,1919,263,1373,603,1383,297,781,145,285,767,1739, - 1715,715,317,1333,85,831,1615,81,1667,1467,1457,1453,1825, - 109,387,1207,2039,213,1351,1329,1173, - 57,1769,951,183,23,451,1155,1551, - 2037,811,635,1671,1451,863,1499,1673,363,1029,1077,1525,277, - 1023,655,665,1869,1255,965,277,1601,329,1603,1901,395,65, - 1307,2029,21,1321,543,1569,1185,1905,1701,413,2041,1697,725, - 1417,1847,411,211,915,1891,17,1877,1699,687,1089,1973,1809, - 851,1495,1257,63,1323,1307,609,881,1543,177,617,1505,1747, - 1537,925,183,77,1723,1877,1703,397,459,521,257,1177,389,1947, - 1553,1583,1831,261,485,289,1281,1543,1591,1123,573,821,1065, - 1933,1373,2005,905,207,173,1573,1597,573,1883,1795,1499,1743, - 553,335,333,1645,791,871,1157,969,557,141,223,1129,1685,423, - 1069,391,99,95,1847,531,1859,1833,1833,341,237,1997,1799,409, - 431,1917,363,335,1039,1085,1657,1975,1527,1111,659,389,899, - 595,1439,1861,1979,1569,1087,1009,165,1895,1481,1583,29,1193, - 1673,1075,301,1081,1377,1747,1497,1103,1789,887,739,1577,313, - 1367,1299,1801,1131,1837,73,1865,1065,843,635,55,1655,913, - 1037,223,1871,1161,461,479,511,1721,1107,389,151,35,375,1099, - 937,1185,1701,769,639,1633, - 1609,379,1613,2031,685,289,975,671, - 1599,1447,871,647,99,139,1427,959,89,117,841,891,1959,223, - 1697,1145,499,1435,1809,1413,1445,1675,171,1073,1349,1545, - 2039,1027,1563,859,215,1673,1919,1633,779,411,1845,1477,1489, - 447,1545,351,1989,495,183,1639,1385,1805,1097,1249,1431,1571, - 591,697,1509,709,31,1563,165,513,1425,1299,1081,145,1841, - 1211,941,609,845,1169,1865,1593,347,293,1277,157,211,93,1679, - 1799,527,41,473,563,187,1525,575,1579,857,703,1211,647,709, - 981,285,697,163,981,153,1515,47,1553,599,225,1147,381,135, - 821,1965,609,1033,983,503,1117,327,453,2005,1257,343,1649, - 1199,599,1877,569,695,1587,1475,187,973,233,511,51,1083,665, - 1321,531,1875,1939,859,1507,1979,1203,1965,737,921,1565,1943, - 819,223,365,167,1705,413,1577,745,1573,655,1633,1003,91,1123, - 477,1741,1663,35,715,37,1513,815,941,1379,263,1831,1735,1111, - 1449,353,1941,1655,1349,877,285,1723,125,1753,985,723,175, - 439,791,1051,1261,717,1555,1757,1777,577,1583,1957,873,331, - 1163,313,1,1963,963,1905,821, - 1677,185,709,545,1723,215,1885, - 1249,583,1803,839,885,485,413,1767,425,129,1035,329,1263, - 1881,1779,1565,359,367,453,707,1419,831,1889,887,1871,1869, - 747,223,1547,1799,433,1441,553,2021,1303,1505,1735,1619,1065, - 1161,2047,347,867,881,1447,329,781,1065,219,589,645,1257, - 1833,749,1841,1733,1179,1191,1025,1639,1955,1423,1685,1711, - 493,549,783,1653,397,895,233,759,1505,677,1449,1573,1297, - 1821,1691,791,289,1187,867,1535,575,183}, - /* [11][*] */ - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 3915,97,3047,937,2897,953,127,1201, - 3819,193,2053,3061,3759,1553,2007,2493,603,3343,3751,1059, - 783,1789,1589,283,1093,3919,2747,277,2605,2169,2905,721,4069, - 233,261,1137,3993,3619,2881,1275,3865,1299,3757,1193,733,993, - 1153,2945,3163,3179,437,271,3493,3971,1005,2615,2253,1131, - 585,2775,2171,2383,2937,2447,1745,663,1515,3767,2709,1767, - 3185,3017,2815,1829,87,3341,793,2627,2169,1875,3745,367,3783, - 783,827,3253,2639,2955,3539,1579,2109,379,2939,3019,1999, - 2253,2911,3733,481,1767,1055,4019,4085,105,1829,2097,2379, - 1567,2713,737,3423,3941,2659,3961,1755,3613,1937,1559,2287, - 2743,67,2859,325,2601,1149,3259,2403,3947,2011,175,3389,3915, - 1315,2447,141,359,3609,3933,729,2051,1755,2149,2107,1741, - 1051,3681,471,1055,845,257,1559,1061,2803,2219,1315,1369, - 3211,4027,105,11,1077,2857,337,3553,3503,3917,2665,3823,3403, - 3711,2085,1103,1641,701,4095,2883,1435,653,2363,1597,767,869, - 1825,1117,1297,501,505,149,873,2673,551,1499,2793,3277,2143, - 3663,533,3991,575,1877,1009,3929,473,3009,2595,3249,675,3593, - 2453,1567,973,595,1335,1715,589,85, - 2265,3069,461,1659,2627,1307,1731,1501,1699,3545,3803,2157, - 453,2813,2047,2999,3841,2361,1079,573,69,1363,1597,3427,2899, - 2771,1327,1117,1523,3521,2393,2537,1979,3179,683,2453,453, - 1227,779,671,3483,2135,3139,3381,3945,57,1541,3405,3381,2371, - 2879,1985,987,3017,3031,3839,1401,3749,2977,681,1175,1519, - 3355,907,117,771,3741,3337,1743,1227,3335,2755,1909,3603, - 2397,653,87,2025,2617,3257,287,3051,3809,897,2215,63,2043, - 1757,3671,297,3131,1305,293,3865,3173,3397,2269,3673,717, - 3041,3341,3595,3819,2871,3973,1129,513,871,1485,3977,2473, - 1171,1143,3063,3547,2183,3993,133,2529,2699,233,2355,231, - 3241,611,1309,3829,1839,1495,301,1169,1613,2673,243,3601, - 3669,2813,2671,2679,3463,2477,1795,617,2317,1855,1057,1703, - 1761,2515,801,1205,1311,473,3963,697,1221,251,381,3887,1761, - 3093,3721,2079,4085,379,3601,3845,433,1781,29,1897,1599,2163, - 75,3475,3957,1641,3911,2959,2833,1279,1099,403,799,2183,2699, - 1711,2037,727,289,1785,1575,3633,2367,1261,3953,1735,171, - 1959, - 2867,859,2951,3211,15,1279,1323,599, - 1651,3951,1011,315,3513,3351,1725,3793,2399,287,4017,3571, - 1007,541,3115,429,1585,1285,755,1211,3047,915,3611,2697,2129, - 3669,81,3939,2437,915,779,3567,3701,2479,3807,1893,3927,2619, - 2543,3633,2007,3857,3837,487,1769,3759,3105,2727,3155,2479, - 1341,1657,2767,2541,577,2105,799,17,2871,3637,953,65,69,2897, - 3841,3559,4067,2335,3409,1087,425,2813,1705,1701,1237,821, - 1375,3673,2693,3925,1541,1871,2285,847,4035,1101,2029,855, - 2733,2503,121,2855,1069,3463,3505,1539,607,1349,575,2301, - 2321,1101,333,291,2171,4085,2173,2541,1195,925,4039,1379,699, - 1979,275,953,1755,1643,325,101,2263,3329,3673,3413,1977,2727, - 2313,1419,887,609,2475,591,2613,2081,3805,3435,2409,111,3557, - 3607,903,231,3059,473,2959,2925,3861,2043,3887,351,2865,369, - 1377,2639,1261,3625,3279,2201,2949,3049,449,1297,897,1891, - 411,2773,749,2753,1825,853,2775,3547,3923,3923,987,3723,2189, - 3877,3577,297,2763,1845,3083,2951,483,2169,3985,245,3655, - 3441,1023,235,835,3693,3585,327,1003,543,3059,2637, - 2923,87,3617,1031,1043,903,2913, - 2177,2641,3279,389,2009,525,4085,3299,987,2409,813,2683,373, - 2695,3775,2375,1119,2791,223,325,587,1379,2877,2867,3793,655, - 831,3425,1663,1681,2657,1865,3943,2977,1979,2271,3247,1267, - 1747,811,159,429,2001,1195,3065,553,1499,3529,1081,2877,3077, - 845,1793,2409,3995,2559,4081,1195,2955,1117,1409,785,287, - 1521,1607,85,3055,3123,2533,2329,3477,799,3683,3715,337,3139, - 3311,431,3511,2299,365,2941,3067,1331,1081,1097,2853,2299, - 495,1745,749,3819,619,1059,3559,183,3743,723,949,3501,733, - 2599,3983,3961,911,1899,985,2493,1795,653,157,433,2361,3093, - 3119,3679,2367,1701,1445,1321,2397,1241,3305,3985,2349,4067, - 3805,3073,2837,1567,3783,451,2441,1181,487,543,1201,3735, - 2517,733,1535,2175,3613,3019}, - /* [12][*] */ - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 2319,653,1379,1675,1951,7075,2087, - 7147,1427,893,171,2019,7235,5697,3615,1961,7517,6849,2893, - 1883,2863,2173,4543,73,381,3893,6045,1643,7669,1027,1549, - 3983,1985,6589,7497,2745,2375,7047,1117,1171,1975,5199,3915, - 3695,8113,4303,3773,7705,6855,1675,2245,2817,1719,569,1021, - 2077,5945,1833,2631,4851,6371,833,7987,331,1899,8093,6719, - 6903,5903,5657,5007,2689,6637,2675,1645,1819,689,6709,7717, - 6295,7013,7695,3705,7069,2621,3631,6571,6259,7261,3397,7645, - 1115,4753,2047,7579,2271,5403,4911,7629,4225,1209,6955,6951, - 1829,5579,5231,1783,4285,7425,599,5785,3275,5643,2263,657, - 6769,6261,1251,3249,4447,4111,3991,1215,131,4397,3487,7585, - 5565,7199,3573,7105,7409,1671,949,3889,5971,3333,225,3647, - 5403,3409,7459,6879,5789,6567,5581,4919,1927,4407,8085,4691, - 611,3005,591,753,589,171,5729,5891,1033,3049,6567,5257,8003, - 1757,4489,4923,6379,5171,1757,689,3081,1389,4113,455,2761, - 847,7575,5829,633,6629,1103,7635,803,6175,6587,2711,3879,67, - 1179,4761,7281,1557,3379,2459,4273,4127,7147,35, - 3549,395,3735,5787,4179,5889,5057, - 7473,4713,2133,2897,1841,2125,1029,1695,6523,1143,5105,7133, - 3351,2775,3971,4503,7589,5155,4305,1641,4717,2427,5617,1267, - 399,5831,4305,4241,3395,3045,4899,1713,171,411,7099,5473, - 5209,1195,1077,1309,2953,7343,4887,3229,6759,6721,6775,675, - 4039,2493,7511,3269,4199,6625,7943,2013,4145,667,513,2303, - 4591,7941,2741,987,8061,3161,5951,1431,831,5559,7405,1357, - 4319,4235,5421,2559,4415,2439,823,1725,6219,4903,6699,5451, - 349,7703,2927,7809,6179,1417,5987,3017,4983,3479,4525,4643, - 4911,227,5475,2287,5581,6817,1937,1421,4415,7977,1789,3907, - 6815,6789,6003,5609,4507,337,7427,7943,3075,6427,1019,7121, - 4763,81,3587,2929,1795,8067,2415,1265,4025,5599,4771,3025, - 2313,6129,7611,6881,5253,4413,7869,105,3173,1629,2537,1023, - 4409,7209,4413,7107,7469,33,1955,2881,5167,6451,4211,179, - 5573,7879,3387,7759,5455,7157,1891,5683,5689,6535,3109,6555, - 6873,1249,4251,6437,49,2745,1201,7327,4179,6783,623,2779, - 5963,2585,6927,5333,4033,285,7467,4443,4917,3, - 4319,5517,3449,813,5499,2515,5771, - 3357,2073,4395,4925,2643,7215,5817,1199,1597,1619,7535,4833, - 609,4797,8171,6847,793,6757,8165,3371,2431,5235,4739,7703, - 7223,6525,5891,5605,4433,3533,5267,5125,5037,225,6717,1121, - 5741,2013,4327,4839,569,5227,7677,4315,2391,5551,859,3627, - 6377,3903,4311,6527,7573,4905,7731,1909,1555,3279,1949,1887, - 6675,5509,2033,5473,3539,5033,5935,6095,4761,1771,1271,1717, - 4415,5083,6277,3147,7695,2461,4783,4539,5833,5583,651,1419, - 2605,5511,3913,5795,2333,2329,4431,3725,6069,2699,7055,6879, - 1017,3121,2547,4603,2385,6915,6103,5669,7833,2001,4287,6619, - 955,2761,5711,6291,3415,3909,2841,5627,4939,7671,6059,6275, - 6517,1931,4583,7301,1267,7509,1435,2169,6939,3515,2985,2787, - 2123,1969,3307,353,4359,7059,5273,5873,6657,6765,6229,3179, - 1583,6237,2155,371,273,7491,3309,6805,3015,6831,7819,713, - 4747,3935,4109,1311,709,3089,7059,4247,2989,1509,4919,1841, - 3045,3821,6929,4655,1333,6429,6649,2131,5265,1051,261,8057, - 3379,2179,1993,5655,3063,6381, - 3587,7417,1579,1541,2107,5085,2873, - 6141,955,3537,2157,841,1999,1465,5171,5651,1535,7235,4349, - 1263,1453,1005,6893,2919,1947,1635,3963,397,969,4569,655, - 6737,2995,7235,7713,973,4821,2377,1673,1,6541} - }; - - return sobol_minit[degree][dim]; - } - -}; - -} // namespace sbl - // sobol_lattice sets up the random-number generator to produce a Sobol // sequence of at most max dims-dimensional quasi-random vectors. @@ -951,12 +24,13 @@ struct sobol_tables // http://doi.acm.org/10.1145/42288.214372 -template +template struct sobol_lattice { - typedef IntType value_type; + typedef UIntType value_type; - BOOST_STATIC_CONSTANT(int, bit_count = std::numeric_limits::digits); + BOOST_STATIC_ASSERT(w > 0u); + BOOST_STATIC_CONSTANT(unsigned, bit_count = w); // default copy c-tor is fine @@ -967,151 +41,190 @@ struct sobol_lattice void resize(std::size_t dimension) { - if (dimension > sbl::sobol_tables::max_dimension) - { - throw std::invalid_argument("The Sobol quasi-random number generator only supports up to " - BOOST_PP_STRINGIZE(BOOST_RANDOM_SOBOL_MAX_DIMENSION) " dimensions."); - } + dimension_assert("Sobol", dimension, SobolTables::max_dimension); // Initialize the bit array - bits.resize(boost::extents[bit_count][dimension]); + bits.resize(bit_count * dimension); // Initialize direction table in dimension 0 - for (int k = 0; k < bit_count; ++k) - bits[k][0] = static_cast(1); + for (unsigned k = 0; k != bit_count; ++k) + bits[dimension*k] = static_cast(1); // Initialize in remaining dimensions. for (std::size_t dim = 1; dim < dimension; ++dim) { - const int poly = sbl::sobol_tables::polynomial(dim-1); - if (static_cast(poly) > - static_cast(std::numeric_limits::max())) { - boost::throw_exception( std::range_error("sobol: polynomial value outside the given IntType range") ); + const unsigned int poly = SobolTables::polynomial(dim-1); + if (poly > std::numeric_limits::max()) { + boost::throw_exception( std::range_error("sobol: polynomial value outside the given value type range") ); } - const int degree = multiprecision::detail::find_msb(poly); // integer log2(poly) + const unsigned degree = multiprecision::msb(poly); // integer log2(poly) // set initial values of m from table - for (int k = 0; k < degree; ++k) - bits[k][dim] = sbl::sobol_tables::vinit(k, dim-1); + for (unsigned k = 0; k != degree; ++k) + bits[dimension*k + dim] = SobolTables::minit(dim-1, k); // Calculate remaining elements for this dimension, // as explained in Bratley+Fox, section 2. - for (int j = degree; j < bit_count; ++j) + for (unsigned j = degree; j < bit_count; ++j) { - int p_i = poly; - bits[j][dim] = bits[j - degree][dim]; - for (int k = 0; k < degree; ++k) + unsigned int p_i = poly; + const std::size_t bit_offset = dimension*j + dim; + + bits[bit_offset] = bits[dimension*(j-degree) + dim]; + for (unsigned k = 0; k != degree; ++k, p_i >>= 1) { int rem = degree - k; - bits[j][dim] ^= ((p_i & 1) * bits[j-rem][dim]) << rem; - p_i >>= 1; + bits[bit_offset] ^= ((p_i & 1) * bits[dimension*(j-rem) + dim]) << rem; } } } - // Multiply columns by appropriate power of 2. - IntType p = static_cast(2); - for (int j = bit_count-1-1; j >= 0; --j, p <<= 1) + // Shift columns by appropriate power of 2. + unsigned p = 1u; + for (int j = bit_count-1-1; j >= 0; --j, ++p) + { + const std::size_t bit_offset = dimension * j; for (std::size_t dim = 0; dim != dimension; ++dim) - bits[j][dim] *= p; + bits[bit_offset + dim] <<= p; + } } - value_type operator()(int i, int j) const + typename std::vector::const_iterator iter_at(std::size_t n) const { - return bits[i][j]; + BOOST_ASSERT(!(n > bits.size())); + return bits.begin() + n; } private: - boost::multi_array bits; + std::vector bits; }; } // namespace detail + +typedef detail::qrng_tables::sobol default_sobol_table; + /** @endcond */ -//!class template sobol implements a quasi-random number generator as described in +//!Instantiations of class template sobol_engine model a \quasi_random_number_generator. +//!The sobol_engine uses the algorithm described in //! \blockquote //![Bratley+Fox, TOMS 14, 88 (1988)] //!and [Antonov+Saleev, USSR Comput. Maths. Math. Phys. 19, 252 (1980)] //! \endblockquote //! -//!\attention \b Important: This implementation supports up to 40 dimensions. +//!\attention sobol_engine skips trivial zeroes at the start of the sequence. For example, the beginning +//!of the 2-dimensional Sobol sequence in @c uniform_01 distribution will look like this: +//!\code{.cpp} +//!0.5, 0.5, +//!0.75, 0.25, +//!0.25, 0.75, +//!0.375, 0.375, +//!0.875, 0.875, +//!... +//!\endcode //! //!In the following documentation @c X denotes the concrete class of the template -//!sobol returning objects of type @c IntType, u and v are the values of @c X. +//!sobol_engine returning objects of type @c UIntType, u and v are the values of @c X. //! -//!Some member functions may throw exceptions of type @c std::overflow_error. This +//!Some member functions may throw exceptions of type @c std::range_error. This //!happens when the quasi-random domain is exhausted and the generator cannot produce -//!any more values. The length of the low discrepancy sequence is given by -//! \f$L=Dimension \times 2^{digits}\f$, where digits = std::numeric_limits::digits. -//! -//! \copydoc friendfunctions -template -class sobol : public detail::gray_coded_qrng_base< - sobol - , detail::sobol_lattice - > +//!any more values. The length of the low discrepancy sequence is given by \f$L=Dimension \times (2^{w} - 1)\f$. +template +class sobol_engine + : public detail::gray_coded_qrng< + detail::sobol_lattice + > { - typedef sobol self_t; - typedef detail::sobol_lattice lattice_t; - typedef detail::gray_coded_qrng_base base_t; + typedef detail::sobol_lattice lattice_t; + typedef detail::gray_coded_qrng base_t; public: - typedef IntType result_type; - - /** @copydoc boost::random::niederreiter_base2::min() */ - static result_type min /** @cond */ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ () { return 0u; } - - /** @copydoc boost::random::niederreiter_base2::max() */ - static result_type max /** @cond */ BOOST_PREVENT_MACRO_SUBSTITUTION /** @endcond */ () { return std::numeric_limits::max(); } - - //!Effects: Constructs the default s-dimensional Sobol quasi-random number generator. + //!Effects: Constructs the default `s`-dimensional Sobol quasi-random number generator. //! //!Throws: bad_alloc, invalid_argument, range_error. - explicit sobol(std::size_t s) + explicit sobol_engine(std::size_t s) : base_t(s) {} // default copy c-tor is fine - /** @copydoc boost::random::niederreiter_base2::seed() */ +#ifdef BOOST_RANDOM_DOXYGEN + //=========================Doxygen needs this!============================== + typedef UIntType result_type; + + /** @copydoc boost::random::niederreiter_base2_engine::min() */ + static BOOST_CONSTEXPR result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () + { return (base_t::min)(); } + + /** @copydoc boost::random::niederreiter_base2_engine::max() */ + static BOOST_CONSTEXPR result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () + { return (base_t::max)(); } + + /** @copydoc boost::random::niederreiter_base2_engine::dimension() */ + std::size_t dimension() const { return base_t::dimension(); } + + /** @copydoc boost::random::niederreiter_base2_engine::seed() */ void seed() { - base_t::reset_state(); + base_t::seed(); } - /** @copydoc boost::random::niederreiter_base2::seed(std::size_t) */ - void seed(std::size_t init) + /** @copydoc boost::random::niederreiter_base2_engine::seed(UIntType) */ + void seed(UIntType init) { - base_t::seed(init, "sobol::seed"); + base_t::seed(init); } - //=========================Doxygen needs this!============================== - - //!Requirements: *this is mutable. - //! - //!Returns: Returns a successive element of an s-dimensional - //!(s = X::dimension()) vector at each invocation. When all elements are - //!exhausted, X::operator() begins anew with the starting element of a - //!subsequent s-dimensional vector. - //! - //!Throws: overflow_error. - - // Fixed in Doxygen 1.7.0 -- id 612458: Fixed problem handling @copydoc for function operators. + /** @copydoc boost::random::niederreiter_base2_engine::operator()() */ result_type operator()() { return base_t::operator()(); } - /** @copydoc boost::random::niederreiter_base2::discard(std::size_t) */ - void discard(std::size_t z) + /** @copydoc boost::random::niederreiter_base2_engine::discard(boost::uintmax_t) */ + void discard(boost::uintmax_t z) { base_t::discard(z); } + + /** Returns true if the two generators will produce identical sequences of outputs. */ + BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(sobol_engine, x, y) + { return static_cast(x) == y; } + + /** Returns true if the two generators will produce different sequences of outputs. */ + BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(sobol_engine) + + /** Writes the textual representation of the generator to a @c std::ostream. */ + BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, sobol_engine, s) + { return os << static_cast(s); } + + /** Reads the textual representation of the generator from a @c std::istream. */ + BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, sobol_engine, s) + { return is >> static_cast(s); } + +#endif // BOOST_RANDOM_DOXYGEN }; -} // namespace random +/** + * @attention This specialization of \sobol_engine supports up to 3667 dimensions. + * + * Data on the primitive binary polynomials `a` and the corresponding starting values `m` + * for Sobol sequences in up to 21201 dimensions was taken from + * + * @blockquote + * S. Joe and F. Y. Kuo, Constructing Sobol sequences with better two-dimensional projections, + * SIAM J. Sci. Comput. 30, 2635-2654 (2008). + * @endblockquote + * + * See the original tables up to dimension 21201: https://web.archive.org/web/20170802022909/http://web.maths.unsw.edu.au/~fkuo/sobol/new-joe-kuo-6.21201 + * + * For practical reasons the default table uses only the subset of binary polynomials `a` < 216. + * + * However, it is possible to provide your own table to \sobol_engine should the default one be insufficient. + */ +typedef sobol_engine sobol; -typedef random::sobol sobol; +} // namespace random } // namespace boost diff --git a/test/niederreiter_base2_validade.cpp b/test/niederreiter_base2_validate.cpp similarity index 97% rename from test/niederreiter_base2_validade.cpp rename to test/niederreiter_base2_validate.cpp index 7eca8af..132536e 100644 --- a/test/niederreiter_base2_validade.cpp +++ b/test/niederreiter_base2_validate.cpp @@ -1,4 +1,4 @@ -// Copyright Justinas Vygintas Daugmaudis, 2010. +// Copyright Justinas Vygintas Daugmaudis, 2010-2018. // Use, modification and distribution is subject to the // Boost Software License, Version 1.0. (See accompanying // file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) @@ -26,7 +26,7 @@ // Spatial dimension: 2 // N: 100 -// Vectors skipped: 4096 +// Vectors skipped: 4095 static const double niederreiter_base2_02_100[100][2] = { { 0.0003662109, 0.4705810548 }, @@ -133,7 +133,7 @@ static const double niederreiter_base2_02_100[100][2] = // Spatial dimension: 7 // N: 100 -// Vectors skipped: 4096 +// Vectors skipped: 4095 static const double niederreiter_base2_07_100[100][7] = { { 0.0003662109, 0.4705810548, 0.6358642580, 0.9561767580, 0.6715087892, 0.9793701174, 0.6053466798 }, @@ -241,7 +241,7 @@ static const double niederreiter_base2_07_100[100][7] = // Spatial dimension: 16 // N: 100 -// Vectors skipped: 4096 +// Vectors skipped: 4095 static const double niederreiter_base2_16_100[100][16] = { { 0.0003662109, 0.4705810548, 0.6358642580, 0.9561767580, 0.6715087892, 0.9793701174, 0.6053466798, 0.1983642579, 0.2217731476, 0.3769855500, 0.5390644075, 0.4707050325, 0.2744159699, 0.9942340853, 0.5396728517, 0.0626220703 }, @@ -348,25 +348,32 @@ static const double niederreiter_base2_16_100[100][16] = QRNG_VALIDATION_TEST_FUNCTIONS(niederreiter_base2) +QRNG_VALIDATION_TEST_DISCARD(niederreiter_base2) +BOOST_AUTO_TEST_CASE( check_generator_limits ) +{ + test_niederreiter_base2_max_seed(); + test_niederreiter_base2_max_discard(); + test_niederreiter_base2_max_dimension(BOOST_RANDOM_NIEDERREITER_BASE2_MAX_DIMENSION); +} BOOST_AUTO_TEST_CASE( validate_niederreiter_base2 ) { - test_niederreiter_base2_values(niederreiter_base2_02_100, 4096); - test_niederreiter_base2_values(niederreiter_base2_07_100, 4096); - test_niederreiter_base2_values(niederreiter_base2_16_100, 4096); + test_niederreiter_base2_values(niederreiter_base2_02_100, 4095); + test_niederreiter_base2_values(niederreiter_base2_07_100, 4095); + test_niederreiter_base2_values(niederreiter_base2_16_100, 4095); } BOOST_AUTO_TEST_CASE( validate_niederreiter_base2_seed ) { - test_niederreiter_base2_seed(niederreiter_base2_02_100, 4096); - test_niederreiter_base2_seed(niederreiter_base2_07_100, 4096); - test_niederreiter_base2_seed(niederreiter_base2_16_100, 4096); + test_niederreiter_base2_seed(niederreiter_base2_02_100, 4095); + test_niederreiter_base2_seed(niederreiter_base2_07_100, 4095); + test_niederreiter_base2_seed(niederreiter_base2_16_100, 4095); } BOOST_AUTO_TEST_CASE( validate_niederreiter_base2_discard ) { - test_niederreiter_base2_discard(niederreiter_base2_02_100, 4096); - test_niederreiter_base2_discard(niederreiter_base2_07_100, 4096); - test_niederreiter_base2_discard(niederreiter_base2_16_100, 4096); + test_niederreiter_base2_discard(niederreiter_base2_02_100, 4095); + test_niederreiter_base2_discard(niederreiter_base2_07_100, 4095); + test_niederreiter_base2_discard(niederreiter_base2_16_100, 4095); } diff --git a/test/sobol_validate.cpp b/test/sobol_validate.cpp index b2c0a4c..941cf58 100644 --- a/test/sobol_validate.cpp +++ b/test/sobol_validate.cpp @@ -1,4 +1,4 @@ -// Copyright Justinas Vygintas Daugmaudis, 2010. +// Copyright Justinas Vygintas Daugmaudis, 2010-2018. // Use, modification and distribution is subject to the // Boost Software License, Version 1.0. (See accompanying // file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) @@ -18,19 +18,20 @@ // ~~~~~~~~~~~~ // // This file tests the sobol quasi-random number generator. -// These tests compare our results with values produced by the original -// version of ACM TOMS Algorithm 659, which is available in the -// TOMS subdirectory in http://www.netlib.org +// These tests compare our results with values produced by the +// original sobol.cc program http://web.maths.unsw.edu.au/~fkuo/sobol/, +// using the new-joe-kuo-6.21201 direction polynomials and direction vectors. // -// For independently generated datasets look at http://people.sc.fsu.edu/~jburkardt/datasets/sobol/ - +// Generally, the command line used to generate the datasets was +// sobol SKIP+N+1 DIMENSION new-joe-kuo-6.21201 | tail -n N +// Note that we asked to show +1 sample from sobol.cc program, because +// it outputs trivial zeros as the first sample. // Spatial dimension: 2 -// N: 100 +// N: 99 // Vectors skipped: 0 -static const double sobol_02_100[100][2] = +static const double sobol_02_99[99][2] = { - { 0.0000000000, 0.0000000000 }, { 0.5000000002, 0.5000000002 }, { 0.7500000003, 0.2500000001 }, { 0.2500000001, 0.7500000003 }, @@ -134,238 +135,246 @@ static const double sobol_02_100[100][2] = // Spatial dimension: 7 // N: 100 -// Vectors skipped: 128 +// Vectors skipped: 127 static const double sobol_07_100[100][7] = { - { 0.0117187500, 0.3320312502, 0.7851562504, 0.9414062504, 0.4648437502, 0.4179687502, 0.4648437502 }, - { 0.5117187502, 0.8320312504, 0.2851562501, 0.4414062502, 0.9648437504, 0.9179687504, 0.9648437504 }, - { 0.7617187504, 0.0820312500, 0.0351562500, 0.6914062503, 0.7148437503, 0.1679687501, 0.7148437503 }, - { 0.2617187501, 0.5820312503, 0.5351562502, 0.1914062501, 0.2148437501, 0.6679687503, 0.2148437501 }, - { 0.3867187502, 0.2070312501, 0.4101562502, 0.8164062504, 0.5898437503, 0.5429687503, 0.3398437502 }, - { 0.8867187504, 0.7070312503, 0.9101562504, 0.3164062501, 0.0898437500, 0.0429687500, 0.8398437504 }, - { 0.6367187503, 0.4570312502, 0.6601562503, 0.5664062503, 0.3398437502, 0.7929687504, 0.5898437503 }, - { 0.1367187501, 0.9570312504, 0.1601562501, 0.0664062500, 0.8398437504, 0.2929687501, 0.0898437500 }, - { 0.1992187501, 0.0195312500, 0.5976562503, 0.2539062501, 0.9023437504, 0.3554687502, 0.4023437502 }, - { 0.6992187503, 0.5195312502, 0.0976562500, 0.7539062504, 0.4023437502, 0.8554687504, 0.9023437504 }, - { 0.9492187504, 0.2695312501, 0.3476562502, 0.0039062500, 0.1523437501, 0.1054687500, 0.6523437503 }, - { 0.4492187502, 0.7695312504, 0.8476562504, 0.5039062502, 0.6523437503, 0.6054687503, 0.1523437501 }, - { 0.3242187502, 0.3945312502, 0.2226562501, 0.3789062502, 0.0273437500, 0.7304687503, 0.2773437501 }, - { 0.8242187504, 0.8945312504, 0.7226562503, 0.8789062504, 0.5273437502, 0.2304687501, 0.7773437504 }, - { 0.5742187503, 0.1445312501, 0.9726562505, 0.1289062501, 0.7773437504, 0.9804687505, 0.5273437502 }, - { 0.0742187500, 0.6445312503, 0.4726562502, 0.6289062503, 0.2773437501, 0.4804687502, 0.0273437500 }, - { 0.1054687500, 0.1757812501, 0.0664062500, 0.5976562503, 0.2460937501, 0.1992187501, 0.9960937505 }, - { 0.6054687503, 0.6757812503, 0.5664062503, 0.0976562500, 0.7460937503, 0.6992187503, 0.4960937502 }, - { 0.8554687504, 0.4257812502, 0.8164062504, 0.8476562504, 0.9960937505, 0.4492187502, 0.2460937501 }, - { 0.3554687502, 0.9257812504, 0.3164062501, 0.3476562502, 0.4960937502, 0.9492187504, 0.7460937503 }, - { 0.4804687502, 0.3007812501, 0.6914062503, 0.7226562503, 0.8710937504, 0.8242187504, 0.8710937504 }, - { 0.9804687505, 0.8007812504, 0.1914062501, 0.2226562501, 0.3710937502, 0.3242187502, 0.3710937502 }, - { 0.7304687503, 0.0507812500, 0.4414062502, 0.9726562505, 0.1210937501, 0.5742187503, 0.1210937501 }, - { 0.2304687501, 0.5507812503, 0.9414062504, 0.4726562502, 0.6210937503, 0.0742187500, 0.6210937503 }, - { 0.1679687501, 0.4882812502, 0.2539062501, 0.1601562501, 0.6835937503, 0.0117187500, 0.9335937504 }, - { 0.6679687503, 0.9882812505, 0.7539062504, 0.6601562503, 0.1835937501, 0.5117187502, 0.4335937502 }, - { 0.9179687504, 0.2382812501, 0.5039062502, 0.4101562502, 0.4335937502, 0.2617187501, 0.1835937501 }, - { 0.4179687502, 0.7382812503, 0.0039062500, 0.9101562504, 0.9335937504, 0.7617187504, 0.6835937503 }, - { 0.2929687501, 0.1132812501, 0.8789062504, 0.0351562500, 0.3085937501, 0.8867187504, 0.8085937504 }, - { 0.7929687504, 0.6132812503, 0.3789062502, 0.5351562502, 0.8085937504, 0.3867187502, 0.3085937501 }, - { 0.5429687503, 0.3632812502, 0.1289062501, 0.2851562501, 0.5585937503, 0.6367187503, 0.0585937500 }, - { 0.0429687500, 0.8632812504, 0.6289062503, 0.7851562504, 0.0585937500, 0.1367187501, 0.5585937503 }, - { 0.0585937500, 0.0664062500, 0.3320312502, 0.3945312502, 0.7617187504, 0.8085937504, 0.1992187501 }, - { 0.5585937503, 0.5664062503, 0.8320312504, 0.8945312504, 0.2617187501, 0.3085937501, 0.6992187503 }, - { 0.8085937504, 0.3164062501, 0.5820312503, 0.1445312501, 0.0117187500, 0.5585937503, 0.9492187504 }, - { 0.3085937501, 0.8164062504, 0.0820312500, 0.6445312503, 0.5117187502, 0.0585937500, 0.4492187502 }, - { 0.4335937502, 0.4414062502, 0.9570312504, 0.2695312501, 0.1367187501, 0.1835937501, 0.0742187500 }, - { 0.9335937504, 0.9414062504, 0.4570312502, 0.7695312504, 0.6367187503, 0.6835937503, 0.5742187503 }, - { 0.6835937503, 0.1914062501, 0.2070312501, 0.0195312500, 0.8867187504, 0.4335937502, 0.8242187504 }, - { 0.1835937501, 0.6914062503, 0.7070312503, 0.5195312502, 0.3867187502, 0.9335937504, 0.3242187502 }, - { 0.2460937501, 0.2539062501, 0.0195312500, 0.8320312504, 0.3242187502, 0.9960937505, 0.1367187501 }, - { 0.7460937503, 0.7539062504, 0.5195312502, 0.3320312502, 0.8242187504, 0.4960937502, 0.6367187503 }, - { 0.9960937505, 0.0039062500, 0.7695312504, 0.5820312503, 0.5742187503, 0.7460937503, 0.8867187504 }, - { 0.4960937502, 0.5039062502, 0.2695312501, 0.0820312500, 0.0742187500, 0.2460937501, 0.3867187502 }, - { 0.3710937502, 0.1289062501, 0.6445312503, 0.9570312504, 0.6992187503, 0.1210937501, 0.0117187500 }, - { 0.8710937504, 0.6289062503, 0.1445312501, 0.4570312502, 0.1992187501, 0.6210937503, 0.5117187502 }, - { 0.6210937503, 0.3789062502, 0.3945312502, 0.7070312503, 0.4492187502, 0.3710937502, 0.7617187504 }, - { 0.1210937501, 0.8789062504, 0.8945312504, 0.2070312501, 0.9492187504, 0.8710937504, 0.2617187501 }, - { 0.0898437500, 0.4101562502, 0.5507812503, 0.0507812500, 0.5429687503, 0.5898437503, 0.7304687503 }, - { 0.5898437503, 0.9101562504, 0.0507812500, 0.5507812503, 0.0429687500, 0.0898437500, 0.2304687501 }, - { 0.8398437504, 0.1601562501, 0.3007812501, 0.3007812501, 0.2929687501, 0.8398437504, 0.4804687502 }, - { 0.3398437502, 0.6601562503, 0.8007812504, 0.8007812504, 0.7929687504, 0.3398437502, 0.9804687505 }, - { 0.4648437502, 0.0351562500, 0.1757812501, 0.1757812501, 0.4179687502, 0.4648437502, 0.6054687503 }, - { 0.9648437504, 0.5351562502, 0.6757812503, 0.6757812503, 0.9179687504, 0.9648437504, 0.1054687500 }, - { 0.7148437503, 0.2851562501, 0.9257812504, 0.4257812502, 0.6679687503, 0.2148437501, 0.3554687502 }, - { 0.2148437501, 0.7851562504, 0.4257812502, 0.9257812504, 0.1679687501, 0.7148437503, 0.8554687504 }, - { 0.1523437501, 0.2226562501, 0.8632812504, 0.7382812503, 0.1054687500, 0.6523437503, 0.6679687503 }, - { 0.6523437503, 0.7226562503, 0.3632812502, 0.2382812501, 0.6054687503, 0.1523437501, 0.1679687501 }, - { 0.9023437504, 0.4726562502, 0.1132812501, 0.9882812505, 0.8554687504, 0.9023437504, 0.4179687502 }, - { 0.4023437502, 0.9726562505, 0.6132812503, 0.4882812502, 0.3554687502, 0.4023437502, 0.9179687504 }, - { 0.2773437501, 0.3476562502, 0.4882812502, 0.6132812503, 0.9804687505, 0.2773437501, 0.5429687503 }, - { 0.7773437504, 0.8476562504, 0.9882812505, 0.1132812501, 0.4804687502, 0.7773437504, 0.0429687500 }, - { 0.5273437502, 0.0976562500, 0.7382812503, 0.8632812504, 0.2304687501, 0.0273437500, 0.2929687501 }, - { 0.0273437500, 0.5976562503, 0.2382812501, 0.3632812502, 0.7304687503, 0.5273437502, 0.7929687504 }, - { 0.0195312500, 0.1992187501, 0.7304687503, 0.2460937501, 0.2539062501, 0.7070312503, 0.0664062500 }, - { 0.5195312502, 0.6992187503, 0.2304687501, 0.7460937503, 0.7539062504, 0.2070312501, 0.5664062503 }, - { 0.7695312504, 0.4492187502, 0.4804687502, 0.4960937502, 0.5039062502, 0.9570312504, 0.8164062504 }, - { 0.2695312501, 0.9492187504, 0.9804687505, 0.9960937505, 0.0039062500, 0.4570312502, 0.3164062501 }, - { 0.3945312502, 0.3242187502, 0.1054687500, 0.1210937501, 0.6289062503, 0.3320312502, 0.1914062501 }, - { 0.8945312504, 0.8242187504, 0.6054687503, 0.6210937503, 0.1289062501, 0.8320312504, 0.6914062503 }, - { 0.6445312503, 0.0742187500, 0.8554687504, 0.3710937502, 0.3789062502, 0.0820312500, 0.9414062504 }, - { 0.1445312501, 0.5742187503, 0.3554687502, 0.8710937504, 0.8789062504, 0.5820312503, 0.4414062502 }, - { 0.2070312501, 0.3867187502, 0.9179687504, 0.5585937503, 0.8164062504, 0.5195312502, 0.0039062500 }, - { 0.7070312503, 0.8867187504, 0.4179687502, 0.0585937500, 0.3164062501, 0.0195312500, 0.5039062502 }, - { 0.9570312504, 0.1367187501, 0.1679687501, 0.8085937504, 0.0664062500, 0.7695312504, 0.7539062504 }, - { 0.4570312502, 0.6367187503, 0.6679687503, 0.3085937501, 0.5664062503, 0.2695312501, 0.2539062501 }, - { 0.3320312502, 0.0117187500, 0.2929687501, 0.6835937503, 0.1914062501, 0.3945312502, 0.1289062501 }, - { 0.8320312504, 0.5117187502, 0.7929687504, 0.1835937501, 0.6914062503, 0.8945312504, 0.6289062503 }, - { 0.5820312503, 0.2617187501, 0.5429687503, 0.9335937504, 0.9414062504, 0.1445312501, 0.8789062504 }, - { 0.0820312500, 0.7617187504, 0.0429687500, 0.4335937502, 0.4414062502, 0.6445312503, 0.3789062502 }, - { 0.1132812501, 0.2929687501, 0.3867187502, 0.3398437502, 0.0351562500, 0.9257812504, 0.5976562503 }, - { 0.6132812503, 0.7929687504, 0.8867187504, 0.8398437504, 0.5351562502, 0.4257812502, 0.0976562500 }, - { 0.8632812504, 0.0429687500, 0.6367187503, 0.0898437500, 0.7851562504, 0.6757812503, 0.3476562502 }, - { 0.3632812502, 0.5429687503, 0.1367187501, 0.5898437503, 0.2851562501, 0.1757812501, 0.8476562504 }, - { 0.4882812502, 0.1679687501, 0.7617187504, 0.4648437502, 0.9101562504, 0.0507812500, 0.7226562503 }, - { 0.9882812505, 0.6679687503, 0.2617187501, 0.9648437504, 0.4101562502, 0.5507812503, 0.2226562501 }, - { 0.7382812503, 0.4179687502, 0.0117187500, 0.2148437501, 0.1601562501, 0.3007812501, 0.4726562502 }, - { 0.2382812501, 0.9179687504, 0.5117187502, 0.7148437503, 0.6601562503, 0.8007812504, 0.9726562505 }, - { 0.1757812501, 0.1054687500, 0.1992187501, 0.9023437504, 0.5976562503, 0.8632812504, 0.5351562502 }, - { 0.6757812503, 0.6054687503, 0.6992187503, 0.4023437502, 0.0976562500, 0.3632812502, 0.0351562500 }, - { 0.9257812504, 0.3554687502, 0.9492187504, 0.6523437503, 0.3476562502, 0.6132812503, 0.2851562501 }, - { 0.4257812502, 0.8554687504, 0.4492187502, 0.1523437501, 0.8476562504, 0.1132812501, 0.7851562504 }, - { 0.3007812501, 0.4804687502, 0.5742187503, 0.7773437504, 0.4726562502, 0.2382812501, 0.6601562503 }, - { 0.8007812504, 0.9804687505, 0.0742187500, 0.2773437501, 0.9726562505, 0.7382812503, 0.1601562501 }, - { 0.5507812503, 0.2304687501, 0.3242187502, 0.5273437502, 0.7226562503, 0.4882812502, 0.4101562502 }, - { 0.0507812500, 0.7304687503, 0.8242187504, 0.0273437500, 0.2226562501, 0.9882812505, 0.9101562504 }, - { 0.0351562500, 0.4648437502, 0.1523437501, 0.6679687503, 0.9570312504, 0.0664062500, 0.3320312502 }, - { 0.5351562502, 0.9648437504, 0.6523437503, 0.1679687501, 0.4570312502, 0.5664062503, 0.8320312504 }, - { 0.7851562504, 0.2148437501, 0.9023437504, 0.9179687504, 0.2070312501, 0.3164062501, 0.5820312503 }, - { 0.2851562501, 0.7148437503, 0.4023437502, 0.4179687502, 0.7070312503, 0.8164062504, 0.0820312500 } + { 0.0117187500, 0.3320312500, 0.2929687500, 0.1914062500, 0.9023437500, 0.6757812500, 0.8632812500 }, + { 0.5117187500, 0.8320312500, 0.7929687500, 0.6914062500, 0.4023437500, 0.1757812500, 0.3632812500 }, + { 0.7617187500, 0.0820312500, 0.0429687500, 0.4414062500, 0.1523437500, 0.4257812500, 0.6132812500 }, + { 0.2617187500, 0.5820312500, 0.5429687500, 0.9414062500, 0.6523437500, 0.9257812500, 0.1132812500 }, + { 0.3867187500, 0.2070312500, 0.9179687500, 0.8164062500, 0.5273437500, 0.5507812500, 0.7382812500 }, + { 0.8867187500, 0.7070312500, 0.4179687500, 0.3164062500, 0.0273437500, 0.0507812500, 0.2382812500 }, + { 0.6367187500, 0.4570312500, 0.6679687500, 0.5664062500, 0.2773437500, 0.3007812500, 0.9882812500 }, + { 0.1367187500, 0.9570312500, 0.1679687500, 0.0664062500, 0.7773437500, 0.8007812500, 0.4882812500 }, + { 0.1992187500, 0.0195312500, 0.7304687500, 0.2539062500, 0.4648437500, 0.9882812500, 0.6757812500 }, + { 0.6992187500, 0.5195312500, 0.2304687500, 0.7539062500, 0.9648437500, 0.4882812500, 0.1757812500 }, + { 0.9492187500, 0.2695312500, 0.9804687500, 0.0039062500, 0.7148437500, 0.2382812500, 0.9257812500 }, + { 0.4492187500, 0.7695312500, 0.4804687500, 0.5039062500, 0.2148437500, 0.7382812500, 0.4257812500 }, + { 0.3242187500, 0.3945312500, 0.1054687500, 0.6289062500, 0.0898437500, 0.8632812500, 0.8007812500 }, + { 0.8242187500, 0.8945312500, 0.6054687500, 0.1289062500, 0.5898437500, 0.3632812500, 0.3007812500 }, + { 0.5742187500, 0.1445312500, 0.3554687500, 0.8789062500, 0.8398437500, 0.1132812500, 0.5507812500 }, + { 0.0742187500, 0.6445312500, 0.8554687500, 0.3789062500, 0.3398437500, 0.6132812500, 0.0507812500 }, + { 0.1054687500, 0.1757812500, 0.1992187500, 0.5976562500, 0.6835937500, 0.3320312500, 0.3320312500 }, + { 0.6054687500, 0.6757812500, 0.6992187500, 0.0976562500, 0.1835937500, 0.8320312500, 0.8320312500 }, + { 0.8554687500, 0.4257812500, 0.4492187500, 0.8476562500, 0.4335937500, 0.5820312500, 0.0820312500 }, + { 0.3554687500, 0.9257812500, 0.9492187500, 0.3476562500, 0.9335937500, 0.0820312500, 0.5820312500 }, + { 0.4804687500, 0.3007812500, 0.5742187500, 0.4726562500, 0.8085937500, 0.4570312500, 0.2070312500 }, + { 0.9804687500, 0.8007812500, 0.0742187500, 0.9726562500, 0.3085937500, 0.9570312500, 0.7070312500 }, + { 0.7304687500, 0.0507812500, 0.8242187500, 0.2226562500, 0.0585937500, 0.7070312500, 0.4570312500 }, + { 0.2304687500, 0.5507812500, 0.3242187500, 0.7226562500, 0.5585937500, 0.2070312500, 0.9570312500 }, + { 0.1679687500, 0.4882812500, 0.7617187500, 0.9101562500, 0.2460937500, 0.0195312500, 0.1445312500 }, + { 0.6679687500, 0.9882812500, 0.2617187500, 0.4101562500, 0.7460937500, 0.5195312500, 0.6445312500 }, + { 0.9179687500, 0.2382812500, 0.5117187500, 0.6601562500, 0.9960937500, 0.7695312500, 0.3945312500 }, + { 0.4179687500, 0.7382812500, 0.0117187500, 0.1601562500, 0.4960937500, 0.2695312500, 0.8945312500 }, + { 0.2929687500, 0.1132812500, 0.3867187500, 0.0351562500, 0.3710937500, 0.1445312500, 0.2695312500 }, + { 0.7929687500, 0.6132812500, 0.8867187500, 0.5351562500, 0.8710937500, 0.6445312500, 0.7695312500 }, + { 0.5429687500, 0.3632812500, 0.1367187500, 0.2851562500, 0.6210937500, 0.8945312500, 0.0195312500 }, + { 0.0429687500, 0.8632812500, 0.6367187500, 0.7851562500, 0.1210937500, 0.3945312500, 0.5195312500 }, + { 0.0585937500, 0.0664062500, 0.9960937500, 0.7382812500, 0.7617187500, 0.2539062500, 0.0664062500 }, + { 0.5585937500, 0.5664062500, 0.4960937500, 0.2382812500, 0.2617187500, 0.7539062500, 0.5664062500 }, + { 0.8085937500, 0.3164062500, 0.7460937500, 0.9882812500, 0.0117187500, 0.5039062500, 0.3164062500 }, + { 0.3085937500, 0.8164062500, 0.2460937500, 0.4882812500, 0.5117187500, 0.0039062500, 0.8164062500 }, + { 0.4335937500, 0.4414062500, 0.3710937500, 0.3632812500, 0.6367187500, 0.3789062500, 0.4414062500 }, + { 0.9335937500, 0.9414062500, 0.8710937500, 0.8632812500, 0.1367187500, 0.8789062500, 0.9414062500 }, + { 0.6835937500, 0.1914062500, 0.1210937500, 0.1132812500, 0.3867187500, 0.6289062500, 0.1914062500 }, + { 0.1835937500, 0.6914062500, 0.6210937500, 0.6132812500, 0.8867187500, 0.1289062500, 0.6914062500 }, + { 0.2460937500, 0.2539062500, 0.0585937500, 0.8007812500, 0.3242187500, 0.0664062500, 0.3789062500 }, + { 0.7460937500, 0.7539062500, 0.5585937500, 0.3007812500, 0.8242187500, 0.5664062500, 0.8789062500 }, + { 0.9960937500, 0.0039062500, 0.3085937500, 0.5507812500, 0.5742187500, 0.8164062500, 0.1289062500 }, + { 0.4960937500, 0.5039062500, 0.8085937500, 0.0507812500, 0.0742187500, 0.3164062500, 0.6289062500 }, + { 0.3710937500, 0.1289062500, 0.6835937500, 0.1757812500, 0.1992187500, 0.1914062500, 0.0039062500 }, + { 0.8710937500, 0.6289062500, 0.1835937500, 0.6757812500, 0.6992187500, 0.6914062500, 0.5039062500 }, + { 0.6210937500, 0.3789062500, 0.9335937500, 0.4257812500, 0.9492187500, 0.9414062500, 0.2539062500 }, + { 0.1210937500, 0.8789062500, 0.4335937500, 0.9257812500, 0.4492187500, 0.4414062500, 0.7539062500 }, + { 0.0898437500, 0.4101562500, 0.5273437500, 0.0820312500, 0.5429687500, 0.7226562500, 0.5976562500 }, + { 0.5898437500, 0.9101562500, 0.0273437500, 0.5820312500, 0.0429687500, 0.2226562500, 0.0976562500 }, + { 0.8398437500, 0.1601562500, 0.7773437500, 0.3320312500, 0.2929687500, 0.4726562500, 0.8476562500 }, + { 0.3398437500, 0.6601562500, 0.2773437500, 0.8320312500, 0.7929687500, 0.9726562500, 0.3476562500 }, + { 0.4648437500, 0.0351562500, 0.1523437500, 0.9570312500, 0.9179687500, 0.5976562500, 0.9726562500 }, + { 0.9648437500, 0.5351562500, 0.6523437500, 0.4570312500, 0.4179687500, 0.0976562500, 0.4726562500 }, + { 0.7148437500, 0.2851562500, 0.4023437500, 0.7070312500, 0.1679687500, 0.3476562500, 0.7226562500 }, + { 0.2148437500, 0.7851562500, 0.9023437500, 0.2070312500, 0.6679687500, 0.8476562500, 0.2226562500 }, + { 0.1523437500, 0.2226562500, 0.4648437500, 0.3945312500, 0.1054687500, 0.9101562500, 0.9101562500 }, + { 0.6523437500, 0.7226562500, 0.9648437500, 0.8945312500, 0.6054687500, 0.4101562500, 0.4101562500 }, + { 0.9023437500, 0.4726562500, 0.2148437500, 0.1445312500, 0.8554687500, 0.1601562500, 0.6601562500 }, + { 0.4023437500, 0.9726562500, 0.7148437500, 0.6445312500, 0.3554687500, 0.6601562500, 0.1601562500 }, + { 0.2773437500, 0.3476562500, 0.8398437500, 0.5195312500, 0.4804687500, 0.7851562500, 0.5351562500 }, + { 0.7773437500, 0.8476562500, 0.3398437500, 0.0195312500, 0.9804687500, 0.2851562500, 0.0351562500 }, + { 0.5273437500, 0.0976562500, 0.5898437500, 0.7695312500, 0.7304687500, 0.0351562500, 0.7851562500 }, + { 0.0273437500, 0.5976562500, 0.0898437500, 0.2695312500, 0.2304687500, 0.5351562500, 0.2851562500 }, + { 0.0195312500, 0.1992187500, 0.5976562500, 0.9023437500, 0.2539062500, 0.8710937500, 0.4648437500 }, + { 0.5195312500, 0.6992187500, 0.0976562500, 0.4023437500, 0.7539062500, 0.3710937500, 0.9648437500 }, + { 0.7695312500, 0.4492187500, 0.8476562500, 0.6523437500, 0.5039062500, 0.1210937500, 0.2148437500 }, + { 0.2695312500, 0.9492187500, 0.3476562500, 0.1523437500, 0.0039062500, 0.6210937500, 0.7148437500 }, + { 0.3945312500, 0.3242187500, 0.2226562500, 0.0273437500, 0.1289062500, 0.9960937500, 0.0898437500 }, + { 0.8945312500, 0.8242187500, 0.7226562500, 0.5273437500, 0.6289062500, 0.4960937500, 0.5898437500 }, + { 0.6445312500, 0.0742187500, 0.4726562500, 0.2773437500, 0.8789062500, 0.2460937500, 0.3398437500 }, + { 0.1445312500, 0.5742187500, 0.9726562500, 0.7773437500, 0.3789062500, 0.7460937500, 0.8398437500 }, + { 0.2070312500, 0.3867187500, 0.4101562500, 0.5898437500, 0.8164062500, 0.5585937500, 0.0273437500 }, + { 0.7070312500, 0.8867187500, 0.9101562500, 0.0898437500, 0.3164062500, 0.0585937500, 0.5273437500 }, + { 0.9570312500, 0.1367187500, 0.1601562500, 0.8398437500, 0.0664062500, 0.3085937500, 0.2773437500 }, + { 0.4570312500, 0.6367187500, 0.6601562500, 0.3398437500, 0.5664062500, 0.8085937500, 0.7773437500 }, + { 0.3320312500, 0.0117187500, 0.7851562500, 0.4648437500, 0.6914062500, 0.6835937500, 0.4023437500 }, + { 0.8320312500, 0.5117187500, 0.2851562500, 0.9648437500, 0.1914062500, 0.1835937500, 0.9023437500 }, + { 0.5820312500, 0.2617187500, 0.5351562500, 0.2148437500, 0.4414062500, 0.4335937500, 0.1523437500 }, + { 0.0820312500, 0.7617187500, 0.0351562500, 0.7148437500, 0.9414062500, 0.9335937500, 0.6523437500 }, + { 0.1132812500, 0.2929687500, 0.8789062500, 0.3085937500, 0.0351562500, 0.1523437500, 0.9960937500 }, + { 0.6132812500, 0.7929687500, 0.3789062500, 0.8085937500, 0.5351562500, 0.6523437500, 0.4960937500 }, + { 0.8632812500, 0.0429687500, 0.6289062500, 0.0585937500, 0.7851562500, 0.9023437500, 0.7460937500 }, + { 0.3632812500, 0.5429687500, 0.1289062500, 0.5585937500, 0.2851562500, 0.4023437500, 0.2460937500 }, + { 0.4882812500, 0.1679687500, 0.2539062500, 0.6835937500, 0.4101562500, 0.0273437500, 0.6210937500 }, + { 0.9882812500, 0.6679687500, 0.7539062500, 0.1835937500, 0.9101562500, 0.5273437500, 0.1210937500 }, + { 0.7382812500, 0.4179687500, 0.0039062500, 0.9335937500, 0.6601562500, 0.7773437500, 0.8710937500 }, + { 0.2382812500, 0.9179687500, 0.5039062500, 0.4335937500, 0.1601562500, 0.2773437500, 0.3710937500 }, + { 0.1757812500, 0.1054687500, 0.0664062500, 0.2460937500, 0.5976562500, 0.4648437500, 0.5585937500 }, + { 0.6757812500, 0.6054687500, 0.5664062500, 0.7460937500, 0.0976562500, 0.9648437500, 0.0585937500 }, + { 0.9257812500, 0.3554687500, 0.3164062500, 0.4960937500, 0.3476562500, 0.7148437500, 0.8085937500 }, + { 0.4257812500, 0.8554687500, 0.8164062500, 0.9960937500, 0.8476562500, 0.2148437500, 0.3085937500 }, + { 0.3007812500, 0.4804687500, 0.6914062500, 0.8710937500, 0.9726562500, 0.3398437500, 0.9335937500 }, + { 0.8007812500, 0.9804687500, 0.1914062500, 0.3710937500, 0.4726562500, 0.8398437500, 0.4335937500 }, + { 0.5507812500, 0.2304687500, 0.9414062500, 0.6210937500, 0.2226562500, 0.5898437500, 0.6835937500 }, + { 0.0507812500, 0.7304687500, 0.4414062500, 0.1210937500, 0.7226562500, 0.0898437500, 0.1835937500 }, + { 0.0351562500, 0.4648437500, 0.1757812500, 0.4179687500, 0.3945312500, 0.1992187500, 0.7304687500 }, + { 0.5351562500, 0.9648437500, 0.6757812500, 0.9179687500, 0.8945312500, 0.6992187500, 0.2304687500 }, + { 0.7851562500, 0.2148437500, 0.4257812500, 0.1679687500, 0.6445312500, 0.9492187500, 0.9804687500 }, + { 0.2851562500, 0.7148437500, 0.9257812500, 0.6679687500, 0.1445312500, 0.4492187500, 0.4804687500 } }; // Spatial dimension: 16 // N: 100 -// Vectors skipped: 128 +// Vectors skipped: 127 static const double sobol_16_100[100][16] = { - { 0.0117187500, 0.3320312502, 0.7851562504, 0.9414062504, 0.4648437502, 0.4179687502, 0.4648437502, 0.4882812502, 0.7304687503, 0.5742187503, 0.5664062503, 0.2460937501, 0.4882812502, 0.6367187503, 0.7617187504, 0.1835937501 }, - { 0.5117187502, 0.8320312504, 0.2851562501, 0.4414062502, 0.9648437504, 0.9179687504, 0.9648437504, 0.9882812505, 0.2304687501, 0.0742187500, 0.0664062500, 0.7460937503, 0.9882812505, 0.1367187501, 0.2617187501, 0.6835937503 }, - { 0.7617187504, 0.0820312500, 0.0351562500, 0.6914062503, 0.7148437503, 0.1679687501, 0.7148437503, 0.2382812501, 0.9804687505, 0.3242187502, 0.8164062504, 0.9960937505, 0.2382812501, 0.3867187502, 0.5117187502, 0.9335937504 }, - { 0.2617187501, 0.5820312503, 0.5351562502, 0.1914062501, 0.2148437501, 0.6679687503, 0.2148437501, 0.7382812503, 0.4804687502, 0.8242187504, 0.3164062501, 0.4960937502, 0.7382812503, 0.8867187504, 0.0117187500, 0.4335937502 }, - { 0.3867187502, 0.2070312501, 0.4101562502, 0.8164062504, 0.5898437503, 0.5429687503, 0.3398437502, 0.8632812504, 0.6054687503, 0.4492187502, 0.9414062504, 0.6210937503, 0.3632812502, 0.7617187504, 0.3867187502, 0.0585937500 }, - { 0.8867187504, 0.7070312503, 0.9101562504, 0.3164062501, 0.0898437500, 0.0429687500, 0.8398437504, 0.3632812502, 0.1054687500, 0.9492187504, 0.4414062502, 0.1210937501, 0.8632812504, 0.2617187501, 0.8867187504, 0.5585937503 }, - { 0.6367187503, 0.4570312502, 0.6601562503, 0.5664062503, 0.3398437502, 0.7929687504, 0.5898437503, 0.6132812503, 0.8554687504, 0.6992187503, 0.6914062503, 0.3710937502, 0.1132812501, 0.0117187500, 0.1367187501, 0.8085937504 }, - { 0.1367187501, 0.9570312504, 0.1601562501, 0.0664062500, 0.8398437504, 0.2929687501, 0.0898437500, 0.1132812501, 0.3554687502, 0.1992187501, 0.1914062501, 0.8710937504, 0.6132812503, 0.5117187502, 0.6367187503, 0.3085937501 }, - { 0.1992187501, 0.0195312500, 0.5976562503, 0.2539062501, 0.9023437504, 0.3554687502, 0.4023437502, 0.5507812503, 0.5429687503, 0.5117187502, 0.1289062501, 0.9335937504, 0.9257812504, 0.0742187500, 0.9492187504, 0.6210937503 }, - { 0.6992187503, 0.5195312502, 0.0976562500, 0.7539062504, 0.4023437502, 0.8554687504, 0.9023437504, 0.0507812500, 0.0429687500, 0.0117187500, 0.6289062503, 0.4335937502, 0.4257812502, 0.5742187503, 0.4492187502, 0.1210937501 }, - { 0.9492187504, 0.2695312501, 0.3476562502, 0.0039062500, 0.1523437501, 0.1054687500, 0.6523437503, 0.8007812504, 0.7929687504, 0.2617187501, 0.3789062502, 0.1835937501, 0.6757812503, 0.8242187504, 0.6992187503, 0.3710937502 }, - { 0.4492187502, 0.7695312504, 0.8476562504, 0.5039062502, 0.6523437503, 0.6054687503, 0.1523437501, 0.3007812501, 0.2929687501, 0.7617187504, 0.8789062504, 0.6835937503, 0.1757812501, 0.3242187502, 0.1992187501, 0.8710937504 }, - { 0.3242187502, 0.3945312502, 0.2226562501, 0.3789062502, 0.0273437500, 0.7304687503, 0.2773437501, 0.1757812501, 0.6679687503, 0.3867187502, 0.2539062501, 0.3085937501, 0.8007812504, 0.4492187502, 0.3242187502, 0.7460937503 }, - { 0.8242187504, 0.8945312504, 0.7226562503, 0.8789062504, 0.5273437502, 0.2304687501, 0.7773437504, 0.6757812503, 0.1679687501, 0.8867187504, 0.7539062504, 0.8085937504, 0.3007812501, 0.9492187504, 0.8242187504, 0.2460937501 }, - { 0.5742187503, 0.1445312501, 0.9726562505, 0.1289062501, 0.7773437504, 0.9804687505, 0.5273437502, 0.4257812502, 0.9179687504, 0.6367187503, 0.0039062500, 0.5585937503, 0.5507812503, 0.6992187503, 0.0742187500, 0.4960937502 }, - { 0.0742187500, 0.6445312503, 0.4726562502, 0.6289062503, 0.2773437501, 0.4804687502, 0.0273437500, 0.9257812504, 0.4179687502, 0.1367187501, 0.5039062502, 0.0585937500, 0.0507812500, 0.1992187501, 0.5742187503, 0.9960937505 }, - { 0.1054687500, 0.1757812501, 0.0664062500, 0.5976562503, 0.2460937501, 0.1992187501, 0.9960937505, 0.6445312503, 0.4492187502, 0.9804687505, 0.9726562505, 0.9023437504, 0.6445312503, 0.5429687503, 0.0429687500, 0.6523437503 }, - { 0.6054687503, 0.6757812503, 0.5664062503, 0.0976562500, 0.7460937503, 0.6992187503, 0.4960937502, 0.1445312501, 0.9492187504, 0.4804687502, 0.4726562502, 0.4023437502, 0.1445312501, 0.0429687500, 0.5429687503, 0.1523437501 }, - { 0.8554687504, 0.4257812502, 0.8164062504, 0.8476562504, 0.9960937505, 0.4492187502, 0.2460937501, 0.8945312504, 0.1992187501, 0.2304687501, 0.7226562503, 0.1523437501, 0.8945312504, 0.2929687501, 0.2929687501, 0.4023437502 }, - { 0.3554687502, 0.9257812504, 0.3164062501, 0.3476562502, 0.4960937502, 0.9492187504, 0.7460937503, 0.3945312502, 0.6992187503, 0.7304687503, 0.2226562501, 0.6523437503, 0.3945312502, 0.7929687504, 0.7929687504, 0.9023437504 }, - { 0.4804687502, 0.3007812501, 0.6914062503, 0.7226562503, 0.8710937504, 0.8242187504, 0.8710937504, 0.0195312500, 0.3242187502, 0.1054687500, 0.5976562503, 0.2773437501, 0.5195312502, 0.9179687504, 0.6679687503, 0.5273437502 }, - { 0.9804687505, 0.8007812504, 0.1914062501, 0.2226562501, 0.3710937502, 0.3242187502, 0.3710937502, 0.5195312502, 0.8242187504, 0.6054687503, 0.0976562500, 0.7773437504, 0.0195312500, 0.4179687502, 0.1679687501, 0.0273437500 }, - { 0.7304687503, 0.0507812500, 0.4414062502, 0.9726562505, 0.1210937501, 0.5742187503, 0.1210937501, 0.2695312501, 0.0742187500, 0.8554687504, 0.8476562504, 0.5273437502, 0.7695312504, 0.1679687501, 0.9179687504, 0.2773437501 }, - { 0.2304687501, 0.5507812503, 0.9414062504, 0.4726562502, 0.6210937503, 0.0742187500, 0.6210937503, 0.7695312504, 0.5742187503, 0.3554687502, 0.3476562502, 0.0273437500, 0.2695312501, 0.6679687503, 0.4179687502, 0.7773437504 }, - { 0.1679687501, 0.4882812502, 0.2539062501, 0.1601562501, 0.6835937503, 0.0117187500, 0.9335937504, 0.3320312502, 0.2617187501, 0.9179687504, 0.2851562501, 0.2148437501, 0.2070312501, 0.2304687501, 0.2304687501, 0.0898437500 }, - { 0.6679687503, 0.9882812505, 0.7539062504, 0.6601562503, 0.1835937501, 0.5117187502, 0.4335937502, 0.8320312504, 0.7617187504, 0.4179687502, 0.7851562504, 0.7148437503, 0.7070312503, 0.7304687503, 0.7304687503, 0.5898437503 }, - { 0.9179687504, 0.2382812501, 0.5039062502, 0.4101562502, 0.4335937502, 0.2617187501, 0.1835937501, 0.0820312500, 0.0117187500, 0.1679687501, 0.0351562500, 0.9648437504, 0.4570312502, 0.9804687505, 0.4804687502, 0.8398437504 }, - { 0.4179687502, 0.7382812503, 0.0039062500, 0.9101562504, 0.9335937504, 0.7617187504, 0.6835937503, 0.5820312503, 0.5117187502, 0.6679687503, 0.5351562502, 0.4648437502, 0.9570312504, 0.4804687502, 0.9804687505, 0.3398437502 }, - { 0.2929687501, 0.1132812501, 0.8789062504, 0.0351562500, 0.3085937501, 0.8867187504, 0.8085937504, 0.9570312504, 0.3867187502, 0.0429687500, 0.1601562501, 0.5898437503, 0.0820312500, 0.3554687502, 0.6054687503, 0.2148437501 }, - { 0.7929687504, 0.6132812503, 0.3789062502, 0.5351562502, 0.8085937504, 0.3867187502, 0.3085937501, 0.4570312502, 0.8867187504, 0.5429687503, 0.6601562503, 0.0898437500, 0.5820312503, 0.8554687504, 0.1054687500, 0.7148437503 }, - { 0.5429687503, 0.3632812502, 0.1289062501, 0.2851562501, 0.5585937503, 0.6367187503, 0.0585937500, 0.7070312503, 0.1367187501, 0.7929687504, 0.4101562502, 0.3398437502, 0.3320312502, 0.6054687503, 0.8554687504, 0.9648437504 }, - { 0.0429687500, 0.8632812504, 0.6289062503, 0.7851562504, 0.0585937500, 0.1367187501, 0.5585937503, 0.2070312501, 0.6367187503, 0.2929687501, 0.9101562504, 0.8398437504, 0.8320312504, 0.1054687500, 0.3554687502, 0.4648437502 }, - { 0.0585937500, 0.0664062500, 0.3320312502, 0.3945312502, 0.7617187504, 0.8085937504, 0.1992187501, 0.8164062504, 0.1835937501, 0.6210937503, 0.6445312503, 0.1054687500, 0.1289062501, 0.5585937503, 0.8710937504, 0.4179687502 }, - { 0.5585937503, 0.5664062503, 0.8320312504, 0.8945312504, 0.2617187501, 0.3085937501, 0.6992187503, 0.3164062501, 0.6835937503, 0.1210937501, 0.1445312501, 0.6054687503, 0.6289062503, 0.0585937500, 0.3710937502, 0.9179687504 }, - { 0.8085937504, 0.3164062501, 0.5820312503, 0.1445312501, 0.0117187500, 0.5585937503, 0.9492187504, 0.5664062503, 0.4335937502, 0.3710937502, 0.8945312504, 0.8554687504, 0.3789062502, 0.3085937501, 0.6210937503, 0.6679687503 }, - { 0.3085937501, 0.8164062504, 0.0820312500, 0.6445312503, 0.5117187502, 0.0585937500, 0.4492187502, 0.0664062500, 0.9335937504, 0.8710937504, 0.3945312502, 0.3554687502, 0.8789062504, 0.8085937504, 0.1210937501, 0.1679687501 }, - { 0.4335937502, 0.4414062502, 0.9570312504, 0.2695312501, 0.1367187501, 0.1835937501, 0.0742187500, 0.4414062502, 0.0585937500, 0.4960937502, 0.7695312504, 0.7304687503, 0.0039062500, 0.9335937504, 0.4960937502, 0.2929687501 }, - { 0.9335937504, 0.9414062504, 0.4570312502, 0.7695312504, 0.6367187503, 0.6835937503, 0.5742187503, 0.9414062504, 0.5585937503, 0.9960937505, 0.2695312501, 0.2304687501, 0.5039062502, 0.4335937502, 0.9960937505, 0.7929687504 }, - { 0.6835937503, 0.1914062501, 0.2070312501, 0.0195312500, 0.8867187504, 0.4335937502, 0.8242187504, 0.1914062501, 0.3085937501, 0.7460937503, 0.5195312502, 0.4804687502, 0.2539062501, 0.1835937501, 0.2460937501, 0.5429687503 }, - { 0.1835937501, 0.6914062503, 0.7070312503, 0.5195312502, 0.3867187502, 0.9335937504, 0.3242187502, 0.6914062503, 0.8085937504, 0.2460937501, 0.0195312500, 0.9804687505, 0.7539062504, 0.6835937503, 0.7460937503, 0.0429687500 }, - { 0.2460937501, 0.2539062501, 0.0195312500, 0.8320312504, 0.3242187502, 0.9960937505, 0.1367187501, 0.1289062501, 0.1210937501, 0.5585937503, 0.0820312500, 0.7929687504, 0.6914062503, 0.2460937501, 0.9335937504, 0.8554687504 }, - { 0.7460937503, 0.7539062504, 0.5195312502, 0.3320312502, 0.8242187504, 0.4960937502, 0.6367187503, 0.6289062503, 0.6210937503, 0.0585937500, 0.5820312503, 0.2929687501, 0.1914062501, 0.7460937503, 0.4335937502, 0.3554687502 }, - { 0.9960937505, 0.0039062500, 0.7695312504, 0.5820312503, 0.5742187503, 0.7460937503, 0.8867187504, 0.3789062502, 0.3710937502, 0.3085937501, 0.3320312502, 0.0429687500, 0.9414062504, 0.9960937505, 0.6835937503, 0.1054687500 }, - { 0.4960937502, 0.5039062502, 0.2695312501, 0.0820312500, 0.0742187500, 0.2460937501, 0.3867187502, 0.8789062504, 0.8710937504, 0.8085937504, 0.8320312504, 0.5429687503, 0.4414062502, 0.4960937502, 0.1835937501, 0.6054687503 }, - { 0.3710937502, 0.1289062501, 0.6445312503, 0.9570312504, 0.6992187503, 0.1210937501, 0.0117187500, 0.5039062502, 0.2460937501, 0.4335937502, 0.4570312502, 0.4179687502, 0.5664062503, 0.3710937502, 0.3085937501, 0.9804687505 }, - { 0.8710937504, 0.6289062503, 0.1445312501, 0.4570312502, 0.1992187501, 0.6210937503, 0.5117187502, 0.0039062500, 0.7460937503, 0.9335937504, 0.9570312504, 0.9179687504, 0.0664062500, 0.8710937504, 0.8085937504, 0.4804687502 }, - { 0.6210937503, 0.3789062502, 0.3945312502, 0.7070312503, 0.4492187502, 0.3710937502, 0.7617187504, 0.7539062504, 0.4960937502, 0.6835937503, 0.2070312501, 0.6679687503, 0.8164062504, 0.6210937503, 0.0585937500, 0.2304687501 }, - { 0.1210937501, 0.8789062504, 0.8945312504, 0.2070312501, 0.9492187504, 0.8710937504, 0.2617187501, 0.2539062501, 0.9960937505, 0.1835937501, 0.7070312503, 0.1679687501, 0.3164062501, 0.1210937501, 0.5585937503, 0.7304687503 }, - { 0.0898437500, 0.4101562502, 0.5507812503, 0.0507812500, 0.5429687503, 0.5898437503, 0.7304687503, 0.0351562500, 0.9023437504, 0.9648437504, 0.8007812504, 0.7617187504, 0.9726562505, 0.6523437503, 0.0898437500, 0.8867187504 }, - { 0.5898437503, 0.9101562504, 0.0507812500, 0.5507812503, 0.0429687500, 0.0898437500, 0.2304687501, 0.5351562502, 0.4023437502, 0.4648437502, 0.3007812501, 0.2617187501, 0.4726562502, 0.1523437501, 0.5898437503, 0.3867187502 }, - { 0.8398437504, 0.1601562501, 0.3007812501, 0.3007812501, 0.2929687501, 0.8398437504, 0.4804687502, 0.2851562501, 0.6523437503, 0.2148437501, 0.5507812503, 0.0117187500, 0.7226562503, 0.4023437502, 0.3398437502, 0.1367187501 }, - { 0.3398437502, 0.6601562503, 0.8007812504, 0.8007812504, 0.7929687504, 0.3398437502, 0.9804687505, 0.7851562504, 0.1523437501, 0.7148437503, 0.0507812500, 0.5117187502, 0.2226562501, 0.9023437504, 0.8398437504, 0.6367187503 }, - { 0.4648437502, 0.0351562500, 0.1757812501, 0.1757812501, 0.4179687502, 0.4648437502, 0.6054687503, 0.6601562503, 0.7773437504, 0.0898437500, 0.6757812503, 0.3867187502, 0.8476562504, 0.7773437504, 0.7148437503, 0.7617187504 }, - { 0.9648437504, 0.5351562502, 0.6757812503, 0.6757812503, 0.9179687504, 0.9648437504, 0.1054687500, 0.1601562501, 0.2773437501, 0.5898437503, 0.1757812501, 0.8867187504, 0.3476562502, 0.2773437501, 0.2148437501, 0.2617187501 }, - { 0.7148437503, 0.2851562501, 0.9257812504, 0.4257812502, 0.6679687503, 0.2148437501, 0.3554687502, 0.9101562504, 0.5273437502, 0.8398437504, 0.9257812504, 0.6367187503, 0.5976562503, 0.0273437500, 0.9648437504, 0.0117187500 }, - { 0.2148437501, 0.7851562504, 0.4257812502, 0.9257812504, 0.1679687501, 0.7148437503, 0.8554687504, 0.4101562502, 0.0273437500, 0.3398437502, 0.4257812502, 0.1367187501, 0.0976562500, 0.5273437502, 0.4648437502, 0.5117187502 }, - { 0.1523437501, 0.2226562501, 0.8632812504, 0.7382812503, 0.1054687500, 0.6523437503, 0.6679687503, 0.9726562505, 0.8398437504, 0.9023437504, 0.4882812502, 0.0742187500, 0.4101562502, 0.0898437500, 0.1523437501, 0.3242187502 }, - { 0.6523437503, 0.7226562503, 0.3632812502, 0.2382812501, 0.6054687503, 0.1523437501, 0.1679687501, 0.4726562502, 0.3398437502, 0.4023437502, 0.9882812505, 0.5742187503, 0.9101562504, 0.5898437503, 0.6523437503, 0.8242187504 }, - { 0.9023437504, 0.4726562502, 0.1132812501, 0.9882812505, 0.8554687504, 0.9023437504, 0.4179687502, 0.7226562503, 0.5898437503, 0.1523437501, 0.2382812501, 0.8242187504, 0.1601562501, 0.8398437504, 0.4023437502, 0.5742187503 }, - { 0.4023437502, 0.9726562505, 0.6132812503, 0.4882812502, 0.3554687502, 0.4023437502, 0.9179687504, 0.2226562501, 0.0898437500, 0.6523437503, 0.7382812503, 0.3242187502, 0.6601562503, 0.3398437502, 0.9023437504, 0.0742187500 }, - { 0.2773437501, 0.3476562502, 0.4882812502, 0.6132812503, 0.9804687505, 0.2773437501, 0.5429687503, 0.3476562502, 0.9648437504, 0.0273437500, 0.1132812501, 0.6992187503, 0.2851562501, 0.4648437502, 0.5273437502, 0.4492187502 }, - { 0.7773437504, 0.8476562504, 0.9882812505, 0.1132812501, 0.4804687502, 0.7773437504, 0.0429687500, 0.8476562504, 0.4648437502, 0.5273437502, 0.6132812503, 0.1992187501, 0.7851562504, 0.9648437504, 0.0273437500, 0.9492187504 }, - { 0.5273437502, 0.0976562500, 0.7382812503, 0.8632812504, 0.2304687501, 0.0273437500, 0.2929687501, 0.0976562500, 0.7148437503, 0.7773437504, 0.3632812502, 0.4492187502, 0.0351562500, 0.7148437503, 0.7773437504, 0.6992187503 }, - { 0.0273437500, 0.5976562503, 0.2382812501, 0.3632812502, 0.7304687503, 0.5273437502, 0.7929687504, 0.5976562503, 0.2148437501, 0.2773437501, 0.8632812504, 0.9492187504, 0.5351562502, 0.2148437501, 0.2773437501, 0.1992187501 }, - { 0.0195312500, 0.1992187501, 0.7304687503, 0.2460937501, 0.2539062501, 0.7070312503, 0.0664062500, 0.8085937504, 0.5195312502, 0.8007812504, 0.2460937501, 0.6757812503, 0.9023437504, 0.9570312504, 0.2539062501, 0.4726562502 }, - { 0.5195312502, 0.6992187503, 0.2304687501, 0.7460937503, 0.7539062504, 0.2070312501, 0.5664062503, 0.3085937501, 0.0195312500, 0.3007812501, 0.7460937503, 0.1757812501, 0.4023437502, 0.4570312502, 0.7539062504, 0.9726562505 }, - { 0.7695312504, 0.4492187502, 0.4804687502, 0.4960937502, 0.5039062502, 0.9570312504, 0.8164062504, 0.5585937503, 0.7695312504, 0.0507812500, 0.4960937502, 0.4257812502, 0.6523437503, 0.2070312501, 0.0039062500, 0.7226562503 }, - { 0.2695312501, 0.9492187504, 0.9804687505, 0.9960937505, 0.0039062500, 0.4570312502, 0.3164062501, 0.0585937500, 0.2695312501, 0.5507812503, 0.9960937505, 0.9257812504, 0.1523437501, 0.7070312503, 0.5039062502, 0.2226562501 }, - { 0.3945312502, 0.3242187502, 0.1054687500, 0.1210937501, 0.6289062503, 0.3320312502, 0.1914062501, 0.4335937502, 0.6445312503, 0.1757812501, 0.3710937502, 0.0507812500, 0.7773437504, 0.5820312503, 0.8789062504, 0.3476562502 }, - { 0.8945312504, 0.8242187504, 0.6054687503, 0.6210937503, 0.1289062501, 0.8320312504, 0.6914062503, 0.9335937504, 0.1445312501, 0.6757812503, 0.8710937504, 0.5507812503, 0.2773437501, 0.0820312500, 0.3789062502, 0.8476562504 }, - { 0.6445312503, 0.0742187500, 0.8554687504, 0.3710937502, 0.3789062502, 0.0820312500, 0.9414062504, 0.1835937501, 0.8945312504, 0.9257812504, 0.1210937501, 0.8007812504, 0.5273437502, 0.3320312502, 0.6289062503, 0.5976562503 }, - { 0.1445312501, 0.5742187503, 0.3554687502, 0.8710937504, 0.8789062504, 0.5820312503, 0.4414062502, 0.6835937503, 0.3945312502, 0.4257812502, 0.6210937503, 0.3007812501, 0.0273437500, 0.8320312504, 0.1289062501, 0.0976562500 }, - { 0.2070312501, 0.3867187502, 0.9179687504, 0.5585937503, 0.8164062504, 0.5195312502, 0.0039062500, 0.2460937501, 0.7070312503, 0.8632812504, 0.5585937503, 0.4882812502, 0.4648437502, 0.2695312501, 0.4414062502, 0.7851562504 }, - { 0.7070312503, 0.8867187504, 0.4179687502, 0.0585937500, 0.3164062501, 0.0195312500, 0.5039062502, 0.7460937503, 0.2070312501, 0.3632812502, 0.0585937500, 0.9882812505, 0.9648437504, 0.7695312504, 0.9414062504, 0.2851562501 }, - { 0.9570312504, 0.1367187501, 0.1679687501, 0.8085937504, 0.0664062500, 0.7695312504, 0.7539062504, 0.4960937502, 0.9570312504, 0.1132812501, 0.8085937504, 0.7382812503, 0.2148437501, 0.5195312502, 0.1914062501, 0.0351562500 }, - { 0.4570312502, 0.6367187503, 0.6679687503, 0.3085937501, 0.5664062503, 0.2695312501, 0.2539062501, 0.9960937505, 0.4570312502, 0.6132812503, 0.3085937501, 0.2382812501, 0.7148437503, 0.0195312500, 0.6914062503, 0.5351562502 }, - { 0.3320312502, 0.0117187500, 0.2929687501, 0.6835937503, 0.1914062501, 0.3945312502, 0.1289062501, 0.6210937503, 0.5820312503, 0.2382812501, 0.9335937504, 0.8632812504, 0.3398437502, 0.1445312501, 0.8164062504, 0.9101562504 }, - { 0.8320312504, 0.5117187502, 0.7929687504, 0.1835937501, 0.6914062503, 0.8945312504, 0.6289062503, 0.1210937501, 0.0820312500, 0.7382812503, 0.4335937502, 0.3632812502, 0.8398437504, 0.6445312503, 0.3164062501, 0.4101562502 }, - { 0.5820312503, 0.2617187501, 0.5429687503, 0.9335937504, 0.9414062504, 0.1445312501, 0.8789062504, 0.8710937504, 0.8320312504, 0.9882812505, 0.6835937503, 0.1132812501, 0.0898437500, 0.8945312504, 0.5664062503, 0.1601562501 }, - { 0.0820312500, 0.7617187504, 0.0429687500, 0.4335937502, 0.4414062502, 0.6445312503, 0.3789062502, 0.3710937502, 0.3320312502, 0.4882812502, 0.1835937501, 0.6132812503, 0.5898437503, 0.3945312502, 0.0664062500, 0.6601562503 }, - { 0.1132812501, 0.2929687501, 0.3867187502, 0.3398437502, 0.0351562500, 0.9257812504, 0.5976562503, 0.0898437500, 0.3007812501, 0.6445312503, 0.3398437502, 0.4570312502, 0.2460937501, 0.8632812504, 0.5351562502, 0.9414062504 }, - { 0.6132812503, 0.7929687504, 0.8867187504, 0.8398437504, 0.5351562502, 0.4257812502, 0.0976562500, 0.5898437503, 0.8007812504, 0.1445312501, 0.8398437504, 0.9570312504, 0.7460937503, 0.3632812502, 0.0351562500, 0.4414062502 }, - { 0.8632812504, 0.0429687500, 0.6367187503, 0.0898437500, 0.7851562504, 0.6757812503, 0.3476562502, 0.3398437502, 0.0507812500, 0.3945312502, 0.0898437500, 0.7070312503, 0.4960937502, 0.1132812501, 0.7851562504, 0.1914062501 }, - { 0.3632812502, 0.5429687503, 0.1367187501, 0.5898437503, 0.2851562501, 0.1757812501, 0.8476562504, 0.8398437504, 0.5507812503, 0.8945312504, 0.5898437503, 0.2070312501, 0.9960937505, 0.6132812503, 0.2851562501, 0.6914062503 }, - { 0.4882812502, 0.1679687501, 0.7617187504, 0.4648437502, 0.9101562504, 0.0507812500, 0.7226562503, 0.7148437503, 0.4257812502, 0.2695312501, 0.2148437501, 0.8320312504, 0.1210937501, 0.7382812503, 0.1601562501, 0.8164062504 }, - { 0.9882812505, 0.6679687503, 0.2617187501, 0.9648437504, 0.4101562502, 0.5507812503, 0.2226562501, 0.2148437501, 0.9257812504, 0.7695312504, 0.7148437503, 0.3320312502, 0.6210937503, 0.2382812501, 0.6601562503, 0.3164062501 }, - { 0.7382812503, 0.4179687502, 0.0117187500, 0.2148437501, 0.1601562501, 0.3007812501, 0.4726562502, 0.9648437504, 0.1757812501, 0.5195312502, 0.4648437502, 0.0820312500, 0.3710937502, 0.4882812502, 0.4101562502, 0.0664062500 }, - { 0.2382812501, 0.9179687504, 0.5117187502, 0.7148437503, 0.6601562503, 0.8007812504, 0.9726562505, 0.4648437502, 0.6757812503, 0.0195312500, 0.9648437504, 0.5820312503, 0.8710937504, 0.9882812505, 0.9101562504, 0.5664062503 }, - { 0.1757812501, 0.1054687500, 0.1992187501, 0.9023437504, 0.5976562503, 0.8632812504, 0.5351562502, 0.9023437504, 0.4882812502, 0.7070312503, 0.9023437504, 0.6445312503, 0.6835937503, 0.4257812502, 0.7226562503, 0.2539062501 }, - { 0.6757812503, 0.6054687503, 0.6992187503, 0.4023437502, 0.0976562500, 0.3632812502, 0.0351562500, 0.4023437502, 0.9882812505, 0.2070312501, 0.4023437502, 0.1445312501, 0.1835937501, 0.9257812504, 0.2226562501, 0.7539062504 }, - { 0.9257812504, 0.3554687502, 0.9492187504, 0.6523437503, 0.3476562502, 0.6132812503, 0.2851562501, 0.6523437503, 0.2382812501, 0.4570312502, 0.6523437503, 0.3945312502, 0.9335937504, 0.6757812503, 0.9726562505, 0.5039062502 }, - { 0.4257812502, 0.8554687504, 0.4492187502, 0.1523437501, 0.8476562504, 0.1132812501, 0.7851562504, 0.1523437501, 0.7382812503, 0.9570312504, 0.1523437501, 0.8945312504, 0.4335937502, 0.1757812501, 0.4726562502, 0.0039062500 }, - { 0.3007812501, 0.4804687502, 0.5742187503, 0.7773437504, 0.4726562502, 0.2382812501, 0.6601562503, 0.2773437501, 0.3632812502, 0.3320312502, 0.5273437502, 0.0195312500, 0.5585937503, 0.0507812500, 0.0976562500, 0.3789062502 }, - { 0.8007812504, 0.9804687505, 0.0742187500, 0.2773437501, 0.9726562505, 0.7382812503, 0.1601562501, 0.7773437504, 0.8632812504, 0.8320312504, 0.0273437500, 0.5195312502, 0.0585937500, 0.5507812503, 0.5976562503, 0.8789062504 }, - { 0.5507812503, 0.2304687501, 0.3242187502, 0.5273437502, 0.7226562503, 0.4882812502, 0.4101562502, 0.0273437500, 0.1132812501, 0.5820312503, 0.7773437504, 0.7695312504, 0.8085937504, 0.8007812504, 0.3476562502, 0.6289062503 }, - { 0.0507812500, 0.7304687503, 0.8242187504, 0.0273437500, 0.2226562501, 0.9882812505, 0.9101562504, 0.5273437502, 0.6132812503, 0.0820312500, 0.2773437501, 0.2695312501, 0.3085937501, 0.3007812501, 0.8476562504, 0.1289062501 }, - { 0.0351562500, 0.4648437502, 0.1523437501, 0.6679687503, 0.9570312504, 0.0664062500, 0.3320312502, 0.3867187502, 0.0664062500, 0.7539062504, 0.0429687500, 0.5351562502, 0.7304687503, 0.8476562504, 0.3632812502, 0.2382812501 }, - { 0.5351562502, 0.9648437504, 0.6523437503, 0.1679687501, 0.4570312502, 0.5664062503, 0.8320312504, 0.8867187504, 0.5664062503, 0.2539062501, 0.5429687503, 0.0351562500, 0.2304687501, 0.3476562502, 0.8632812504, 0.7382812503 }, - { 0.7851562504, 0.2148437501, 0.9023437504, 0.9179687504, 0.2070312501, 0.3164062501, 0.5820312503, 0.1367187501, 0.3164062501, 0.0039062500, 0.2929687501, 0.2851562501, 0.9804687505, 0.0976562500, 0.1132812501, 0.9882812505 }, - { 0.2851562501, 0.7148437503, 0.4023437502, 0.4179687502, 0.7070312503, 0.8164062504, 0.0820312500, 0.6367187503, 0.8164062504, 0.5039062502, 0.7929687504, 0.7851562504, 0.4804687502, 0.5976562503, 0.6132812503, 0.4882812502 } + { 0.0117187500, 0.3320312500, 0.2929687500, 0.1914062500, 0.9023437500, 0.6757812500, 0.8632812500, 0.2460937500, 0.1054687500, 0.8164062500, 0.7382812500, 0.7382812500, 0.8164062500, 0.8789062500, 0.0273437500, 0.7617187500 }, + { 0.5117187500, 0.8320312500, 0.7929687500, 0.6914062500, 0.4023437500, 0.1757812500, 0.3632812500, 0.7460937500, 0.6054687500, 0.3164062500, 0.2382812500, 0.2382812500, 0.3164062500, 0.3789062500, 0.5273437500, 0.2617187500 }, + { 0.7617187500, 0.0820312500, 0.0429687500, 0.4414062500, 0.1523437500, 0.4257812500, 0.6132812500, 0.9960937500, 0.8554687500, 0.0664062500, 0.4882812500, 0.4882812500, 0.5664062500, 0.6289062500, 0.7773437500, 0.5117187500 }, + { 0.2617187500, 0.5820312500, 0.5429687500, 0.9414062500, 0.6523437500, 0.9257812500, 0.1132812500, 0.4960937500, 0.3554687500, 0.5664062500, 0.9882812500, 0.9882812500, 0.0664062500, 0.1289062500, 0.2773437500, 0.0117187500 }, + { 0.3867187500, 0.2070312500, 0.9179687500, 0.8164062500, 0.5273437500, 0.5507812500, 0.7382812500, 0.8710937500, 0.9804687500, 0.4414062500, 0.3632812500, 0.8632812500, 0.6914062500, 0.2539062500, 0.4023437500, 0.1367187500 }, + { 0.8867187500, 0.7070312500, 0.4179687500, 0.3164062500, 0.0273437500, 0.0507812500, 0.2382812500, 0.3710937500, 0.4804687500, 0.9414062500, 0.8632812500, 0.3632812500, 0.1914062500, 0.7539062500, 0.9023437500, 0.6367187500 }, + { 0.6367187500, 0.4570312500, 0.6679687500, 0.5664062500, 0.2773437500, 0.3007812500, 0.9882812500, 0.1210937500, 0.2304687500, 0.6914062500, 0.6132812500, 0.1132812500, 0.9414062500, 0.0039062500, 0.6523437500, 0.3867187500 }, + { 0.1367187500, 0.9570312500, 0.1679687500, 0.0664062500, 0.7773437500, 0.8007812500, 0.4882812500, 0.6210937500, 0.7304687500, 0.1914062500, 0.1132812500, 0.6132812500, 0.4414062500, 0.5039062500, 0.1523437500, 0.8867187500 }, + { 0.1992187500, 0.0195312500, 0.7304687500, 0.2539062500, 0.4648437500, 0.9882812500, 0.6757812500, 0.8085937500, 0.9179687500, 0.5039062500, 0.0507812500, 0.6757812500, 0.1289062500, 0.0664062500, 0.8398437500, 0.1992187500 }, + { 0.6992187500, 0.5195312500, 0.2304687500, 0.7539062500, 0.9648437500, 0.4882812500, 0.1757812500, 0.3085937500, 0.4179687500, 0.0039062500, 0.5507812500, 0.1757812500, 0.6289062500, 0.5664062500, 0.3398437500, 0.6992187500 }, + { 0.9492187500, 0.2695312500, 0.9804687500, 0.0039062500, 0.7148437500, 0.2382812500, 0.9257812500, 0.0585937500, 0.1679687500, 0.2539062500, 0.8007812500, 0.4257812500, 0.3789062500, 0.3164062500, 0.0898437500, 0.4492187500 }, + { 0.4492187500, 0.7695312500, 0.4804687500, 0.5039062500, 0.2148437500, 0.7382812500, 0.4257812500, 0.5585937500, 0.6679687500, 0.7539062500, 0.3007812500, 0.9257812500, 0.8789062500, 0.8164062500, 0.5898437500, 0.9492187500 }, + { 0.3242187500, 0.3945312500, 0.1054687500, 0.6289062500, 0.0898437500, 0.8632812500, 0.8007812500, 0.1835937500, 0.0429687500, 0.1289062500, 0.9257812500, 0.8007812500, 0.2539062500, 0.6914062500, 0.7148437500, 0.8242187500 }, + { 0.8242187500, 0.8945312500, 0.6054687500, 0.1289062500, 0.5898437500, 0.3632812500, 0.3007812500, 0.6835937500, 0.5429687500, 0.6289062500, 0.4257812500, 0.3007812500, 0.7539062500, 0.1914062500, 0.2148437500, 0.3242187500 }, + { 0.5742187500, 0.1445312500, 0.3554687500, 0.8789062500, 0.8398437500, 0.1132812500, 0.5507812500, 0.9335937500, 0.7929687500, 0.8789062500, 0.1757812500, 0.0507812500, 0.0039062500, 0.9414062500, 0.4648437500, 0.5742187500 }, + { 0.0742187500, 0.6445312500, 0.8554687500, 0.3789062500, 0.3398437500, 0.6132812500, 0.0507812500, 0.4335937500, 0.2929687500, 0.3789062500, 0.6757812500, 0.5507812500, 0.5039062500, 0.4414062500, 0.9648437500, 0.0742187500 }, + { 0.1054687500, 0.1757812500, 0.1992187500, 0.5976562500, 0.6835937500, 0.3320312500, 0.3320312500, 0.9023437500, 0.3867187500, 0.9726562500, 0.6445312500, 0.8320312500, 0.4726562500, 0.2851562500, 0.3710937500, 0.7929687500 }, + { 0.6054687500, 0.6757812500, 0.6992187500, 0.0976562500, 0.1835937500, 0.8320312500, 0.8320312500, 0.4023437500, 0.8867187500, 0.4726562500, 0.1445312500, 0.3320312500, 0.9726562500, 0.7851562500, 0.8710937500, 0.2929687500 }, + { 0.8554687500, 0.4257812500, 0.4492187500, 0.8476562500, 0.4335937500, 0.5820312500, 0.0820312500, 0.1523437500, 0.6367187500, 0.2226562500, 0.3945312500, 0.0820312500, 0.2226562500, 0.0351562500, 0.6210937500, 0.5429687500 }, + { 0.3554687500, 0.9257812500, 0.9492187500, 0.3476562500, 0.9335937500, 0.0820312500, 0.5820312500, 0.6523437500, 0.1367187500, 0.7226562500, 0.8945312500, 0.5820312500, 0.7226562500, 0.5351562500, 0.1210937500, 0.0429687500 }, + { 0.4804687500, 0.3007812500, 0.5742187500, 0.4726562500, 0.8085937500, 0.4570312500, 0.2070312500, 0.0273437500, 0.5117187500, 0.3476562500, 0.2695312500, 0.7070312500, 0.0976562500, 0.9101562500, 0.2460937500, 0.1679687500 }, + { 0.9804687500, 0.8007812500, 0.0742187500, 0.9726562500, 0.3085937500, 0.9570312500, 0.7070312500, 0.5273437500, 0.0117187500, 0.8476562500, 0.7695312500, 0.2070312500, 0.5976562500, 0.4101562500, 0.7460937500, 0.6679687500 }, + { 0.7304687500, 0.0507812500, 0.8242187500, 0.2226562500, 0.0585937500, 0.7070312500, 0.4570312500, 0.7773437500, 0.2617187500, 0.5976562500, 0.5195312500, 0.4570312500, 0.3476562500, 0.6601562500, 0.9960937500, 0.4179687500 }, + { 0.2304687500, 0.5507812500, 0.3242187500, 0.7226562500, 0.5585937500, 0.2070312500, 0.9570312500, 0.2773437500, 0.7617187500, 0.0976562500, 0.0195312500, 0.9570312500, 0.8476562500, 0.1601562500, 0.4960937500, 0.9179687500 }, + { 0.1679687500, 0.4882812500, 0.7617187500, 0.9101562500, 0.2460937500, 0.0195312500, 0.1445312500, 0.0898437500, 0.5742187500, 0.6601562500, 0.0820312500, 0.7695312500, 0.5351562500, 0.7226562500, 0.5585937500, 0.2304687500 }, + { 0.6679687500, 0.9882812500, 0.2617187500, 0.4101562500, 0.7460937500, 0.5195312500, 0.6445312500, 0.5898437500, 0.0742187500, 0.1601562500, 0.5820312500, 0.2695312500, 0.0351562500, 0.2226562500, 0.0585937500, 0.7304687500 }, + { 0.9179687500, 0.2382812500, 0.5117187500, 0.6601562500, 0.9960937500, 0.7695312500, 0.3945312500, 0.8398437500, 0.3242187500, 0.4101562500, 0.8320312500, 0.0195312500, 0.7851562500, 0.9726562500, 0.3085937500, 0.4804687500 }, + { 0.4179687500, 0.7382812500, 0.0117187500, 0.1601562500, 0.4960937500, 0.2695312500, 0.8945312500, 0.3398437500, 0.8242187500, 0.9101562500, 0.3320312500, 0.5195312500, 0.2851562500, 0.4726562500, 0.8085937500, 0.9804687500 }, + { 0.2929687500, 0.1132812500, 0.3867187500, 0.0351562500, 0.3710937500, 0.1445312500, 0.2695312500, 0.9648437500, 0.4492187500, 0.0351562500, 0.9570312500, 0.6445312500, 0.9101562500, 0.0976562500, 0.9335937500, 0.8554687500 }, + { 0.7929687500, 0.6132812500, 0.8867187500, 0.5351562500, 0.8710937500, 0.6445312500, 0.7695312500, 0.4648437500, 0.9492187500, 0.5351562500, 0.4570312500, 0.1445312500, 0.4101562500, 0.5976562500, 0.4335937500, 0.3554687500 }, + { 0.5429687500, 0.3632812500, 0.1367187500, 0.2851562500, 0.6210937500, 0.8945312500, 0.0195312500, 0.2148437500, 0.6992187500, 0.7851562500, 0.2070312500, 0.3945312500, 0.6601562500, 0.3476562500, 0.1835937500, 0.6054687500 }, + { 0.0429687500, 0.8632812500, 0.6367187500, 0.7851562500, 0.1210937500, 0.3945312500, 0.5195312500, 0.7148437500, 0.1992187500, 0.2851562500, 0.7070312500, 0.8945312500, 0.1601562500, 0.8476562500, 0.6835937500, 0.1054687500 }, + { 0.0585937500, 0.0664062500, 0.9960937500, 0.7382812500, 0.7617187500, 0.2539062500, 0.0664062500, 0.5742187500, 0.9023437500, 0.8632812500, 0.8476562500, 0.2851562500, 0.6445312500, 0.1132812500, 0.9804687500, 0.8710937500 }, + { 0.5585937500, 0.5664062500, 0.4960937500, 0.2382812500, 0.2617187500, 0.7539062500, 0.5664062500, 0.0742187500, 0.4023437500, 0.3632812500, 0.3476562500, 0.7851562500, 0.1445312500, 0.6132812500, 0.4804687500, 0.3710937500 }, + { 0.8085937500, 0.3164062500, 0.7460937500, 0.9882812500, 0.0117187500, 0.5039062500, 0.3164062500, 0.3242187500, 0.1523437500, 0.1132812500, 0.0976562500, 0.5351562500, 0.8945312500, 0.3632812500, 0.2304687500, 0.6210937500 }, + { 0.3085937500, 0.8164062500, 0.2460937500, 0.4882812500, 0.5117187500, 0.0039062500, 0.8164062500, 0.8242187500, 0.6523437500, 0.6132812500, 0.5976562500, 0.0351562500, 0.3945312500, 0.8632812500, 0.7304687500, 0.1210937500 }, + { 0.4335937500, 0.4414062500, 0.3710937500, 0.3632812500, 0.6367187500, 0.3789062500, 0.4414062500, 0.4492187500, 0.0273437500, 0.4882812500, 0.2226562500, 0.1601562500, 0.7695312500, 0.7382812500, 0.6054687500, 0.2460937500 }, + { 0.9335937500, 0.9414062500, 0.8710937500, 0.8632812500, 0.1367187500, 0.8789062500, 0.9414062500, 0.9492187500, 0.5273437500, 0.9882812500, 0.7226562500, 0.6601562500, 0.2695312500, 0.2382812500, 0.1054687500, 0.7460937500 }, + { 0.6835937500, 0.1914062500, 0.1210937500, 0.1132812500, 0.3867187500, 0.6289062500, 0.1914062500, 0.6992187500, 0.7773437500, 0.7382812500, 0.9726562500, 0.9101562500, 0.5195312500, 0.9882812500, 0.3554687500, 0.4960937500 }, + { 0.1835937500, 0.6914062500, 0.6210937500, 0.6132812500, 0.8867187500, 0.1289062500, 0.6914062500, 0.1992187500, 0.2773437500, 0.2382812500, 0.4726562500, 0.4101562500, 0.0195312500, 0.4882812500, 0.8554687500, 0.9960937500 }, + { 0.2460937500, 0.2539062500, 0.0585937500, 0.8007812500, 0.3242187500, 0.0664062500, 0.3789062500, 0.3867187500, 0.0898437500, 0.5507812500, 0.4101562500, 0.3476562500, 0.3320312500, 0.9257812500, 0.1679687500, 0.1835937500 }, + { 0.7460937500, 0.7539062500, 0.5585937500, 0.3007812500, 0.8242187500, 0.5664062500, 0.8789062500, 0.8867187500, 0.5898437500, 0.0507812500, 0.9101562500, 0.8476562500, 0.8320312500, 0.4257812500, 0.6679687500, 0.6835937500 }, + { 0.9960937500, 0.0039062500, 0.3085937500, 0.5507812500, 0.5742187500, 0.8164062500, 0.1289062500, 0.6367187500, 0.8398437500, 0.3007812500, 0.6601562500, 0.5976562500, 0.0820312500, 0.6757812500, 0.9179687500, 0.4335937500 }, + { 0.4960937500, 0.5039062500, 0.8085937500, 0.0507812500, 0.0742187500, 0.3164062500, 0.6289062500, 0.1367187500, 0.3398437500, 0.8007812500, 0.1601562500, 0.0976562500, 0.5820312500, 0.1757812500, 0.4179687500, 0.9335937500 }, + { 0.3710937500, 0.1289062500, 0.6835937500, 0.1757812500, 0.1992187500, 0.1914062500, 0.0039062500, 0.5117187500, 0.9648437500, 0.1757812500, 0.5351562500, 0.2226562500, 0.2070312500, 0.3007812500, 0.2929687500, 0.8085937500 }, + { 0.8710937500, 0.6289062500, 0.1835937500, 0.6757812500, 0.6992187500, 0.6914062500, 0.5039062500, 0.0117187500, 0.4648437500, 0.6757812500, 0.0351562500, 0.7226562500, 0.7070312500, 0.8007812500, 0.7929687500, 0.3085937500 }, + { 0.6210937500, 0.3789062500, 0.9335937500, 0.4257812500, 0.9492187500, 0.9414062500, 0.2539062500, 0.2617187500, 0.2148437500, 0.9257812500, 0.2851562500, 0.9726562500, 0.4570312500, 0.0507812500, 0.5429687500, 0.5585937500 }, + { 0.1210937500, 0.8789062500, 0.4335937500, 0.9257812500, 0.4492187500, 0.4414062500, 0.7539062500, 0.7617187500, 0.7148437500, 0.4257812500, 0.7851562500, 0.4726562500, 0.9570312500, 0.5507812500, 0.0429687500, 0.0585937500 }, + { 0.0898437500, 0.4101562500, 0.5273437500, 0.0820312500, 0.5429687500, 0.7226562500, 0.5976562500, 0.2929687500, 0.6210937500, 0.9570312500, 0.7539062500, 0.1289062500, 0.0507812500, 0.7070312500, 0.6367187500, 0.8398437500 }, + { 0.5898437500, 0.9101562500, 0.0273437500, 0.5820312500, 0.0429687500, 0.2226562500, 0.0976562500, 0.7929687500, 0.1210937500, 0.4570312500, 0.2539062500, 0.6289062500, 0.5507812500, 0.2070312500, 0.1367187500, 0.3398437500 }, + { 0.8398437500, 0.1601562500, 0.7773437500, 0.3320312500, 0.2929687500, 0.4726562500, 0.8476562500, 0.5429687500, 0.3710937500, 0.2070312500, 0.0039062500, 0.8789062500, 0.3007812500, 0.9570312500, 0.3867187500, 0.5898437500 }, + { 0.3398437500, 0.6601562500, 0.2773437500, 0.8320312500, 0.7929687500, 0.9726562500, 0.3476562500, 0.0429687500, 0.8710937500, 0.7070312500, 0.5039062500, 0.3789062500, 0.8007812500, 0.4570312500, 0.8867187500, 0.0898437500 }, + { 0.4648437500, 0.0351562500, 0.1523437500, 0.9570312500, 0.9179687500, 0.5976562500, 0.9726562500, 0.6679687500, 0.4960937500, 0.3320312500, 0.1289062500, 0.2539062500, 0.4257812500, 0.0820312500, 0.7617187500, 0.2148437500 }, + { 0.9648437500, 0.5351562500, 0.6523437500, 0.4570312500, 0.4179687500, 0.0976562500, 0.4726562500, 0.1679687500, 0.9960937500, 0.8320312500, 0.6289062500, 0.7539062500, 0.9257812500, 0.5820312500, 0.2617187500, 0.7148437500 }, + { 0.7148437500, 0.2851562500, 0.4023437500, 0.7070312500, 0.1679687500, 0.3476562500, 0.7226562500, 0.4179687500, 0.7460937500, 0.5820312500, 0.8789062500, 0.5039062500, 0.1757812500, 0.3320312500, 0.0117187500, 0.4648437500 }, + { 0.2148437500, 0.7851562500, 0.9023437500, 0.2070312500, 0.6679687500, 0.8476562500, 0.2226562500, 0.9179687500, 0.2460937500, 0.0820312500, 0.3789062500, 0.0039062500, 0.6757812500, 0.8320312500, 0.5117187500, 0.9648437500 }, + { 0.1523437500, 0.2226562500, 0.4648437500, 0.3945312500, 0.1054687500, 0.9101562500, 0.9101562500, 0.7304687500, 0.4335937500, 0.6445312500, 0.4414062500, 0.1914062500, 0.9882812500, 0.2695312500, 0.4492187500, 0.1523437500 }, + { 0.6523437500, 0.7226562500, 0.9648437500, 0.8945312500, 0.6054687500, 0.4101562500, 0.4101562500, 0.2304687500, 0.9335937500, 0.1445312500, 0.9414062500, 0.6914062500, 0.4882812500, 0.7695312500, 0.9492187500, 0.6523437500 }, + { 0.9023437500, 0.4726562500, 0.2148437500, 0.1445312500, 0.8554687500, 0.1601562500, 0.6601562500, 0.4804687500, 0.6835937500, 0.3945312500, 0.6914062500, 0.9414062500, 0.7382812500, 0.0195312500, 0.6992187500, 0.4023437500 }, + { 0.4023437500, 0.9726562500, 0.7148437500, 0.6445312500, 0.3554687500, 0.6601562500, 0.1601562500, 0.9804687500, 0.1835937500, 0.8945312500, 0.1914062500, 0.4414062500, 0.2382812500, 0.5195312500, 0.1992187500, 0.9023437500 }, + { 0.2773437500, 0.3476562500, 0.8398437500, 0.5195312500, 0.4804687500, 0.7851562500, 0.5351562500, 0.3554687500, 0.5585937500, 0.0195312500, 0.5664062500, 0.3164062500, 0.6132812500, 0.8945312500, 0.0742187500, 0.7773437500 }, + { 0.7773437500, 0.8476562500, 0.3398437500, 0.0195312500, 0.9804687500, 0.2851562500, 0.0351562500, 0.8554687500, 0.0585937500, 0.5195312500, 0.0664062500, 0.8164062500, 0.1132812500, 0.3945312500, 0.5742187500, 0.2773437500 }, + { 0.5273437500, 0.0976562500, 0.5898437500, 0.7695312500, 0.7304687500, 0.0351562500, 0.7851562500, 0.6054687500, 0.3085937500, 0.7695312500, 0.3164062500, 0.5664062500, 0.8632812500, 0.6445312500, 0.8242187500, 0.5273437500 }, + { 0.0273437500, 0.5976562500, 0.0898437500, 0.2695312500, 0.2304687500, 0.5351562500, 0.2851562500, 0.1054687500, 0.8085937500, 0.2695312500, 0.8164062500, 0.0664062500, 0.3632812500, 0.1445312500, 0.3242187500, 0.0273437500 }, + { 0.0195312500, 0.1992187500, 0.5976562500, 0.9023437500, 0.2539062500, 0.8710937500, 0.4648437500, 0.0351562500, 0.6445312500, 0.8085937500, 0.3085937500, 0.5273437500, 0.7460937500, 0.4023437500, 0.7851562500, 0.2539062500 }, + { 0.5195312500, 0.6992187500, 0.0976562500, 0.4023437500, 0.7539062500, 0.3710937500, 0.9648437500, 0.5351562500, 0.1445312500, 0.3085937500, 0.8085937500, 0.0273437500, 0.2460937500, 0.9023437500, 0.2851562500, 0.7539062500 }, + { 0.7695312500, 0.4492187500, 0.8476562500, 0.6523437500, 0.5039062500, 0.1210937500, 0.2148437500, 0.7851562500, 0.3945312500, 0.0585937500, 0.5585937500, 0.2773437500, 0.9960937500, 0.1523437500, 0.0351562500, 0.0039062500 }, + { 0.2695312500, 0.9492187500, 0.3476562500, 0.1523437500, 0.0039062500, 0.6210937500, 0.7148437500, 0.2851562500, 0.8945312500, 0.5585937500, 0.0585937500, 0.7773437500, 0.4960937500, 0.6523437500, 0.5351562500, 0.5039062500 }, + { 0.3945312500, 0.3242187500, 0.2226562500, 0.0273437500, 0.1289062500, 0.9960937500, 0.0898437500, 0.9101562500, 0.2695312500, 0.4335937500, 0.6835937500, 0.9023437500, 0.8710937500, 0.7773437500, 0.6601562500, 0.6289062500 }, + { 0.8945312500, 0.8242187500, 0.7226562500, 0.5273437500, 0.6289062500, 0.4960937500, 0.5898437500, 0.4101562500, 0.7695312500, 0.9335937500, 0.1835937500, 0.4023437500, 0.3710937500, 0.2773437500, 0.1601562500, 0.1289062500 }, + { 0.6445312500, 0.0742187500, 0.4726562500, 0.2773437500, 0.8789062500, 0.2460937500, 0.3398437500, 0.1601562500, 0.5195312500, 0.6835937500, 0.4335937500, 0.1523437500, 0.6210937500, 0.5273437500, 0.4101562500, 0.8789062500 }, + { 0.1445312500, 0.5742187500, 0.9726562500, 0.7773437500, 0.3789062500, 0.7460937500, 0.8398437500, 0.6601562500, 0.0195312500, 0.1835937500, 0.9335937500, 0.6523437500, 0.1210937500, 0.0273437500, 0.9101562500, 0.3789062500 }, + { 0.2070312500, 0.3867187500, 0.4101562500, 0.5898437500, 0.8164062500, 0.5585937500, 0.0273437500, 0.9726562500, 0.3320312500, 0.6210937500, 0.9960937500, 0.5898437500, 0.3085937500, 0.5898437500, 0.0976562500, 0.6914062500 }, + { 0.7070312500, 0.8867187500, 0.9101562500, 0.0898437500, 0.3164062500, 0.0585937500, 0.5273437500, 0.4726562500, 0.8320312500, 0.1210937500, 0.4960937500, 0.0898437500, 0.8085937500, 0.0898437500, 0.5976562500, 0.1914062500 }, + { 0.9570312500, 0.1367187500, 0.1601562500, 0.8398437500, 0.0664062500, 0.3085937500, 0.2773437500, 0.2226562500, 0.5820312500, 0.3710937500, 0.2460937500, 0.3398437500, 0.0585937500, 0.8398437500, 0.8476562500, 0.9414062500 }, + { 0.4570312500, 0.6367187500, 0.6601562500, 0.3398437500, 0.5664062500, 0.8085937500, 0.7773437500, 0.7226562500, 0.0820312500, 0.8710937500, 0.7460937500, 0.8398437500, 0.5585937500, 0.3398437500, 0.3476562500, 0.4414062500 }, + { 0.3320312500, 0.0117187500, 0.7851562500, 0.4648437500, 0.6914062500, 0.6835937500, 0.4023437500, 0.0976562500, 0.7070312500, 0.2460937500, 0.1210937500, 0.9648437500, 0.1835937500, 0.2148437500, 0.4726562500, 0.3164062500 }, + { 0.8320312500, 0.5117187500, 0.2851562500, 0.9648437500, 0.1914062500, 0.1835937500, 0.9023437500, 0.5976562500, 0.2070312500, 0.7460937500, 0.6210937500, 0.4648437500, 0.6835937500, 0.7148437500, 0.9726562500, 0.8164062500 }, + { 0.5820312500, 0.2617187500, 0.5351562500, 0.2148437500, 0.4414062500, 0.4335937500, 0.1523437500, 0.8476562500, 0.4570312500, 0.9960937500, 0.8710937500, 0.2148437500, 0.4335937500, 0.4648437500, 0.7226562500, 0.0664062500 }, + { 0.0820312500, 0.7617187500, 0.0351562500, 0.7148437500, 0.9414062500, 0.9335937500, 0.6523437500, 0.3476562500, 0.9570312500, 0.4960937500, 0.3710937500, 0.7148437500, 0.9335937500, 0.9648437500, 0.2226562500, 0.5664062500 }, + { 0.1132812500, 0.2929687500, 0.8789062500, 0.3085937500, 0.0351562500, 0.1523437500, 0.9960937500, 0.8164062500, 0.8632812500, 0.9023437500, 0.3398437500, 0.9335937500, 0.0898437500, 0.8085937500, 0.5664062500, 0.2851562500 }, + { 0.6132812500, 0.7929687500, 0.3789062500, 0.8085937500, 0.5351562500, 0.6523437500, 0.4960937500, 0.3164062500, 0.3632812500, 0.4023437500, 0.8398437500, 0.4335937500, 0.5898437500, 0.3085937500, 0.0664062500, 0.7851562500 }, + { 0.8632812500, 0.0429687500, 0.6289062500, 0.0585937500, 0.7851562500, 0.9023437500, 0.7460937500, 0.0664062500, 0.1132812500, 0.1523437500, 0.5898437500, 0.1835937500, 0.3398437500, 0.5585937500, 0.3164062500, 0.0351562500 }, + { 0.3632812500, 0.5429687500, 0.1289062500, 0.5585937500, 0.2851562500, 0.4023437500, 0.2460937500, 0.5664062500, 0.6132812500, 0.6523437500, 0.0898437500, 0.6835937500, 0.8398437500, 0.0585937500, 0.8164062500, 0.5351562500 }, + { 0.4882812500, 0.1679687500, 0.2539062500, 0.6835937500, 0.4101562500, 0.0273437500, 0.6210937500, 0.1914062500, 0.2382812500, 0.2773437500, 0.7148437500, 0.5585937500, 0.4648437500, 0.4335937500, 0.9414062500, 0.6601562500 }, + { 0.9882812500, 0.6679687500, 0.7539062500, 0.1835937500, 0.9101562500, 0.5273437500, 0.1210937500, 0.6914062500, 0.7382812500, 0.7773437500, 0.2148437500, 0.0585937500, 0.9648437500, 0.9335937500, 0.4414062500, 0.1601562500 }, + { 0.7382812500, 0.4179687500, 0.0039062500, 0.9335937500, 0.6601562500, 0.7773437500, 0.8710937500, 0.9414062500, 0.9882812500, 0.5273437500, 0.4648437500, 0.3085937500, 0.2148437500, 0.1835937500, 0.1914062500, 0.9101562500 }, + { 0.2382812500, 0.9179687500, 0.5039062500, 0.4335937500, 0.1601562500, 0.2773437500, 0.3710937500, 0.4414062500, 0.4882812500, 0.0273437500, 0.9648437500, 0.8085937500, 0.7148437500, 0.6835937500, 0.6914062500, 0.4101562500 }, + { 0.1757812500, 0.1054687500, 0.0664062500, 0.2460937500, 0.5976562500, 0.4648437500, 0.5585937500, 0.1289062500, 0.1757812500, 0.7148437500, 0.9023437500, 0.9960937500, 0.9023437500, 0.2460937500, 0.2539062500, 0.7226562500 }, + { 0.6757812500, 0.6054687500, 0.5664062500, 0.7460937500, 0.0976562500, 0.9648437500, 0.0585937500, 0.6289062500, 0.6757812500, 0.2148437500, 0.4023437500, 0.4960937500, 0.4023437500, 0.7460937500, 0.7539062500, 0.2226562500 }, + { 0.9257812500, 0.3554687500, 0.3164062500, 0.4960937500, 0.3476562500, 0.7148437500, 0.8085937500, 0.8789062500, 0.9257812500, 0.4648437500, 0.1523437500, 0.2460937500, 0.6523437500, 0.4960937500, 0.5039062500, 0.9726562500 }, + { 0.4257812500, 0.8554687500, 0.8164062500, 0.9960937500, 0.8476562500, 0.2148437500, 0.3085937500, 0.3789062500, 0.4257812500, 0.9648437500, 0.6523437500, 0.7460937500, 0.1523437500, 0.9960937500, 0.0039062500, 0.4726562500 }, + { 0.3007812500, 0.4804687500, 0.6914062500, 0.8710937500, 0.9726562500, 0.3398437500, 0.9335937500, 0.7539062500, 0.8007812500, 0.0898437500, 0.0273437500, 0.6210937500, 0.5273437500, 0.6210937500, 0.1289062500, 0.3476562500 }, + { 0.8007812500, 0.9804687500, 0.1914062500, 0.3710937500, 0.4726562500, 0.8398437500, 0.4335937500, 0.2539062500, 0.3007812500, 0.5898437500, 0.5273437500, 0.1210937500, 0.0273437500, 0.1210937500, 0.6289062500, 0.8476562500 }, + { 0.5507812500, 0.2304687500, 0.9414062500, 0.6210937500, 0.2226562500, 0.5898437500, 0.6835937500, 0.0039062500, 0.0507812500, 0.8398437500, 0.7773437500, 0.3710937500, 0.7773437500, 0.8710937500, 0.8789062500, 0.0976562500 }, + { 0.0507812500, 0.7304687500, 0.4414062500, 0.1210937500, 0.7226562500, 0.0898437500, 0.1835937500, 0.5039062500, 0.5507812500, 0.3398437500, 0.2773437500, 0.8710937500, 0.2773437500, 0.3710937500, 0.3789062500, 0.5976562500 }, + { 0.0351562500, 0.4648437500, 0.1757812500, 0.4179687500, 0.3945312500, 0.1992187500, 0.7304687500, 0.6445312500, 0.3476562500, 0.7617187500, 0.1679687500, 0.4492187500, 0.7929687500, 0.6054687500, 0.2070312500, 0.3632812500 }, + { 0.5351562500, 0.9648437500, 0.6757812500, 0.9179687500, 0.8945312500, 0.6992187500, 0.2304687500, 0.1445312500, 0.8476562500, 0.2617187500, 0.6679687500, 0.9492187500, 0.2929687500, 0.1054687500, 0.7070312500, 0.8632812500 }, + { 0.7851562500, 0.2148437500, 0.4257812500, 0.1679687500, 0.6445312500, 0.9492187500, 0.9804687500, 0.3945312500, 0.5976562500, 0.0117187500, 0.9179687500, 0.6992187500, 0.5429687500, 0.8554687500, 0.9570312500, 0.1132812500 }, + { 0.2851562500, 0.7148437500, 0.9257812500, 0.6679687500, 0.1445312500, 0.4492187500, 0.4804687500, 0.8945312500, 0.0976562500, 0.5117187500, 0.4179687500, 0.1992187500, 0.0429687500, 0.3554687500, 0.4570312500, 0.6132812500 } }; QRNG_VALIDATION_TEST_FUNCTIONS(sobol) +QRNG_VALIDATION_TEST_DISCARD(sobol) + +BOOST_AUTO_TEST_CASE( check_generator_limits ) +{ + test_sobol_max_seed(); + test_sobol_max_discard(); + test_sobol_max_dimension(BOOST_RANDOM_SOBOL_MAX_DIMENSION); +} BOOST_AUTO_TEST_CASE( validate_sobol ) { - test_sobol_values(sobol_02_100, 0); - test_sobol_values(sobol_07_100, 128); - test_sobol_values(sobol_16_100, 128); + test_sobol_values(sobol_02_99, 0); + test_sobol_values(sobol_07_100, 127); + test_sobol_values(sobol_16_100, 127); } BOOST_AUTO_TEST_CASE( validate_sobol_seed ) { - test_sobol_seed(sobol_02_100, 0); - test_sobol_seed(sobol_07_100, 128); - test_sobol_seed(sobol_16_100, 128); + test_sobol_seed(sobol_02_99, 0); + test_sobol_seed(sobol_07_100, 127); + test_sobol_seed(sobol_16_100, 127); } BOOST_AUTO_TEST_CASE( validate_sobol_discard ) { - test_sobol_discard(sobol_02_100, 0); - test_sobol_discard(sobol_07_100, 128); - test_sobol_discard(sobol_16_100, 128); + test_sobol_discard(sobol_02_99, 0); + test_sobol_discard(sobol_07_100, 127); + test_sobol_discard(sobol_16_100, 127); } diff --git a/test/test_qrng_functions.hpp b/test/test_qrng_functions.hpp new file mode 100644 index 0000000..6248423 --- /dev/null +++ b/test/test_qrng_functions.hpp @@ -0,0 +1,282 @@ +// Copyright Justinas Vygintas Daugmaudis, 2010-2018. +// Use, modification and distribution is subject to the +// Boost Software License, Version 1.0. (See accompanying +// file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) + +#ifndef TEST_QRNG_FUNCTIONS_HPP_INCLUDED +#define TEST_QRNG_FUNCTIONS_HPP_INCLUDED + +#include +#include + +#include + +namespace test { + +// Invokes operator() precisely n times. This is to check that +// Engine::discard(n) actually has the same effect. +template +inline void trivial_discard(Engine& eng, boost::uintmax_t n) +{ + for( ; n != 0; --n ) eng(); +} + + +template +inline void match_vector(Engine& eng, T (&pt)[Dimension]) +{ + BOOST_REQUIRE_EQUAL( eng.dimension(), Dimension ); // paranoid check + + boost::uniform_real dist; + + for( std::size_t i = 0; i != eng.dimension(); ++i ) + { + T val = dist(eng); + // We want to check that quasi-random number generator values differ no + // more than 0.0006% of their value. + BOOST_CHECK_CLOSE(pt[i], val, 0.0006); + } +} + + +template +inline void expected_values(T (&pt)[N][Dimension], std::size_t skip) +{ + Engine eng(Dimension); + + eng.seed(skip); + + for( std::size_t i = 0; i != N; ++i ) + match_vector(eng, pt[i]); +} + +template +inline void test_zero_seed(std::size_t dimension) +{ + Engine eng(dimension); + + Engine other(dimension); + other.seed(0); + + // Check that states are equal after zero seed. + boost::uniform_real dist; + BOOST_CHECK( eng == other ); + for( std:: size_t i = 0; i != dimension; ++i ) + { + T q_val = dist(eng); + T t_val = dist(other); + BOOST_CHECK_CLOSE(q_val, t_val, 0.0001); + } +} + +template +inline void seed_function(T (&pt)[N][Dimension], std::size_t skip) +{ + // Test zero seed before doing other tests. + test_zero_seed(Dimension); + + Engine eng(Dimension); + for( std::size_t i = 0; i != N; ++i ) + { + // For all N seeds an engine + // and checks if the expected values match. + eng.seed(skip + i); + match_vector(eng, pt[i]); + } +} + +template +inline void discard_function(T (&pt)[N][Dimension], std::size_t skip) +{ + Engine eng(Dimension), trivial(Dimension), streamed(Dimension), initial_state(Dimension); + boost::uniform_real dist; + + const std::size_t element_count = N * Dimension; + const T* pt_array = reinterpret_cast(boost::addressof(pt)); + + std::stringstream ss; + + initial_state.seed(skip); + for (std::size_t step = 0; step != element_count; ++step) + { + // Init to the same state + eng = initial_state; + trivial = initial_state; + + // Discards have to have the same effect + eng.discard(step); + trivial_discard(trivial, step); + + // test serialization to stream + ss.str(std::string()); // clear stream + ss << eng; + ss >> streamed; + + // Therefore, states are equal + BOOST_CHECK( eng == trivial ); + BOOST_CHECK( eng == streamed ); + + // Now, let's check whether they really produce the same sequence + T q_val = dist(eng); + T t_val = dist(trivial); + T s_val = dist(streamed); + BOOST_CHECK_CLOSE(q_val, t_val, 0.0001); + BOOST_CHECK_CLOSE(q_val, s_val, 0.0001); + // ~ BOOST_CHECK(q_val == t_val), but those are floating point values, + // so strict equality check may fail unnecessarily + + // States remain equal! + BOOST_CHECK( eng == trivial ); + BOOST_CHECK( eng == streamed ); + + // We want to check that quasi-random number generator values differ no + // more than 0.0006% of their value. + BOOST_CHECK_CLOSE(pt_array[step], q_val, 0.0006); + } +} + +inline bool accept_all_exceptions(const std::exception& e) +{ + BOOST_TEST_MESSAGE( e.what() ); + return true; +} + +template +void test_max_seed(std::size_t dim) +{ + typedef typename Engine::size_type size_type; + static const size_type maxseed = std::numeric_limits::max(); + + Engine eng(dim); + eng.seed(maxseed-1); // must succeed + eng(); // skip one element + BOOST_REQUIRE_EXCEPTION( eng.seed(maxseed), std::range_error, accept_all_exceptions ); + + Engine other(dim); + other.seed(maxseed-1); // must succeed + other(); // skip one element, too + + // States remain the same even after unsuccessful seeding for eng. + BOOST_CHECK( eng == other ); + BOOST_CHECK( eng() == other() ); +} + +template +void test_max_discard(std::size_t dim) +{ + typedef typename Generator::type engine_type; + + static const boost::uintmax_t maxdiscard = dim * Generator::dimlim(); + + // Max discard limit + { + engine_type eng(dim); + eng.discard(maxdiscard-1); // must succeed + eng(); // the very last element + + BOOST_REQUIRE_EXCEPTION( eng(), std::range_error, accept_all_exceptions ); + + engine_type other(dim); + + BOOST_CHECK( eng != other ); // test that comparison does not overflow + + other(); // the very first element + other.discard(maxdiscard-1); // must succeed + + BOOST_CHECK( eng == other ); + + BOOST_REQUIRE_EXCEPTION( other(), std::range_error, accept_all_exceptions ); + } + + // Overdiscarding + { + engine_type eng(dim); + eng.discard(maxdiscard); // must succeed, since it's maxdiscard operator() invocations + + // must fail because after discarding the whole sequence + // we can't put the eng to any valid sequence producing state + BOOST_REQUIRE_EXCEPTION( eng(), std::range_error, accept_all_exceptions ); + + // Plain overdiscarding by 1 + engine_type other(dim); + BOOST_REQUIRE_EXCEPTION( other.discard(maxdiscard+1), std::range_error, accept_all_exceptions ); + } + + // Test wraparound + { + engine_type eng(dim); + + // must fail either because seq_count overflow check is triggered, + // or because this discard violates seeding bitcount constraint + BOOST_REQUIRE_EXCEPTION( eng.discard(maxdiscard*2), std::range_error, accept_all_exceptions ); + } +} + +} // namespace test + + +#define QRNG_VALIDATION_TEST_FUNCTIONS(QRNG) \ +\ +typedef boost::random::QRNG engine_t; \ +\ +template \ +inline void test_##QRNG##_values(T (&pt)[N][Dimension], std::size_t skip) \ +{ \ + test::expected_values(pt, skip); \ +} \ +\ +template \ +inline void test_##QRNG##_seed(T (&pt)[N][Dimension], std::size_t skip) \ +{ \ + test::seed_function(pt, skip); \ +} \ +\ +template \ +inline void test_##QRNG##_discard(T (&pt)[N][Dimension], std::size_t skip) \ +{ \ + test::discard_function(pt, skip); \ +} \ +inline void test_##QRNG##_max_seed() \ +{ \ + test::test_max_seed(2); \ +} \ +inline void test_##QRNG##_max_dimension(std::size_t dim) \ +{ \ + engine_t eng(dim); /*must succeed*/ \ + BOOST_REQUIRE_EXCEPTION( engine_t(dim+1), std::invalid_argument, test::accept_all_exceptions ); \ +} \ +\ +BOOST_AUTO_TEST_CASE( test_##QRNG##_zero_dimension_fails ) \ +{ \ + BOOST_REQUIRE_EXCEPTION( engine_t(0), std::invalid_argument, test::accept_all_exceptions ); \ +} \ +/**/ + +#define QRNG_VALIDATION_TEST_DISCARD(QRNG) \ +\ +template \ +struct gen_engine \ +{ \ + typedef boost::random::QRNG##_engine type; \ + static BOOST_CONSTEXPR IntType dimlim() { \ + /* Compute seq length for a single dimension taking into account the actual bit count */ \ + return type::max() >> (std::numeric_limits::digits - w); \ + } \ +}; \ +\ +inline void test_##QRNG##_max_discard() \ +{ \ + static const std::size_t dim = 2;\ + \ + /* test full 8 bits */ \ + test::test_max_discard >(dim); \ + \ + /* test 7 bits */ \ + test::test_max_discard >(dim); \ + \ + /* test 6 bits for a good measure */ \ + test::test_max_discard >(dim); \ +} \ +/**/ + +#endif // TEST_QRNG_FUNCTIONS_HPP_INCLUDED From c7c9bc350030fa2cab2ef628e7ce304fe7274c06 Mon Sep 17 00:00:00 2001 From: "Justinas V. Daugmaudis" Date: Tue, 6 Mar 2018 12:35:59 +0200 Subject: [PATCH 3/8] Example added --- doc/tutorial.qbk | 7 ++++ example/Jamfile.v2 | 1 + example/intersections.cpp | 74 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 example/intersections.cpp diff --git a/doc/tutorial.qbk b/doc/tutorial.qbk index d14c340..84a0e4f 100644 --- a/doc/tutorial.qbk +++ b/doc/tutorial.qbk @@ -26,3 +26,10 @@ [password] [endsect] + +[section Generating quasi-random line-sphere intersections] + +[import ../example/intersections.cpp] +[intersections] + +[endsect] diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index a57fe3f..c598e78 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -10,3 +10,4 @@ run die.cpp ; run weighted_die.cpp ; run password.cpp /boost//random ; +run intersections.cpp /boost//random ; diff --git a/example/intersections.cpp b/example/intersections.cpp new file mode 100644 index 0000000..f4c1435 --- /dev/null +++ b/example/intersections.cpp @@ -0,0 +1,74 @@ +// intersections.cpp +// +// Copyright (c) 2018 +// Justinas V. Daugmaudis +// +// 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) + +//[intersections +/*` + For the source of this example see + [@boost://libs/random/example/intersections.cpp intersections.cpp]. + + This example demonstrates generating quasi-randomly distributed chord + entry and exit points on an '''S2''' sphere. + + First we include the headers we need for __niederreiter_base2 + and __uniform_01 distribution. + */ + +#include +#include + +#include + +#include + +/*` + We use 4-dimensional __niederreiter_base2 as a source of randomness. + */ +boost::random::niederreiter_base2 gen(4); + + +int main() +{ + typedef boost::tuple point_t; + + const std::size_t n_points = 100; // we will generate 100 points + + std::vector points; + points.reserve(n_points); + + boost::random::uniform_01 dist; + + for (std::size_t i = 0; i != n_points; ++i) + { + /*` + Using formula from J. Rovira et al., "Point sampling with uniformly distributed lines", 2005 + to compute uniformly distributed chord entry and exit points on the surface of a sphere. + */ + double cos_theta = 1 - 2 * dist(gen); + double sin_theta = std::sqrt(1 - cos_theta * cos_theta); + double phi = boost::math::constants::two_pi() * dist(gen); + double sin_phi = std::sin(phi), cos_phi = std::cos(phi); + + point_t point_on_sphere(sin_theta*sin_phi, cos_theta, sin_theta*cos_phi); + + /*` + Here we assume that our sphere is a unit sphere at (0,0,0). If your sphere was + different then now would be the time to scale and translate the `point_on_sphere`. + */ + + points.push_back(point_on_sphere); + } + + /*` + Vector `points` now holds generated 3D points on a unit sphere. + */ + + return 0; +} + +//] From 742474824f6941847b0098a046a9d8c52ff68a0e Mon Sep 17 00:00:00 2001 From: "Justinas V. Daugmaudis" Date: Tue, 6 Mar 2018 15:32:11 +0200 Subject: [PATCH 4/8] Fix docs Edit comment --- doc/concepts.qbk | 6 +++--- example/intersections.cpp | 10 +++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/doc/concepts.qbk b/doc/concepts.qbk index 306bf61..19037d4 100644 --- a/doc/concepts.qbk +++ b/doc/concepts.qbk @@ -215,12 +215,12 @@ part of the square would be proportional to the number of points in the whole sq Such sequences share some properties of random variables and in certain applications such as the quasi-Monte Carlo method their lower discrepancy is an important advantage. -[note Quasi-Monte Carlo method uses a low-discrepancy sequence such as the +[note The quasi-Monte Carlo method uses a low-discrepancy sequence such as the Niederreiter base 2 sequence, the Sobol sequence, or the Faure sequence among the others. The advantage of using low-discrepancy sequences is a probabilistically faster rate of -convergence. Quasi-Monte Carlo has a rate of convergence close to '''O(1/N)''', +convergence. Quasi-Monte Carlo has a rate of convergence O(log(N)[sup s]/N), whereas the rate of convergence for the Monte Carlo method, which uses a pseudo-random sequence, -is '''O(N-0.5)'''.] +is O(N[sup -0.5]).] Harold Niederreiter gives an extensive overview on random number generation and quasi-Monte Carlo methods in his book "Random number generation and diff --git a/example/intersections.cpp b/example/intersections.cpp index f4c1435..fea40d6 100644 --- a/example/intersections.cpp +++ b/example/intersections.cpp @@ -13,7 +13,7 @@ [@boost://libs/random/example/intersections.cpp intersections.cpp]. This example demonstrates generating quasi-randomly distributed chord - entry and exit points on an '''S2''' sphere. + entry and exit points on an S[sup 2] sphere. First we include the headers we need for __niederreiter_base2 and __uniform_01 distribution. @@ -41,6 +41,10 @@ int main() std::vector points; points.reserve(n_points); + /*<< __niederreiter_base2 produces integers in the range [0, 2[sup 64]-1]. + However, we want numbers in the range [0, 1). The distribution + __uniform_01 performs this transformation. + >>*/ boost::random::uniform_01 dist; for (std::size_t i = 0; i != n_points; ++i) @@ -57,7 +61,7 @@ int main() point_t point_on_sphere(sin_theta*sin_phi, cos_theta, sin_theta*cos_phi); /*` - Here we assume that our sphere is a unit sphere at (0,0,0). If your sphere was + Here we assume that our sphere is a unit sphere at origin. If your sphere was different then now would be the time to scale and translate the `point_on_sphere`. */ @@ -65,7 +69,7 @@ int main() } /*` - Vector `points` now holds generated 3D points on a unit sphere. + Vector `points` now holds generated 3D points on a sphere. */ return 0; From b14d592873e829aff22029ccff3002ecc71d2f64 Mon Sep 17 00:00:00 2001 From: "Justinas V. Daugmaudis" Date: Sat, 10 Mar 2018 12:53:38 +0200 Subject: [PATCH 5/8] Quick fixes Fix warnings low_bits_mask_t use high_bit_mask_t Moved qrng details to namespace qrng_detail Removed unnecessary function Simplify gray code size check & readability Disallow negative seeds --- .../boost/random/detail/gray_coded_qrng.hpp | 46 +++++++++++------ include/boost/random/detail/qrng_base.hpp | 49 ++++++++++++++++--- include/boost/random/faure.hpp | 24 +++++---- include/boost/random/niederreiter_base2.hpp | 14 +++--- include/boost/random/sobol.hpp | 12 ++--- test/test_qrng_functions.hpp | 8 +-- 6 files changed, 100 insertions(+), 53 deletions(-) diff --git a/include/boost/random/detail/gray_coded_qrng.hpp b/include/boost/random/detail/gray_coded_qrng.hpp index 4c900fe..a032bc9 100644 --- a/include/boost/random/detail/gray_coded_qrng.hpp +++ b/include/boost/random/detail/gray_coded_qrng.hpp @@ -17,13 +17,15 @@ #include +#include + //!\file //!Describes the gray-coded quasi-random number generator base class template. namespace boost { namespace random { -namespace detail { +namespace qrng_detail { template class gray_coded_qrng @@ -46,27 +48,33 @@ private: friend class qrng_base; // Respect lattice bit_count here - struct do_nothing { - inline static void check(unsigned) {} - inline static void check_log2(size_type) {} + struct check_nothing { + inline static void bit_pos(unsigned) {} + inline static void code_size(size_type) {} }; struct check_bit_range { - inline static void check(unsigned bit_pos) { - if (bit_pos >= LatticeT::bit_count) - boost::throw_exception( std::range_error("gray_coded_qrng: bit_count") ); + static void raise_bit_count() { + boost::throw_exception( std::range_error("gray_coded_qrng: bit_count") ); } - inline static void check_log2(size_type code) { - check_bit_range::check(multiprecision::msb(code)); + inline static void bit_pos(unsigned bit_pos) { + if (bit_pos >= LatticeT::bit_count) + raise_bit_count(); + } + inline static void code_size(size_type code) { + if (code > (self_t::max)()) + raise_bit_count(); } }; // We only want to check whether bit pos is outside the range if given bit_count // is narrower than the size_type, otherwise checks compile to nothing. + BOOST_STATIC_ASSERT(LatticeT::bit_count <= std::numeric_limits::digits); + typedef typename mpl::if_c< LatticeT::bit_count < std::numeric_limits::digits , check_bit_range - , do_nothing - >::type bit_range_checker_t; + , check_nothing + >::type check_bit_range_t; public: //!Returns: Tight lower bound on the set of values returned by operator(). @@ -79,7 +87,7 @@ public: //! //!Throws: nothing. static BOOST_CONSTEXPR result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () - { return (std::numeric_limits::max)(); } + { return low_bits_mask_t::sig_bits; } explicit gray_coded_qrng(std::size_t dimension) : base_t(dimension) @@ -100,6 +108,9 @@ public: { if (init != this->curr_seq()) { + // We don't want negative seeds. + check_seed_sign(init); + size_type seq_code = boost::next(init); if (BOOST_UNLIKELY(!(init < seq_code))) boost::throw_exception( std::range_error("gray_coded_qrng: seed") ); @@ -107,7 +118,7 @@ public: seq_code ^= (seq_code >> 1); // Fail if we see that seq_code is outside bit range. // We do that before we even touch engine state. - bit_range_checker_t::check_log2(seq_code); + check_bit_range_t::code_size(seq_code); set_zero_state(); for (unsigned r = 0; seq_code != 0; ++r, seq_code >>= 1) @@ -126,8 +137,10 @@ private: // Find the position of the least-significant zero in sequence count. // This is the bit that changes in the Gray-code representation as // the count is advanced. - unsigned r = multiprecision::lsb(~seq); - bit_range_checker_t::check(r); + // Xor'ing with max() has the effect of flipping all the bits in seq, + // except for the sign bit. + unsigned r = multiprecision::lsb(seq ^ (self_t::max)()); + check_bit_range_t::bit_pos(r); update_quasi(r); } @@ -145,8 +158,9 @@ private: } }; -}} // namespace detail::random +} // namespace qrng_detail +} // namespace random } // namespace boost #endif // BOOST_RANDOM_DETAIL_GRAY_CODED_QRNG_HPP diff --git a/include/boost/random/detail/qrng_base.hpp b/include/boost/random/detail/qrng_base.hpp index 44fc549..3cc2dc8 100644 --- a/include/boost/random/detail/qrng_base.hpp +++ b/include/boost/random/detail/qrng_base.hpp @@ -22,20 +22,35 @@ #include +#include + //!\file //!Describes the quasi-random number generator base class template. namespace boost { namespace random { -namespace detail { +namespace qrng_detail { -template -inline bool are_close(T x, T y, T eps) // |x - y| <= eps +// If the seed is a signed integer type, then we need to +// check that the value is positive: +template +inline void check_seed_sign(const Integer& v, const mpl::true_) { - if (x < y) std::swap(x, y); - return !(x - y > eps); + if (v < 0) + { + boost::throw_exception( std::range_error("seed must be a positive integer") ); + } } +template +inline void check_seed_sign(const Integer&, const mpl::false_) {} + +template +inline void check_seed_sign(const Integer& v) +{ + check_seed_sign(v, mpl::bool_::is_signed>()); +} + template class qrng_base @@ -103,9 +118,21 @@ public: // Discards vec_n (with correction) consecutive s-dimensional vectors discard_vector(vec_n - static_cast(corr)); + +#ifdef BOOST_MSVC +#pragma warning(push) +// disable unary minus operator applied to an unsigned type, +// result still unsigned. +#pragma warning(disable:4146) +#endif + // Sets up the proper position of the element-to-read // curr_elem = carry + corr*dimension_value curr_elem = carry ^ (-static_cast(corr) & dimension_value); + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif } //!Writes the textual representation of the generator to a @c std::ostream. @@ -123,6 +150,9 @@ public: boost::uintmax_t z; if (is >> dim >> std::ws >> seed >> std::ws >> z) // initialize iff success! { + // Check seed sign before resizing the lattice and/or recomputing state + check_seed_sign(seed); + if (s.dimension() != prevent_zero_dimension(dim)) { s.lattice.resize(dim); @@ -146,7 +176,9 @@ public: // and the last one is curr_elem. return (dimension_value == y.dimension()) && - are_close(x.seq_count, y.seq_count, static_cast(1)) && + // |x.seq_count - y.seq_count| <= 1 + !((x.seq_count < y.seq_count ? y.seq_count - x.seq_count : x.seq_count - y.seq_count) + > static_cast(1)) && // Potential overflows don't matter here, since we've already ascertained // that sequence counts differ by no more than 1, so if they overflow, they // can overflow together. @@ -209,7 +241,7 @@ private: boost::throw_exception( std::range_error("qrng_base: discard_vector") ); std::size_t tmp = curr_elem; - derived().seed(seq_count + z); + derived().seed(static_cast(seq_count + z)); curr_elem = tmp; } @@ -247,8 +279,9 @@ inline void dimension_assert(const char* generator, std::size_t dim, std::size_t } } -}} // namespace detail::random +} // namespace qrng_detail +} // namespace random } // namespace boost #endif // BOOST_RANDOM_DETAIL_QRNG_BASE_HPP diff --git a/include/boost/random/faure.hpp b/include/boost/random/faure.hpp index 5347636..7f526cd 100644 --- a/include/boost/random/faure.hpp +++ b/include/boost/random/faure.hpp @@ -57,15 +57,16 @@ struct primes 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117 }; - dimension_assert("Faure", n, prim_a[number_of_primes - 1]); + qrng_detail::dimension_assert("Faure", n, prim_a[number_of_primes - 1]); return *std::lower_bound(prim_a, prim_a + number_of_primes, n); } }; } // namespace qrng_tables +} // namespace detail - +namespace qrng_detail { namespace fr { // Returns the integer part of the logarithm base Base of arg. @@ -98,6 +99,8 @@ inline T integer_pow(T base, T e) return result; } +} // namespace fr + // Computes a table of binomial coefficients modulo qs. template struct binomial_coefficients @@ -131,12 +134,12 @@ struct binomial_coefficients { if (first != last) { - const size_type ilog = integer_log(static_cast(qs_base), seq); + const size_type ilog = fr::integer_log(static_cast(qs_base), seq); const size_type hisum = ilog + 1; if (coeff.size() != size_hint(hisum)) { ytemp.resize(hisum); compute_coefficients(hisum); - qs_pow = integer_pow(static_cast(qs_base), ilog); + qs_pow = fr::integer_pow(static_cast(qs_base), ilog); } *first = compute_recip(seq, ytemp.rbegin()); @@ -233,7 +236,7 @@ private: size_type qs_pow; }; -}} // namespace detail::fr +} // namespace qrng_detail typedef detail::qrng_tables::primes default_faure_prime_table; @@ -263,18 +266,18 @@ typedef detail::qrng_tables::primes default_faure_prime_table; //!Some member functions may throw exceptions of type @c std::bad_alloc. template class faure_engine - : public detail::qrng_base< + : public qrng_detail::qrng_base< faure_engine - , detail::fr::binomial_coefficients + , qrng_detail::binomial_coefficients , SeqSizeT > { typedef faure_engine self_t; - typedef detail::fr::binomial_coefficients lattice_t; - typedef detail::qrng_base base_t; + typedef qrng_detail::binomial_coefficients lattice_t; + typedef qrng_detail::qrng_base base_t; - friend class detail::qrng_base; + friend class qrng_detail::qrng_base; public: typedef RealType result_type; @@ -344,6 +347,7 @@ private: /** @cond hide_private_members */ void compute_seq(SeqSizeT seq) { + qrng_detail::check_seed_sign(seq); this->lattice.update(seq, this->state_begin(), this->state_end()); } /** @endcond */ diff --git a/include/boost/random/niederreiter_base2.hpp b/include/boost/random/niederreiter_base2.hpp index 9dcb2aa..ac6103c 100644 --- a/include/boost/random/niederreiter_base2.hpp +++ b/include/boost/random/niederreiter_base2.hpp @@ -18,7 +18,7 @@ namespace boost { namespace random { /** @cond */ -namespace detail { +namespace qrng_detail { namespace nb2 { // Return the base 2 logarithm for a given bitset v @@ -137,7 +137,7 @@ struct niederreiter_base2_lattice pb.reset(); // pb == 0 pb.set(pb_degree); // set the proper bit for the pb_degree - value_type j = static_cast(1) << (bit_count - 1); + value_type j = high_bit_mask_t::high_bit; do { // Now choose a value of Kj as defined in section 3.3. @@ -194,7 +194,7 @@ private: std::vector cj; }; -} // namespace detail +} // namespace qrng_detail typedef detail::qrng_tables::niederreiter_base2 default_niederreiter_base2_table; @@ -227,12 +227,12 @@ typedef detail::qrng_tables::niederreiter_base2 default_niederreiter_base2_table //! \f$L=Dimension \times (2^{w} - 1)\f$. template class niederreiter_base2_engine - : public detail::gray_coded_qrng< - detail::niederreiter_base2_lattice + : public qrng_detail::gray_coded_qrng< + qrng_detail::niederreiter_base2_lattice > { - typedef detail::niederreiter_base2_lattice lattice_t; - typedef detail::gray_coded_qrng base_t; + typedef qrng_detail::niederreiter_base2_lattice lattice_t; + typedef qrng_detail::gray_coded_qrng base_t; public: //!Effects: Constructs the default `s`-dimensional Niederreiter base 2 quasi-random number generator. diff --git a/include/boost/random/sobol.hpp b/include/boost/random/sobol.hpp index 0027ddc..c1fcd6f 100644 --- a/include/boost/random/sobol.hpp +++ b/include/boost/random/sobol.hpp @@ -16,7 +16,7 @@ namespace boost { namespace random { /** @cond */ -namespace detail { +namespace qrng_detail { // sobol_lattice sets up the random-number generator to produce a Sobol // sequence of at most max dims-dimensional quasi-random vectors. @@ -99,7 +99,7 @@ private: std::vector bits; }; -} // namespace detail +} // namespace qrng_detail typedef detail::qrng_tables::sobol default_sobol_table; @@ -131,12 +131,12 @@ typedef detail::qrng_tables::sobol default_sobol_table; //!any more values. The length of the low discrepancy sequence is given by \f$L=Dimension \times (2^{w} - 1)\f$. template class sobol_engine - : public detail::gray_coded_qrng< - detail::sobol_lattice + : public qrng_detail::gray_coded_qrng< + qrng_detail::sobol_lattice > { - typedef detail::sobol_lattice lattice_t; - typedef detail::gray_coded_qrng base_t; + typedef qrng_detail::sobol_lattice lattice_t; + typedef qrng_detail::gray_coded_qrng base_t; public: //!Effects: Constructs the default `s`-dimensional Sobol quasi-random number generator. diff --git a/test/test_qrng_functions.hpp b/test/test_qrng_functions.hpp index 6248423..effc960 100644 --- a/test/test_qrng_functions.hpp +++ b/test/test_qrng_functions.hpp @@ -145,7 +145,7 @@ template void test_max_seed(std::size_t dim) { typedef typename Engine::size_type size_type; - static const size_type maxseed = std::numeric_limits::max(); + static const size_type maxseed = Engine::max(); Engine eng(dim); eng.seed(maxseed-1); // must succeed @@ -166,7 +166,7 @@ void test_max_discard(std::size_t dim) { typedef typename Generator::type engine_type; - static const boost::uintmax_t maxdiscard = dim * Generator::dimlim(); + static const boost::uintmax_t maxdiscard = dim * engine_type::max(); // Max discard limit { @@ -258,10 +258,6 @@ template \ struct gen_engine \ { \ typedef boost::random::QRNG##_engine type; \ - static BOOST_CONSTEXPR IntType dimlim() { \ - /* Compute seq length for a single dimension taking into account the actual bit count */ \ - return type::max() >> (std::numeric_limits::digits - w); \ - } \ }; \ \ inline void test_##QRNG##_max_discard() \ From c4dfa0390117ef2a05f576945855c170c6822e6f Mon Sep 17 00:00:00 2001 From: "Justinas V. Daugmaudis" Date: Tue, 13 Mar 2018 18:50:52 +0200 Subject: [PATCH 6/8] Strong exception safety for lattice computation --- include/boost/random/niederreiter_base2.hpp | 16 +++++++++----- include/boost/random/sobol.hpp | 24 +++++++++++++-------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/include/boost/random/niederreiter_base2.hpp b/include/boost/random/niederreiter_base2.hpp index ac6103c..03b5997 100644 --- a/include/boost/random/niederreiter_base2.hpp +++ b/include/boost/random/niederreiter_base2.hpp @@ -94,6 +94,10 @@ struct niederreiter_base2_lattice BOOST_STATIC_ASSERT(w > 0u); BOOST_STATIC_CONSTANT(unsigned, bit_count = w); +private: + typedef std::vector container_type; + +public: explicit niederreiter_base2_lattice(std::size_t dimension) { resize(dimension); @@ -106,7 +110,7 @@ struct niederreiter_base2_lattice dimension_assert("Niederreiter base 2", dimension, Nb2Table::max_dimension); // Initialize the bit array - cj.resize(bit_count * dimension); + container_type cj(bit_count * dimension); // Reserve temporary space for lattice computation bitset_type v, pb, tmp; @@ -182,16 +186,18 @@ struct niederreiter_base2_lattice } } while (j != 0); } + + bits.swap(cj); } - typename std::vector::const_iterator iter_at(std::size_t n) const + typename container_type::const_iterator iter_at(std::size_t n) const { - BOOST_ASSERT(!(n > cj.size())); - return cj.begin() + n; + BOOST_ASSERT(!(n > bits.size())); + return bits.begin() + n; } private: - std::vector cj; + container_type bits; }; } // namespace qrng_detail diff --git a/include/boost/random/sobol.hpp b/include/boost/random/sobol.hpp index c1fcd6f..4811a9a 100644 --- a/include/boost/random/sobol.hpp +++ b/include/boost/random/sobol.hpp @@ -32,23 +32,27 @@ struct sobol_lattice BOOST_STATIC_ASSERT(w > 0u); BOOST_STATIC_CONSTANT(unsigned, bit_count = w); - // default copy c-tor is fine +private: + typedef std::vector container_type; +public: explicit sobol_lattice(std::size_t dimension) { resize(dimension); } + // default copy c-tor is fine + void resize(std::size_t dimension) { dimension_assert("Sobol", dimension, SobolTables::max_dimension); // Initialize the bit array - bits.resize(bit_count * dimension); + container_type cj(bit_count * dimension); // Initialize direction table in dimension 0 for (unsigned k = 0; k != bit_count; ++k) - bits[dimension*k] = static_cast(1); + cj[dimension*k] = static_cast(1); // Initialize in remaining dimensions. for (std::size_t dim = 1; dim < dimension; ++dim) @@ -61,7 +65,7 @@ struct sobol_lattice // set initial values of m from table for (unsigned k = 0; k != degree; ++k) - bits[dimension*k + dim] = SobolTables::minit(dim-1, k); + cj[dimension*k + dim] = SobolTables::minit(dim-1, k); // Calculate remaining elements for this dimension, // as explained in Bratley+Fox, section 2. @@ -70,11 +74,11 @@ struct sobol_lattice unsigned int p_i = poly; const std::size_t bit_offset = dimension*j + dim; - bits[bit_offset] = bits[dimension*(j-degree) + dim]; + cj[bit_offset] = cj[dimension*(j-degree) + dim]; for (unsigned k = 0; k != degree; ++k, p_i >>= 1) { int rem = degree - k; - bits[bit_offset] ^= ((p_i & 1) * bits[dimension*(j-rem) + dim]) << rem; + cj[bit_offset] ^= ((p_i & 1) * cj[dimension*(j-rem) + dim]) << rem; } } } @@ -85,18 +89,20 @@ struct sobol_lattice { const std::size_t bit_offset = dimension * j; for (std::size_t dim = 0; dim != dimension; ++dim) - bits[bit_offset + dim] <<= p; + cj[bit_offset + dim] <<= p; } + + bits.swap(cj); } - typename std::vector::const_iterator iter_at(std::size_t n) const + typename container_type::const_iterator iter_at(std::size_t n) const { BOOST_ASSERT(!(n > bits.size())); return bits.begin() + n; } private: - std::vector bits; + container_type bits; }; } // namespace qrng_detail From 5ebb0554d9253f263d1b641cd2ed8acdef073681 Mon Sep 17 00:00:00 2001 From: "Justinas V. Daugmaudis" Date: Wed, 14 Mar 2018 14:28:20 +0200 Subject: [PATCH 7/8] Nitpicky type adjustments --- include/boost/random/detail/qrng_base.hpp | 2 +- include/boost/random/niederreiter_base2.hpp | 6 +++--- include/boost/random/sobol.hpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/boost/random/detail/qrng_base.hpp b/include/boost/random/detail/qrng_base.hpp index 3cc2dc8..a8e136f 100644 --- a/include/boost/random/detail/qrng_base.hpp +++ b/include/boost/random/detail/qrng_base.hpp @@ -234,7 +234,7 @@ private: // and preserves the position of the element-to-read void discard_vector(boost::uintmax_t z) { - const size_type max_z = std::numeric_limits::max() - seq_count; + const boost::uintmax_t max_z = std::numeric_limits::max() - seq_count; // Don't allow seq_count + z overflows here if (max_z < z) diff --git a/include/boost/random/niederreiter_base2.hpp b/include/boost/random/niederreiter_base2.hpp index 03b5997..03e6b3a 100644 --- a/include/boost/random/niederreiter_base2.hpp +++ b/include/boost/random/niederreiter_base2.hpp @@ -37,8 +37,8 @@ bitset_log2(const DynamicBitset& v) // Multiply polynomials over Z_2. -template -inline void modulo2_multiply(unsigned P, DynamicBitset& v, DynamicBitset& pt) +template +inline void modulo2_multiply(PolynomialT P, DynamicBitset& v, DynamicBitset& pt) { pt.reset(); // pt == 0 for (; P; P >>= 1, v <<= 1) @@ -118,7 +118,7 @@ public: // Compute Niedderreiter base 2 lattice for (std::size_t dim = 0; dim != dimension; ++dim) { - const unsigned int poly = Nb2Table::polynomial(dim); + const typename Nb2Table::value_type poly = Nb2Table::polynomial(dim); if (poly > std::numeric_limits::max()) { boost::throw_exception( std::range_error("niederreiter_base2: polynomial value outside the given value type range") ); } diff --git a/include/boost/random/sobol.hpp b/include/boost/random/sobol.hpp index 4811a9a..2518b37 100644 --- a/include/boost/random/sobol.hpp +++ b/include/boost/random/sobol.hpp @@ -57,7 +57,7 @@ public: // Initialize in remaining dimensions. for (std::size_t dim = 1; dim < dimension; ++dim) { - const unsigned int poly = SobolTables::polynomial(dim-1); + const typename SobolTables::value_type poly = SobolTables::polynomial(dim-1); if (poly > std::numeric_limits::max()) { boost::throw_exception( std::range_error("sobol: polynomial value outside the given value type range") ); } @@ -71,7 +71,7 @@ public: // as explained in Bratley+Fox, section 2. for (unsigned j = degree; j < bit_count; ++j) { - unsigned int p_i = poly; + typename SobolTables::value_type p_i = poly; const std::size_t bit_offset = dimension*j + dim; cj[bit_offset] = cj[dimension*(j-degree) + dim]; From 60c43db293a683dc16ab972e63ef26aa7b2bbd6b Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Sat, 12 May 2018 19:57:16 -0600 Subject: [PATCH 8/8] Fix signed integer overflow in niederreiter_base2. Suppress other (spurious) warnings from msvc. --- include/boost/random/detail/gray_coded_qrng.hpp | 2 +- include/boost/random/detail/qrng_base.hpp | 4 ++++ include/boost/random/faure.hpp | 16 ++++++++-------- include/boost/random/niederreiter_base2.hpp | 4 ++-- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/include/boost/random/detail/gray_coded_qrng.hpp b/include/boost/random/detail/gray_coded_qrng.hpp index a032bc9..643ec38 100644 --- a/include/boost/random/detail/gray_coded_qrng.hpp +++ b/include/boost/random/detail/gray_coded_qrng.hpp @@ -71,7 +71,7 @@ private: BOOST_STATIC_ASSERT(LatticeT::bit_count <= std::numeric_limits::digits); typedef typename mpl::if_c< - LatticeT::bit_count < std::numeric_limits::digits + ((LatticeT::bit_count) < std::numeric_limits::digits) , check_bit_range , check_nothing >::type check_bit_range_t; diff --git a/include/boost/random/detail/qrng_base.hpp b/include/boost/random/detail/qrng_base.hpp index a8e136f..aa95a1e 100644 --- a/include/boost/random/detail/qrng_base.hpp +++ b/include/boost/random/detail/qrng_base.hpp @@ -24,6 +24,8 @@ #include +#include + //!\file //!Describes the quasi-random number generator base class template. @@ -284,4 +286,6 @@ inline void dimension_assert(const char* generator, std::size_t dim, std::size_t } // namespace random } // namespace boost +#include + #endif // BOOST_RANDOM_DETAIL_QRNG_BASE_HPP diff --git a/include/boost/random/faure.hpp b/include/boost/random/faure.hpp index 7f526cd..4301c30 100644 --- a/include/boost/random/faure.hpp +++ b/include/boost/random/faure.hpp @@ -137,7 +137,7 @@ struct binomial_coefficients const size_type ilog = fr::integer_log(static_cast(qs_base), seq); const size_type hisum = ilog + 1; if (coeff.size() != size_hint(hisum)) { - ytemp.resize(hisum); + ytemp.resize(static_cast(hisum)); // cast safe because log is small compute_coefficients(hisum); qs_pow = fr::integer_pow(static_cast(qs_base), ilog); } @@ -153,14 +153,14 @@ struct binomial_coefficients for (size_type i = 0; i != hisum; ++i) { - RealType ztemp = ytemp[i] * upper_element(i, i, hisum); + RealType ztemp = ytemp[static_cast(i)] * upper_element(i, i, hisum); for (size_type j = i + 1; j != hisum; ++j) - ztemp += ytemp[j] * upper_element(i, j, hisum); + ztemp += ytemp[static_cast(j)] * upper_element(i, j, hisum); // Sum ( J <= I <= HISUM ) ( old ytemp(i) * binom(i,j) ) mod QS. - ytemp[i] = std::fmod(ztemp, static_cast(qs_base)); + ytemp[static_cast(i)] = std::fmod(ztemp, static_cast(qs_base)); r *= static_cast(qs_base); - *first += ytemp[i] / r; + *first += ytemp[static_cast(i)] / r; } } } @@ -177,7 +177,7 @@ private: BOOST_ASSERT( i < dim ); BOOST_ASSERT( j < dim ); BOOST_ASSERT( i <= j ); - return coeff[(i * (2 * dim - i + 1)) / 2 + j - i]; + return coeff[static_cast((i * (2 * dim - i + 1)) / 2 + j - i)]; } template @@ -192,7 +192,7 @@ private: for( ; k != 0; ++out, seq = m, k /= qs_base ) { m = seq % k; - RealType v = (seq - m) / k; // RealType <- size type + RealType v = static_cast((seq - m) / k); // RealType <- size type r += v; r /= static_cast(qs_base); *out = v; // saves double dereference @@ -203,7 +203,7 @@ private: void compute_coefficients(const size_type n) { // Resize and initialize to zero - coeff.resize(size_hint(n)); + coeff.resize(static_cast(size_hint(n))); std::fill(coeff.begin(), coeff.end(), packed_uint_t()); // The first row and the diagonal is assigned to 1 diff --git a/include/boost/random/niederreiter_base2.hpp b/include/boost/random/niederreiter_base2.hpp index 03e6b3a..149a4a4 100644 --- a/include/boost/random/niederreiter_base2.hpp +++ b/include/boost/random/niederreiter_base2.hpp @@ -76,9 +76,9 @@ inline void calculate_v(const DynamicBitset& pb, for ( ; r != v.size(); ++r) { bool term = false; - for (int k = -pb_degree; k < 0; ++k) + for (typename DynamicBitset::size_type k = 0; k < pb_degree; ++k) { - term ^= pb.test(k + pb_degree) & v[r + k]; + term ^= pb.test(k) & v[r + k - pb_degree]; } v[r] = term; }