616 lines
17 KiB
C++
616 lines
17 KiB
C++
/*=============================================================================
|
|
|
|
This file is part of FLINT.
|
|
|
|
FLINT is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
FLINT is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with FLINT; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
=============================================================================*/
|
|
/******************************************************************************
|
|
|
|
Copyright (C) 2013 Tom Bachmann
|
|
|
|
******************************************************************************/
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <string>
|
|
|
|
#include "fmpzxx.h"
|
|
#include "flintxx/test/helpers.h"
|
|
|
|
#if !HAVE_FAST_COMPILER
|
|
#warning "Some tests are disabled because your compiler is slow."
|
|
#endif
|
|
|
|
using namespace flint;
|
|
|
|
void
|
|
test_printing()
|
|
{
|
|
fmpzxx a(31);
|
|
|
|
tassert(a.to_string() == "31");
|
|
tassert(a.to_string(2) == "11111");
|
|
|
|
std::ostringstream oss;
|
|
oss << a << '\n' << std::oct << a << '\n'
|
|
<< std::hex << a << '\n' << std::dec << a;
|
|
tassert(oss.str() == "31\n37\n1f\n31");
|
|
|
|
fmpzxx b(-15);
|
|
tassert((a + b).to_string() == "16");
|
|
|
|
char astr[] = "15";
|
|
tassert(fmpzxx(astr) == 15);
|
|
}
|
|
|
|
void
|
|
test_order()
|
|
{
|
|
fmpzxx a(0);
|
|
fmpzxx b(1);
|
|
fmpzxx c(0);
|
|
fmpzxx d(-1);
|
|
|
|
#define TO(xzero, zero, one, mone) \
|
|
tassert(xzero == zero); \
|
|
tassert(xzero != one); \
|
|
tassert(!(xzero == one)); \
|
|
tassert(!(xzero != zero)); \
|
|
tassert(xzero < one); \
|
|
tassert(xzero <= one); \
|
|
tassert(xzero <= zero); \
|
|
tassert(!(xzero < zero)); \
|
|
tassert(!(xzero <= mone)); \
|
|
tassert(xzero > mone); \
|
|
tassert(xzero >= mone); \
|
|
tassert(xzero >= zero); \
|
|
tassert(!(xzero > zero)); \
|
|
tassert(!(xzero >= one));
|
|
|
|
TO(a, c, b, d);
|
|
TO(a, 0, 1, -1);
|
|
TO(a, 0u, 1u, -1);
|
|
TO(a, (signed short)(0), (signed short)(1), (signed short)(-1));
|
|
TO(a, (unsigned short)(0), (unsigned short)(1), -1);
|
|
TO(a, WORD(0), WORD(1), WORD(-1));
|
|
TO(0, c, b, d);
|
|
TO(0u, c, b, d);
|
|
TO(WORD(0), c, b, d);
|
|
TO((short)0, c, b, d);
|
|
TO((unsigned short)0, c, b, d);
|
|
}
|
|
|
|
void
|
|
test_conversion()
|
|
{
|
|
fmpzxx a(4);
|
|
tassert(a.to<slong>() == 4);
|
|
tassert(a.to<ulong>() == 4);
|
|
tassert(a.to<double>() == 4.0);
|
|
// NB: to_string is tested in test_printing
|
|
}
|
|
|
|
void
|
|
test_initialisation_assignment()
|
|
{
|
|
fmpzxx a(4), b(WORD(4)), c(4u), d("4");
|
|
fmpzxx e(a);
|
|
fmpzxx f, g, h, i;
|
|
f = 4;
|
|
g = WORD(4);
|
|
h = 4u;
|
|
i = fmpzxx("4");
|
|
tassert(a == b && a == c&& a == d && a == e && a == f && a == g && a == h
|
|
&& a == i);
|
|
|
|
// test deep copying of fmpzxx with more than one digit
|
|
a = fmpzxx("100000000000000000000");
|
|
b = a;
|
|
tassert(a._fmpz()[0] != b._fmpz()[0]);
|
|
fmpzxx j(a);
|
|
tassert(a._fmpz()[0] != j._fmpz()[0]);
|
|
tassert(a == b && a == j);
|
|
|
|
// just here to test our assumptions on data format
|
|
tassert(c._fmpz()[0] == d._fmpz()[0]);
|
|
|
|
// some more exotic "assignments"
|
|
a.set_ui_smod(15, 16);
|
|
tassert(a == -1);
|
|
a.set_uiui(27, 15);
|
|
tassert(a % (fmpzxx(1) << FLINT_BITS) == 15);
|
|
tassert((a >> FLINT_BITS) == 27);
|
|
b.neg_uiui(27, 15);
|
|
tassert(b == -a);
|
|
}
|
|
|
|
void
|
|
test_arithmetic()
|
|
{
|
|
#define TAC(seven, three) \
|
|
tassert(seven + three == 10); \
|
|
tassert(seven * three == 21);
|
|
|
|
#define TA(seven, three) \
|
|
TAC(seven, three); \
|
|
tassert(seven - three == 4); \
|
|
tassert(seven / three == 2); \
|
|
tassert(seven % three == 1)
|
|
|
|
TA(fmpzxx(7), fmpzxx(3));
|
|
TA(fmpzxx(7), 3u);
|
|
TAC(UWORD(7), fmpzxx(3));
|
|
|
|
// test signed builtins (only div and mul)
|
|
tassert(-7 * fmpzxx(3) == -21);
|
|
tassert(fmpzxx(7) * (WORD(-3)) == -21);
|
|
tassert(fmpzxx(21) / -3 == -7);
|
|
|
|
// test composite arithmetic
|
|
fmpzxx a(3), b(7);
|
|
tassert(3*(a + b) - (b + (a - 4u)) + ((-(a - b)) % (b / 2)) == 25);
|
|
|
|
// test unary minus
|
|
tassert(-a == -3);
|
|
|
|
// test assignment arithmetic
|
|
#define TAA(op, res) \
|
|
{ \
|
|
fmpzxx tmp1(10), tmp2(10), tmp3(10); \
|
|
fmpzxx three(3); \
|
|
tmp1 op three; \
|
|
tmp2 op 3u; \
|
|
tmp3 op three*1; \
|
|
tassert(tmp1 == res); \
|
|
tassert(tmp2 == res); \
|
|
tassert(tmp3 == res); \
|
|
}
|
|
TAA(+=, 13);
|
|
TAA(*=, 30);
|
|
TAA(/=, 3);
|
|
TAA(%=, 1);
|
|
|
|
// shifting
|
|
tassert((fmpzxx(1) << 10) == 1024);
|
|
tassert((fmpzxx(1024) >> 9) == 2);
|
|
|
|
// binary logic
|
|
tassert((fmpzxx(1) | fmpzxx(2)) == 3);
|
|
tassert((fmpzxx(3) & fmpzxx(5)) == 1);
|
|
tassert((fmpzxx(17) ^ fmpzxx(23)) == (UWORD(17) ^ UWORD(23)));
|
|
tassert(~fmpzxx(17) == ~WORD(17));
|
|
}
|
|
|
|
void
|
|
test_functions()
|
|
{
|
|
fmpzxx a(2);
|
|
fmpzxx b(16);
|
|
fmpzxx_srcref c(a);
|
|
|
|
tassert(sgn(a) == 1);
|
|
tassert(size(b) == 1);
|
|
tassert(val2(b) == 4);
|
|
tassert(bits(b) == 5);
|
|
tassert(sizeinbase(b, 2) == 5);
|
|
tassert(b.tstbit(0) == false);
|
|
|
|
tassert(pow(a, 4u) == 16);
|
|
tassert(root(b, 4) == 2);
|
|
tassert(root(b, (unsigned short)4) == 2);
|
|
tassert(sqrt(b) == 4);
|
|
tassert(sqrt(a) == 1);
|
|
tassert(rfac(a, 3u) == 2*3*4);
|
|
tassert(a + fac(4u) == 2 + 4*3*2);
|
|
tassert(fib(4u) == 3);
|
|
tassert(bin(4u, 2u) == 6);
|
|
tassert(abs(a) == a);
|
|
tassert(gcd(a, b) == 2);
|
|
tassert(lcm(a, b) == 16);
|
|
fmpzxx p(31);
|
|
tassert((invmod(b % p, p) * b) % p == 1);
|
|
tassert((negmod(b % p, p) + b) % p == 0);
|
|
|
|
fmpzxx mb(-b);
|
|
fmpzxx three(3);
|
|
tassert(cdiv_q(mb, three) == -5);
|
|
tassert(fdiv_r(mb, three) == 2);
|
|
tassert(tdiv_q(mb, three) == -5);
|
|
tassert(cdiv_q(mb, 3) == -5);
|
|
tassert(tdiv_q(mb, 3) == -5);
|
|
tassert(cdiv_q(mb, 3u) == -5);
|
|
tassert(tdiv_q(mb, 3u) == -5);
|
|
tassert(tdiv_q_2exp(mb, 2u) == -4);
|
|
tassert(fdiv_r_2exp(mb, 2u) == 0);
|
|
tassert(divexact(b, a) == 8 && divexact(b, 2) == 8 && divexact(b, 2u) == 8);
|
|
|
|
// check a composite expression
|
|
tassert(2u + sqrt(a + a) == 4);
|
|
|
|
// check immediate functions
|
|
tassert(divisible(b, a + a));
|
|
tassert(divisible(b, a + a + 2u) == false);
|
|
tassert(divisible(a + a, (unsigned short)2));
|
|
tassert(divisible(-a + b, 3) == false);
|
|
tassert(divisible(c, a) == true);
|
|
|
|
fmpzxx f(15);
|
|
tassert(clog(f, a) == 4 && clog(f, 2u) == 4);
|
|
tassert(flog(f, a) == 3 && flog(f, 2u) == 3);
|
|
tassert(2.7 < dlog(f) && dlog(f) < 2.8);
|
|
|
|
tassert(mul2(a, 15u, 16u) == a*15*16);
|
|
tassert(divexact2(b, 2u, 2u) == 4);
|
|
tassert(powm(a, 4u, fmpzxx(5)) == 1);
|
|
tassert(powm(a, fmpzxx(4), fmpzxx(5)) == 1);
|
|
tassert(mul_tdiv_q_2exp(a, fmpzxx(-3), 2u) == -1);
|
|
tassert(mul_tdiv_q_2exp(a, -3, 2u) == -1);
|
|
|
|
fmpzxx q(1), rem(2);
|
|
tassert(fdiv_qr(b, a) == ltuple(8, 0));
|
|
tassert(tdiv_qr(b, a) == ltuple(8, 0));
|
|
|
|
bool worked;
|
|
ltupleref(worked, q) = sqrtmod(fmpzxx(4), fmpzxx(5));
|
|
tassert(worked && (q == 2 || q == 3));
|
|
tassert(sqrtrem(fmpzxx(5)) == ltuple(2, 1));
|
|
// TODO gcdinv, xgcd
|
|
|
|
// check member functions
|
|
slong exp = 0;
|
|
double d = fmpzxx(3).get_d_2exp(exp);
|
|
double r = d * (WORD(1) << exp);
|
|
tassert(r >= 2.9 && r <= 3.1);
|
|
fmpzxx one(1), mone(-1), zero(0), two(2);
|
|
tassert(one.is_one() && one.is_pm1() && one.is_odd() &&
|
|
!one.is_even() && !one.is_zero());
|
|
tassert(!zero.is_one() && !zero.is_pm1() && zero.is_zero());
|
|
tassert(mone.is_pm1());
|
|
tassert(two.is_even() && !two.is_odd());
|
|
tassert(one.is_square() && !two.is_square());
|
|
tassert(jacobi(b, p) == 1);
|
|
tassert(p.is_probabprime());
|
|
tassert(p.is_prime_pseudosquare());
|
|
|
|
tassert((3*b).remove(a) == ltuple(4, 3));
|
|
|
|
a = 17;
|
|
a.clrbit(0);
|
|
tassert(a == 16);
|
|
a.combit(1);
|
|
tassert(a == 18);
|
|
tassert(a.popcnt() == 2);
|
|
|
|
|
|
frandxx rand;
|
|
mp_bitcnt_t bits = 123; // some extra space in two words
|
|
std::vector<mp_bitcnt_t> arr(bits / FLINT_BITS + 2);
|
|
fmpzxx tostore = fmpzxx::randtest_unsigned(rand, bits);
|
|
bit_pack(arr, bits, tostore);
|
|
tassert(tostore == fmpzxx::bit_unpack_unsigned(arr, bits));
|
|
tassert(tostore == fmpzxx::bit_unpack(arr, bits).get<1>());
|
|
}
|
|
|
|
void
|
|
test_member_functions()
|
|
{
|
|
// NB: only a sample, since these are done by macros anyway
|
|
fmpzxx a(2), b(3);
|
|
tassert((a*b).divisible(b));
|
|
tassert((a*b).divisible(3));
|
|
tassert(b.flog(3u) == 1);
|
|
tassert(a.clog(a) == 1);
|
|
tassert(a.rfac(3u) == rfac(a, 3u));
|
|
tassert(a.gcd(b) == gcd(a, b));
|
|
tassert(a.lcm(b) == lcm(a, b));
|
|
tassert(a.cdiv_q(b) == cdiv_q(a, b));
|
|
tassert(a.mul2(3u, 4u) == mul2(a, 3u, 4u));
|
|
tassert(a.sqrtmod(b) == sqrtmod(a, b));
|
|
tassert(b.sqrt() == sqrt(b));
|
|
}
|
|
|
|
template<class T>
|
|
void assert_is_fmpzxx(const T&)
|
|
{
|
|
tassert(traits::is_fmpzxx<T>::val);
|
|
}
|
|
struct newtype {typedef void data_ref_t; typedef void data_srcref_t;};
|
|
void
|
|
test_traits()
|
|
{
|
|
tassert(traits::is_fmpzxx<fmpzxx>::val == true);
|
|
tassert(traits::is_fmpzxx<int>::val == false);
|
|
assert_is_fmpzxx(fmpzxx(1) + fmpzxx(2));
|
|
// the following does not even compile:
|
|
//tassert((traits::is_fmpzxx<fmpzxx_expression<
|
|
// operations::immediate, newtype> >::val == false));
|
|
}
|
|
|
|
template<class T>
|
|
unsigned count_temporaries2(const T&)
|
|
{
|
|
return T::ev_traits_t::temp_rule_t::temporaries_t::len
|
|
// this term is always zero, but causes compiler error
|
|
// if we are not actually in the ternary case
|
|
+ T::ev_traits_t::temp_rule_t::TERNARY_OP_MARKER;
|
|
}
|
|
|
|
void
|
|
test_temporaries()
|
|
{
|
|
fmpzxx a, b, c;
|
|
tassert(count_temporaries(a + b) == 0);
|
|
tassert(count_temporaries(a + b + c + a + b + c) == 1);
|
|
tassert(count_temporaries(((a / c) + (b % a)) / ((b + c) + (c / a))) == 3);
|
|
tassert(count_temporaries((a/b) + (a/c) + (b/c) + (c/b)) == 2);
|
|
tassert(count_temporaries2((a*b) + (a*c) + (b*c) + (c*b)) == 1);
|
|
|
|
// test a bug in evaluate_2 (if addmul is used on the right, this can
|
|
// be done with two temporaries, else need three)
|
|
tassert(count_temporaries(((a+b)+(a+c)) + (((a+c) + a*c))) == 2);
|
|
}
|
|
|
|
void
|
|
test_ternary()
|
|
{
|
|
fmpzxx b(2), c(3), d(4);
|
|
|
|
#define T0 fac(4u)
|
|
#define T1 (b + b + b)
|
|
#define T2 (T1 + T1)
|
|
#define T3 (T2 + T2)
|
|
#define T4 (T3 + T3)
|
|
|
|
// The inner struct is a trickery to get gcc to free some of its data
|
|
// structures. It reduces the resident set by 50%, and compile time by 75%.
|
|
#define TT3(m1, m2, m3, ntemps) \
|
|
do{ struct inner { static void doit() { \
|
|
fmpzxx b(2), c(3), d(4); \
|
|
tassert(count_temporaries2(m1 + m2*m3) == ntemps); \
|
|
tassert(b + (m1 + m2*m3) == 2 + m1.to<slong>() + m2.to<slong>()*m3.to<slong>()); \
|
|
tassert(count_temporaries2(m1 + m3*m2) == ntemps); \
|
|
tassert(b + (m1 + m3*m2) == 2 + m1.to<slong>() + m2.to<slong>()*m3.to<slong>()); \
|
|
\
|
|
tassert(count_temporaries2(m2*m3 + m1) == ntemps); \
|
|
tassert(b + (m2*m3 + m1) == 2 + m1.to<slong>() + m2.to<slong>()*m3.to<slong>()); \
|
|
tassert(count_temporaries2(m1 + m3*m2) == ntemps); \
|
|
tassert(b + (m3*m2 + m1) == 2 + m1.to<slong>() + m2.to<slong>()*m3.to<slong>()); \
|
|
\
|
|
tassert(count_temporaries2(m1 - m2*m3) == ntemps); \
|
|
tassert(b + (m1 - m2*m3) == 2 + m1.to<slong>() - m2.to<slong>()*m3.to<slong>()); \
|
|
tassert(count_temporaries2(m1 - m3*m2) == ntemps); \
|
|
tassert(b + (m1 - m3*m2) == 2 + m1.to<slong>() - m2.to<slong>()*m3.to<slong>()); \
|
|
} }; inner::doit();} while(0)
|
|
#define TT(m1, m2, ntemps) TT3(m1, m2, d, ntemps)
|
|
|
|
TT(T0, c, 1);
|
|
TT(T1, c, 1);
|
|
TT(T2, c, 2);
|
|
TT(T3, c, 3);
|
|
|
|
TT(T0, T0, 2);
|
|
TT(T0, T1, 2);
|
|
TT(T0, T2, 2);
|
|
TT(T0, T3, 3);
|
|
|
|
#if HAVE_FAST_COMPILER
|
|
TT(T1, T0, 2);
|
|
TT(T1, T1, 2);
|
|
TT(T1, T2, 2);
|
|
TT(T1, T3, 3);
|
|
|
|
TT(T2, T0, 2);
|
|
TT(T2, T1, 2);
|
|
TT(T2, T2, 3);
|
|
TT(T2, T3, 3);
|
|
|
|
TT(T3, T0, 3);
|
|
TT(T3, T1, 3);
|
|
TT(T3, T2, 3);
|
|
TT(T3, T3, 4);
|
|
|
|
// NB: TT3 is symmetric in m2 and m3
|
|
#define TT6(m1, m2, m3, ntemps) \
|
|
TT3(m1, m2, m3, ntemps); \
|
|
TT3(m2, m1, m3, ntemps); \
|
|
TT3(m3, m1, m2, ntemps);
|
|
|
|
TT6(fac(2u), fac(3u), fac(4u), 3);
|
|
TT6(T1, T2, T3, 3);
|
|
TT6(T1, T2, T4, 4);
|
|
TT6(T1, (d+d+d) /* T1' */, T4, 4);
|
|
TT6(T0, fac(2u), T2, 3);
|
|
TT6(T0, T1, (d+d+d), 3);
|
|
TT6(T1, T3, (T2 + T1) /* T3' */, 3);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
test_ternary_assigments()
|
|
{
|
|
fmpzxx a(2), b(3), c(4);
|
|
tassert((a += b*c) == 14);
|
|
tassert(a == 14);
|
|
tassert((a -= b*c) == 2);
|
|
tassert(a == 2);
|
|
|
|
tassert((a += (b+b)*c) == 26);
|
|
tassert((a -= (b+b)*c) == 2);
|
|
tassert((a += c*(b+b)) == 26);
|
|
tassert((a -= c*(b+b)) == 2);
|
|
|
|
tassert((a += (b+b)*(c+c)) == 50);
|
|
tassert((a -= (b+b)*(c+c)) == 2);
|
|
|
|
// Make sure that the general rule kicks
|
|
tassert((a += 3*c) == 14);
|
|
tassert((a -= 3*c) == 2);
|
|
}
|
|
|
|
bool
|
|
try_implicit_conversion(fmpzxx_ref, const fmpzxx_ref&,
|
|
fmpzxx_srcref, const fmpzxx_srcref&, fmpzxx_srcref, const fmpzxx_srcref&)
|
|
{
|
|
return true;
|
|
}
|
|
void
|
|
test_references()
|
|
{
|
|
fmpzxx a(2), b(3);
|
|
fmpzxx_ref ar(a);
|
|
fmpzxx_srcref acr(a), bcr(b);
|
|
|
|
tassert(ar == 2 && bcr == 3 && ar == acr && ar == a);
|
|
|
|
// test assignments
|
|
fmpzxx d(ar);
|
|
a = 4;
|
|
tassert(ar == 4 && acr == 4 && d == 2);
|
|
ar = 2;
|
|
tassert(a == 2);
|
|
|
|
// test some arithmetic
|
|
tassert(a + bcr == 5);
|
|
tassert(acr + bcr == 5);
|
|
tassert(ar + 3u == 5);
|
|
tassert(a < bcr && ar < b && acr < bcr);
|
|
tassert(rfac(acr, 1u) == 2);
|
|
|
|
ar = bin(4u, 2u); tassert(acr == 6);
|
|
tassert(acr.to<slong>() == WORD(6));
|
|
tassert(ar.to_string() == "6");
|
|
ar += b;
|
|
ar += bcr;
|
|
tassert(a == 12);
|
|
|
|
// test conversion of reference types
|
|
tassert(try_implicit_conversion(a, a, a, a, ar, ar));
|
|
tassert((!traits::_is_convertible<fmpzxx, fmpzxx_ref>::val));
|
|
tassert((!traits::_is_convertible<fmpzxx, fmpzxx_srcref>::val));
|
|
tassert((!traits::_is_convertible<fmpzxx_ref, fmpzxx_srcref>::val));
|
|
|
|
// test creation from C types
|
|
fmpzxx_ref ar2 = fmpzxx_ref::make(a._fmpz());
|
|
fmpzxx_srcref acr2 = fmpzxx_srcref::make(acr._fmpz());
|
|
a = 7;
|
|
tassert(ar2 == 7 && acr2 == 7);
|
|
|
|
// test swapping
|
|
a = 2;
|
|
b = 3;
|
|
swap(b, ar);
|
|
tassert(a == 3 && b == 2);
|
|
// make sure ADL is preferred over the general version in std
|
|
using namespace std;
|
|
swap(b, b);
|
|
}
|
|
|
|
void
|
|
test_randomisation()
|
|
{
|
|
frandxx rand;
|
|
tassert(abs(fmpzxx::randbits(rand, 5)) <= 31);
|
|
tassert(abs(fmpzxx::randbits(rand, 5)) >= 16);
|
|
tassert(abs(fmpzxx::randtest(rand, 5)) <= 31);
|
|
tassert(fmpzxx::randtest_unsigned(rand, 5) <= 31);
|
|
tassert(fmpzxx::randtest_unsigned(rand, 5) >= 0);
|
|
tassert(fmpzxx::randtest_not_zero(rand, 5) != 0);
|
|
fmpzxx thirty(30);
|
|
tassert(fmpzxx::randm(rand, thirty) >= 0);
|
|
tassert(fmpzxx::randm(rand, thirty) <= 29);
|
|
tassert(fmpzxx::randtest_mod(rand, thirty) >= 0);
|
|
tassert(fmpzxx::randtest_mod(rand, thirty) <= 29);
|
|
tassert(fmpzxx::randtest_mod_signed(rand, thirty) > -15);
|
|
tassert(fmpzxx::randtest_mod_signed(rand, thirty) <= 15);
|
|
}
|
|
|
|
void
|
|
test_factoring()
|
|
{
|
|
fmpz_factorxx f;f = factor(-2*3*5);
|
|
tassert(f.size() == 3);
|
|
tassert(f.sign() == -1);
|
|
tassert(f.p(0) == 2 && f.exp(0) == 1);
|
|
tassert(f.p(1) == 3 && f.exp(1) == 1);
|
|
tassert(f.p(2) == 5 && f.exp(2) == 1);
|
|
tassert(f == factor(fmpzxx(-2*3*5)));
|
|
tassert(f == fmpz_factorxx(f));
|
|
tassert(f == factor_trial_range(fmpzxx(-2*3*5), 0u, 2u).get<1>());
|
|
tassert(factor_trial_range(fmpzxx(-2*3*5), 0u, 2u).get<0>());
|
|
|
|
tassert(f.expand() == -2*3*5);
|
|
tassert(f.expand() == f.expand_iterative());
|
|
tassert(f.expand() == f.expand_multiexp());
|
|
|
|
if(0)
|
|
print(f); // make sure this compiles
|
|
}
|
|
|
|
void
|
|
test_crt()
|
|
{
|
|
frandxx rand;
|
|
fmpzxx x = fmpzxx::randtest_unsigned(rand, 25);
|
|
std::vector<mp_limb_t> primes;
|
|
primes.push_back(1031);
|
|
primes.push_back(1033);
|
|
primes.push_back(1039);
|
|
|
|
fmpz_combxx comb(primes);
|
|
std::vector<mp_limb_t> residues(primes.size());
|
|
multi_mod(residues, x, comb);
|
|
|
|
fmpzxx prod(1);
|
|
fmpzxx res;
|
|
for(unsigned i = 0;i < primes.size();++i)
|
|
{
|
|
tassert(residues[i] == x % primes[i]);
|
|
res = res.CRT(prod, residues[i], primes[i], false);
|
|
prod *= primes[i];
|
|
}
|
|
tassert(res == x);
|
|
|
|
res = multi_CRT(residues, comb, false);
|
|
tassert(res == x);
|
|
}
|
|
|
|
int
|
|
main()
|
|
{
|
|
std::cout << "fmpzxx....";
|
|
|
|
test_printing();
|
|
test_order();
|
|
test_conversion();
|
|
test_initialisation_assignment();
|
|
test_arithmetic();
|
|
test_functions();
|
|
test_member_functions();
|
|
test_traits();
|
|
test_temporaries();
|
|
test_ternary();
|
|
test_ternary_assigments();
|
|
test_references();
|
|
test_randomisation();
|
|
test_factoring();
|
|
test_crt();
|
|
test_print_read(fmpzxx(-17));
|
|
|
|
// TODO test that certain things *don't* compile?
|
|
// TODO test enable_all_fmpzxx
|
|
|
|
std::cout << "PASS" << std::endl;
|
|
}
|