/*============================================================================= 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 #include #include #include "fmpz_mod_polyxx.h" #include "flintxx/test/helpers.h" using namespace flint; void test_init() { fmpz_mod_polyxx p(fmpzxx(2003)); tassert(p.length() == 0); tassert(p.modulus() == 2003); tassert(fmpz_mod_polyxx::zero(fmpzxx(2003)).is_zero()); } void test_manipulation() { fmpzxx M(1031); fmpz_mod_polyxx p(M), q(M); p.set_coeff(5, 17u + M); tassert(p.degree() == 5); q.set_coeff(5, fmpzxx(16) + fmpzxx(1)); tassert((q + fmpz_mod_polyxx(M)).get_coeff(5) == 17); p.set_coeff(0, 1); tassert(p != q); p.set_coeff(0, 0); tassert(p == q); tassert((p + p).lead() == 2*p.lead()); q.lead() = 0; q._normalise(); tassert(q.is_zero()); p.realloc(0); tassert(p.is_zero()); } void test_assignment() { fmpzxx M(31); fmpz_mod_polyxx p(M), q(M); p.set_coeff(0, 1); tassert(p != q); p = q; tassert(p == q); } void test_conversion() { fmpzxx M(1031); fmpz_mod_polyxx p(M); p = 4u + 1031; tassert(p.length() == 1 && p.get_coeff(0) == 4); p = fmpzxx(5) + M; tassert(p.length() == 1 && p.get_coeff(0) == 5); frandxx rand; fmpz_polyxx P = fmpz_polyxx::randtest(rand, 10, 20); p = P; for(slong i = 0;i < P.length();++i) tassert(P.get_coeff(i) % M == p.get_coeff(i)); fmpz_polyxx Pp = p.to(); for(slong i = 0;i < P.length();++i) tassert(P.get_coeff(i) % M == Pp.get_coeff(i)); } void test_arithmetic() { fmpzxx M(1031); fmpz_mod_polyxx g(M), h(M); g.set_coeff(0, 17); h.set_coeff(0, 15u + M); tassert((g + h).get_coeff(0) == 15 + 17); frandxx state; g.set_randtest(state, 10); h.set_randtest(state, 10); tassert(((-g) + g).is_zero()); tassert(g - h == g + (-h)); tassert(g*fmpzxx(3) == g + g + g); tassert(g.make_monic() == g*g.lead().invmod(M)); fmpz_mod_polyxx f(M);f = 15u; tassert(f*g == fmpzxx(15)*g); f = h*g;f.truncate(7); tassert(f == mullow(h, g, 7)); f = h / g; tassert(f*g + (h % g) == h); tassert(((h*g) % h).is_zero()); f.set_randtest(state, 10); tassert(h.mulmod(g, f) == ((h*g) % f)); fmpz_mod_polyxx X(M);X.set_coeff(1, 1); fmpz_mod_polyxx one(M);one.set_coeff(0, 1); f = X*X + one; fmpzxx x(7); tassert(evaluate(f, x) == x*x + 1u); tassert(f(x) == evaluate(f, x)); fmpz_mod_polyxx seven(M); seven.set_coeff(0, x); tassert(compose(f, seven).get_coeff(0) == f(x)); tassert(f(seven).length() == 1); } void test_functions() { fmpzxx M(1031); fmpz_mod_polyxx g(M), res(M); g.set_coeff(5, 15); g.truncate(3); tassert(g.is_zero()); g.set_coeff(15, 1); fmpz_mod_polyxx one(M);one = 1u; tassert(g.shift_right(15) == one); tassert(g.shift_right(15).shift_left(15) == g); frandxx rand; g.set_randtest(rand, 15); tassert(g.length() <= 15); g.set_randtest_irreducible(rand, 15); tassert(g.length() <= 15); g.set_randtest_not_zero(rand, 15); tassert(g.length() <= 15 && !g.is_zero()); g.set_coeff(15, 1); g.zero_coeffs(14, 15); tassert(g.get_coeff(14) == 0); // multiplication, division, modulo tested in arithmetic tassert(g.pow(3u) == g*g*g); res = g.pow(15u);res.truncate(12); tassert(res == g.pow_trunc(15u, 12)); tassert(res == g.pow_trunc_binexp(15u, 12)); fmpz_mod_polyxx f(M);f.set_randtest(rand, 10); res = g.pow(10u) % f; tassert(res == g.powmod_binexp(10u, f)); tassert(res == g.powmod_binexp(fmpzxx(10), f)); fmpz_mod_polyxx tmp(M); ltupleref(res, tmp) = f.gcdinv(g); tassert(res == gcd(f, g) && tmp*f % g == res); g.set_randtest_irreducible(rand, 5); tassert(f.invmod(g)*f % g == one); assert_exception((f*g).invmod(g).evaluate()); res = g*f; res.remove(f); tassert(res == g); fmpz_polyxx lift; lift = "5 1 1 1 1 1"; res = lift; tassert(res.derivative().to().to_string() == "4 1 2 3 4"); tassert(f.divrem(g) == ltuple(f / g, f % g)); tassert(f.divrem_basecase(g) == f.divrem(g)); tassert(f.divrem_divconquer(g) == f.divrem(g)); tassert(f.divrem_f(g) == ltuple(1, f / g, f % g)); tassert(f.div_basecase(g) == f / g); tassert(f.rem_basecase(g) == f % g); f.set_coeff(0, 17); res = f*f.inv_series_newton(15);res.truncate(15); tassert(res == one); tassert(f(g) == f.compose_divconquer(g)); tassert(f(g) == f.compose_horner(g)); fmpz_mod_polyxx h(M); h.set_randtest(rand, 15); tassert(f.compose_mod(g, h) == f(g) % h); tassert(f.compose_mod(g, h) == f.compose_mod_horner(g, h)); tassert(f.compose_mod(g, h) == f.compose_mod_brent_kung(g, h)); h.set_randtest_irreducible(rand, 12); tassert(h.gcd(f) == one); tassert(f.gcd_euclidean(f) == f.make_monic()); tassert(f.gcd_f(g) == ltuple(1, f.gcd(g))); tassert(f.gcd_euclidean_f(g) == ltuple(1, f.gcd(g))); fmpz_mod_polyxx R(M), S(M); ltupleref(res, R, S) = f.xgcd(g); tassert(res == R*f + S*g && res == gcd(f, g)); tassert(f.xgcd(g) == f.xgcd_euclidean(g)); } bool equiv_fac(const fmpz_mod_poly_factorxx& fac1, const fmpz_mod_poly_factorxx& fac2) { tassert(fac1.size() == 2); if(fac1.exp(0) == fac1.exp(1)) { if(fac2.exp(0) != fac1.exp(0) || fac2.exp(1) != fac1.exp(0)) return false; return (fac1.p(0) == fac2.p(0) && fac1.p(1) == fac2.p(1)) || (fac1.p(1) == fac2.p(0) && fac1.p(0) == fac2.p(1)); } if(fac1.size() != fac2.size()) return false; if(fac1.exp(0) == fac2.exp(0)) return fac1.exp(1) == fac2.exp(1) && fac1.p(0) == fac2.p(0) && fac1.p(1) == fac2.p(1); else return fac1.exp(0) == fac2.exp(1) && fac1.exp(1) == fac2.exp(0) && fac1.p(0) == fac2.p(1) && fac1.p(1) == fac2.p(0); } void test_factoring() { fmpzxx M(1031); fmpz_mod_polyxx f(M), g(M); frandxx state; f.set_randtest_irreducible(state, 4); f = f.make_monic(); g.set_randtest_irreducible(state, 5); g = g.make_monic(); fmpz_mod_poly_factorxx fac = factor(f*f*g); tassert(fac.size() == 2); if(fac.exp(0) == 1) { tassert(fac.p(0) == g); tassert(fac.p(1) == f && fac.exp(1) == 2); } else { tassert(fac.p(0) == f && fac.exp(0) == 2); tassert(fac.p(1) == g && fac.exp(1) == 1); } fmpz_mod_poly_factorxx fac2;fac2 = fac;fac2.pow(2); fac.insert(g, 1); fac.insert(f, 2); tassert(fac == fac2); fmpz_mod_polyxx prod(f*f*f*g*g); fac = factor(prod); tassert(equiv_fac(fac, factor_cantor_zassenhaus(prod))); tassert(equiv_fac(factor(f*g), factor_berlekamp(f*g))); tassert(equiv_fac(fac, factor_kaltofen_shoup(prod))); std::vector degs(2); fac.realloc(0);fac.set_factor_distinct_deg(f*g, degs); tassert(degs.size() == 2); tassert((degs[0] == f.degree() && degs[1] == g.degree()) || (degs[1] == f.degree() && degs[0] == g.degree())); tassert(f.is_irreducible() && f.is_irreducible_ddf() && f.is_irreducible_rabin()); tassert(f.is_squarefree()); // TODO test set_factor_equal_deg* if(0) print(fac); // test this compiles } void test_randomisation() { frandxx state, state2; fmpzxx M(1031); fmpz_mod_polyxx p(M); p.set_randtest(state, 10); tassert(p == fmpz_mod_polyxx::randtest(M, state2, 10)); p.set_randtest_irreducible(state, 10); tassert(p == fmpz_mod_polyxx::randtest_irreducible(M, state2, 10)); p.set_randtest_not_zero(state, 10); tassert(p == fmpz_mod_polyxx::randtest_not_zero(M, state2, 10)); } void test_radix() { fmpzxx M(1031); fmpz_mod_poly_vecxx v1(10, M), v2(10, M); v1[0].set_coeff(7, 1); tassert(v1 != v2); fmpz_mod_poly_vecxx v3(v1); tassert(v3 == v1); v3[0].set_coeff(1, 1); tassert(v3 != v1); v2[0].set_coeff(7, 1); tassert(v1 == v2); frandxx rand; fmpz_mod_polyxx F = fmpz_mod_polyxx::randtest(M, rand, 10); fmpz_mod_polyxx R = fmpz_mod_polyxx::randtest(M, rand, 3); fmpz_mod_poly_vecxx b(F.degree() / R.degree() + 1, M); fmpz_mod_poly_radixxx rad(R, 15); b = F.radix(rad); tassert(b == F.radix(rad)); fmpz_mod_polyxx f(M); for(slong i = 0;i < b.size();++i) f += b[i]*R.pow(static_cast(i)); tassert(f == F); } void test_printing() { frandxx state; fmpz_mod_polyxx f = fmpz_mod_polyxx::randtest(fmpzxx(7), state, 4); test_print_read(f); f.set_zero(); f.set_coeff(0, 3); f.set_coeff(1, 1); tassert_fprint_pretty(f, "x", "x+3"); } void test_unified_access() { fmpz_mod_polyxx p(fmpzxx(1031)); p.set_coeff(0, 1); const fmpz_mod_polyxx& q = p; tassert(q.lead() == 1); } int main() { std::cout << "fmpz_mod_polyxx...."; test_init(); test_manipulation(); test_assignment(); test_conversion(); test_arithmetic(); test_functions(); test_factoring(); test_randomisation(); test_radix(); test_printing(); test_unified_access(); std::cout << "PASS" << std::endl; return 0; }