Skip to content

Commit 0511f62

Browse files
committed
improve coverage
1 parent 4258169 commit 0511f62

File tree

3 files changed

+385
-4
lines changed

3 files changed

+385
-4
lines changed

src/flint/test/test_all.py

Lines changed: 372 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3826,6 +3826,377 @@ def test_fq_default():
38263826

38273827
assert (a*a).is_square()
38283828

3829+
3830+
def test_fq_default_poly():
3831+
from flint import fq_default_ctx, fq_default_poly_ctx, fq_default, fq_default_poly, fmpz, fmpz_poly
3832+
3833+
# fmpz_mod_poly_ctx tests
3834+
F = fq_default_ctx(11, 3)
3835+
R1 = fq_default_poly_ctx(F)
3836+
R2 = fq_default_poly_ctx(11, 3)
3837+
R3 = fq_default_poly_ctx(13, 5)
3838+
3839+
assert raises(lambda: fq_default_poly_ctx("AAA"), TypeError)
3840+
assert (R1 == R1) is True
3841+
assert (R1 != R1) is False
3842+
assert (R1 == R2) is True
3843+
assert (R1 != R2) is False
3844+
assert (R1 != R3) is True
3845+
assert (R1 == R3) is False
3846+
assert (R1 != "AAA") is True
3847+
assert (R1 == "AAA") is False
3848+
3849+
assert (hash(R1) == hash(R1)) is True
3850+
assert (hash(R1) == hash(R2)) is True
3851+
assert (hash(R1) != hash(R3)) is True
3852+
3853+
assert str(R1) == "Context for fq_default_poly with field: Context for fq_default in GF(11^3)[z]/(z^3 + 2*z + 9)"
3854+
assert str(R1) == str(R2)
3855+
assert repr(R3) == "fq_default_poly_ctx(fq_default_ctx(13, 5, 'z', x^5 + 4*x + 11, 'FQ_NMOD'))"
3856+
3857+
assert R1.characteristic() == 11
3858+
assert R3.prime() == 13
3859+
3860+
assert R1.zero().is_zero()
3861+
assert R1.zero() == 0
3862+
assert R1.one().is_one()
3863+
assert R1.one() == 1
3864+
assert R1.gen().is_gen()
3865+
assert R1.gen() == R1([0,1])
3866+
3867+
# Random testing
3868+
f = R1.random_element()
3869+
assert f.degree() <= 3
3870+
f = R1.random_element(degree=5, monic=True)
3871+
assert f.degree() <= 5
3872+
assert f.is_monic()
3873+
f = R1.random_element(degree=100, irreducible=True)
3874+
assert f.degree() <= 100
3875+
assert f.is_irreducible()
3876+
f = R1.random_element(degree=1, monic=True, irreducible=True)
3877+
assert f.degree() <= 1
3878+
assert f.is_irreducible()
3879+
assert f.is_monic()
3880+
assert raises(lambda: R1.random_element(degree=-123), ValueError)
3881+
assert raises(lambda: R1.random_element(monic="A"), ValueError)
3882+
assert raises(lambda: R1.random_element(irreducible="A"), ValueError)
3883+
3884+
# Conversion tests
3885+
F = fq_default_ctx(11)
3886+
F_other = fq_default_ctx(13)
3887+
R = fq_default_poly_ctx(F)
3888+
R_other = fq_default_poly_ctx(F_other)
3889+
3890+
assert raises(lambda: fq_default_poly(1, "A"), TypeError) # Need a valid context
3891+
assert raises(lambda: R(R_other([1,2,3])), ValueError) # field must match
3892+
assert raises(lambda: R(F_other(2)), ValueError) # field must match
3893+
assert raises(lambda: R([F(1), F_other(2)]), ValueError) # field must match
3894+
assert raises(lambda: R([F(1), "A"]), TypeError) # need to be able to cast to fmpz_mod
3895+
3896+
f1 = R([int(-1),int(-2),int(-3)])
3897+
f2 = R([fmpz(-1),fmpz(-2),fmpz(-3)])
3898+
f3 = R([F(-1),F(-2),F(-3)])
3899+
f4 = R(fmpz_poly([-1, -2, -3]))
3900+
f5 = R(f4)
3901+
3902+
assert str(f1) == "8*x^2 + 9*x + 10"
3903+
assert str(f2) == "8*x^2 + 9*x + 10"
3904+
assert str(f3) == "8*x^2 + 9*x + 10"
3905+
assert str(f4) == "8*x^2 + 9*x + 10"
3906+
assert str(f5) == "8*x^2 + 9*x + 10"
3907+
3908+
f1 = R(5)
3909+
f2 = R(fmpz(6))
3910+
f3 = R(F(7))
3911+
assert str(f1) == "5"
3912+
assert str(f2) == "6"
3913+
assert str(f3) == "7"
3914+
3915+
# Printing
3916+
f = R([5, 6, 7, 8])
3917+
assert str(f) == "8*x^3 + 7*x^2 + 6*x + 5"
3918+
3919+
# Get and Set tests
3920+
f = R([5, 6, 7, 8])
3921+
assert f[0] == 5
3922+
assert repr(f[0]) == "5"
3923+
f[0] = 7
3924+
assert repr(f[0]) == "7"
3925+
assert str(f) == "8*x^3 + 7*x^2 + 6*x + 7"
3926+
3927+
# TODO: currently repr does pretty printing
3928+
# just like str, we should address this. Mainly,
3929+
# the issue is we want nice `repr` behaviour in
3930+
# interactive shells, which currently is why this
3931+
# choice has been made
3932+
assert str(f) == repr(f)
3933+
3934+
assert f[-1] == 0
3935+
assert raises(lambda: f.__setitem__(-1, 1), ValueError)
3936+
assert raises(lambda: f.__setitem__(1, "A"), TypeError)
3937+
3938+
# Comparisons
3939+
f1 = R([1,2,3])
3940+
f2 = R([12,13,14])
3941+
f3 = R([4,5,6])
3942+
f4 = R([3])
3943+
3944+
assert (f1 == f2) is True
3945+
assert (f1 != f3) is True
3946+
assert (f1 != "1") is True
3947+
assert (f4 == 3) is True
3948+
assert (hash(f1) == hash(f2)) is True
3949+
assert raises(lambda: f1 > f2, TypeError)
3950+
assert raises(lambda: f1 >= f2, TypeError)
3951+
assert raises(lambda: f1 < f2, TypeError)
3952+
assert raises(lambda: f1 <= f2, TypeError)
3953+
3954+
assert len(f1) == f1.length() == 3
3955+
assert f1.degree() == 2
3956+
3957+
f1 = R([0])
3958+
f2 = R([1])
3959+
f3 = R([0, 1])
3960+
3961+
assert f1.is_zero() is True
3962+
assert f2.is_one() is True
3963+
assert f3.is_gen() is True
3964+
3965+
# Arithmetic
3966+
p_sml = 163
3967+
p_med = 1013
3968+
p_big = 2**127 - 1
3969+
3970+
R_sml = fq_default_poly_ctx(p_sml)
3971+
R_med = fq_default_poly_ctx(p_med)
3972+
R_big = fq_default_poly_ctx(p_big)
3973+
R_sml_ext = fq_default_poly_ctx(p_sml, 5)
3974+
R_med_ext = fq_default_poly_ctx(p_med, 3)
3975+
R_big_ext = fq_default_poly_ctx(p_big, 2)
3976+
3977+
F_cmp = fq_default_ctx(11)
3978+
R_cmp = fq_default_poly_ctx(F_cmp)
3979+
f_cmp = R_cmp([1,2,3,4,5])
3980+
3981+
for R_test in [R_sml, R_med, R_big, R_sml_ext, R_med_ext, R_big_ext]:
3982+
F_test = R_test.base_field()
3983+
while True:
3984+
nqr = F_test.random_element()
3985+
if not nqr.is_square():
3986+
break
3987+
3988+
f = R_test([-1,-2])
3989+
g = R_test([-3,-4])
3990+
3991+
# pos, neg
3992+
assert f is +f
3993+
assert -f == R_test([1,2])
3994+
3995+
# add
3996+
assert raises(lambda: f + f_cmp, ValueError)
3997+
assert raises(lambda: f + "AAA", TypeError)
3998+
assert raises(lambda: "AAA" + f, TypeError)
3999+
assert f + g == R_test([-4,-6])
4000+
assert f + 1 == R_test([0,-2])
4001+
assert f + fmpz(1) == R_test([0,-2])
4002+
assert f + F_test(1) == R_test([0,-2])
4003+
assert 1 + f == R_test([0,-2])
4004+
assert fmpz(1) + f == R_test([0,-2])
4005+
assert F_test(1) + f == R_test([0,-2])
4006+
4007+
# sub
4008+
assert raises(lambda: f - f_cmp, ValueError)
4009+
assert raises(lambda: f - "AAA", TypeError)
4010+
assert raises(lambda: "AAA" - f, TypeError)
4011+
assert f - g == R_test([2, 2])
4012+
assert f - 1 == R_test([-2,-2])
4013+
assert f - fmpz(1) == R_test([-2,-2])
4014+
assert f - F_test(1) == R_test([-2,-2])
4015+
assert 1 - f == R_test([2, 2])
4016+
assert fmpz(1) - f == R_test([2, 2])
4017+
assert F_test(1) - f == R_test([2, 2])
4018+
4019+
# mul
4020+
assert raises(lambda: f * f_cmp, ValueError)
4021+
assert raises(lambda: f * "AAA", TypeError)
4022+
assert raises(lambda: "AAA" * f, TypeError)
4023+
assert f * g == R_test([3, 4 + 6, 8])
4024+
assert f * 2 == R_test([-2,-4])
4025+
assert f * fmpz(2) == R_test([-2,-4])
4026+
assert f * F_test(2) == R_test([-2,-4])
4027+
assert 2 * f == R_test([-2,-4])
4028+
assert fmpz(2) * f == R_test([-2,-4])
4029+
assert F_test(2) * f == R_test([-2,-4])
4030+
4031+
# Exact division
4032+
assert raises(lambda: f.exact_division(f_cmp), ValueError)
4033+
assert raises(lambda: f.exact_division("AAA"), TypeError)
4034+
assert raises(lambda: f.exact_division(0), ZeroDivisionError)
4035+
4036+
assert (f * g).exact_division(g) == f
4037+
assert raises(lambda: f.exact_division(g), DomainError)
4038+
4039+
# true div
4040+
assert raises(lambda: f / "AAA", TypeError)
4041+
assert raises(lambda: f / 0, ZeroDivisionError)
4042+
4043+
assert (f + f) / 2 == f
4044+
assert (f + f) / fmpz(2) == f
4045+
assert (f + f) / F_test(2) == f
4046+
4047+
# floor div
4048+
assert raises(lambda: f // f_cmp, ValueError)
4049+
assert raises(lambda: f // "AAA", TypeError)
4050+
assert raises(lambda: "AAA" // f, TypeError)
4051+
assert (f * g) // g == f
4052+
assert (f + f) // 2 == f
4053+
assert (f + f) // fmpz(2) == f
4054+
assert (f + f) // F_test(2) == f
4055+
assert 2 // R_test(2) == 1
4056+
assert (f + 1) // f == 1
4057+
4058+
# pow
4059+
assert raises(lambda: f**(-2), ValueError)
4060+
assert f*f == f**2
4061+
assert f*f == f**fmpz(2)
4062+
4063+
# pow_mod
4064+
# assert ui and fmpz exp agree for polynomials and generators
4065+
R_gen = R_test.gen()
4066+
assert pow(f, 2**60, g) == pow(pow(f, 2**30, g), 2**30, g)
4067+
assert pow(R_gen, 2**60, g) == pow(pow(R_gen, 2**30, g), 2**30, g)
4068+
4069+
# Check other typechecks for pow_mod
4070+
assert raises(lambda: pow(f, -2, g), ValueError)
4071+
assert raises(lambda: pow(f, 1, "A"), TypeError)
4072+
assert raises(lambda: pow(f, "A", g), TypeError)
4073+
assert raises(lambda: f.pow_mod(2**32, g, mod_rev_inv="A"), TypeError)
4074+
4075+
# Shifts
4076+
assert raises(lambda: R_test([1,2,3]).left_shift(-1), ValueError)
4077+
assert raises(lambda: R_test([1,2,3]).right_shift(-1), ValueError)
4078+
assert R_test([1,2,3]).left_shift(3) == R_test([0,0,0,1,2,3])
4079+
assert R_test([1,2,3]).right_shift(1) == R_test([2,3])
4080+
4081+
# Mod
4082+
assert raises(lambda: f % "AAA", TypeError)
4083+
assert raises(lambda: tuple() % f, TypeError), f'{"AAA" % f = }'
4084+
4085+
assert f % 1 == 0
4086+
assert R_test.one() % 1 == 0
4087+
assert 100 % R_test.one() == 0
4088+
assert (f*g + 1) % f == 1
4089+
assert (f*g + g) % f == (g % f)
4090+
assert f % R_test([0,1]) == f.constant_coefficient()
4091+
4092+
# Evaluation
4093+
h = R_test([0, 1])
4094+
assert h(1) == 1
4095+
assert h(-1) == R_test.base_field()(-1)
4096+
h = R_test([0, 0, 1])
4097+
assert h(1) == h(-1)
4098+
assert raises(lambda: h("AAA"), TypeError)
4099+
4100+
# compose
4101+
assert raises(lambda: h.compose("AAA"), TypeError)
4102+
4103+
# compose mod
4104+
mod = R_test([1,2,3,4])
4105+
assert f.compose(h) % mod == f.compose_mod(h, mod)
4106+
assert raises(lambda: h.compose_mod("AAA", mod), TypeError)
4107+
assert raises(lambda: h.compose_mod(f, "AAA"), TypeError)
4108+
assert raises(lambda: h.compose_mod(f, R_test(0)), ZeroDivisionError)
4109+
4110+
# Reverse
4111+
assert raises(lambda: h.reverse(degree=-100), ValueError)
4112+
assert R_test([-1,-2,-3]).reverse() == R_test([-3,-2,-1])
4113+
4114+
# monic
4115+
assert R_test([1,2]).monic() == R_test([1 / F_test(2), 1])
4116+
4117+
# Square
4118+
assert f*f == f**2 == f.square()
4119+
4120+
# mulmod
4121+
assert f.mul_mod(f, g) == (f*f) % g
4122+
assert raises(lambda: f.mul_mod(f, "AAA"), TypeError)
4123+
assert raises(lambda: f.mul_mod("AAA", g), TypeError)
4124+
4125+
# pow_mod
4126+
assert f.pow_mod(2, g) == (f*f) % g
4127+
assert raises(lambda: f.pow_mod(2, "AAA"), TypeError)
4128+
4129+
# divmod
4130+
S, T = f.divmod(g)
4131+
assert S*g + T == f
4132+
assert raises(lambda: f.divmod("AAA"), TypeError)
4133+
4134+
# gcd
4135+
assert raises(lambda: f.gcd("f"), TypeError)
4136+
4137+
# xgcd
4138+
assert raises(lambda: (f).xgcd("f_cmp"), TypeError)
4139+
4140+
f_inv = f.inverse_series_trunc(2)
4141+
assert (f * f_inv) % R_test([0,0,1]) == 1
4142+
assert raises(lambda: R_test([0,1]).inverse_series_trunc(2), ZeroDivisionError)
4143+
4144+
# sqrt
4145+
f1 = R_test.random_element(irreducible=True)
4146+
assert raises(lambda: f1.sqrt(), ValueError)
4147+
assert (f1*f1).sqrt() in [f1, -f1]
4148+
4149+
# sqrt series
4150+
f_non_square = R_test([nqr, 1, 1, 1])
4151+
f_zero = R_test([0, 1, 1, 1])
4152+
assert raises(lambda: f_non_square.sqrt_trunc(1), ValueError)
4153+
assert raises(lambda: f_zero.sqrt_trunc(1), ZeroDivisionError)
4154+
assert raises(lambda: f_non_square.inv_sqrt_trunc(1), ValueError)
4155+
assert raises(lambda: f_zero.inv_sqrt_trunc(1), ZeroDivisionError)
4156+
4157+
# deflation
4158+
f1 = R_test([1,0,2,0,3])
4159+
assert raises(lambda: f1.deflate(100), ValueError)
4160+
assert f1.deflate(2) == R_test([1,2,3])
4161+
4162+
# factor
4163+
ff = R_test([3,2,1]) * R_test([3,2,1]) * R_test([5,4,3])
4164+
ff_rebuild = R_test.one()
4165+
c, facs = ff.factor()
4166+
ff_rebuild *= c
4167+
for p, e in facs:
4168+
assert p.is_irreducible()
4169+
ff_rebuild *= p**e
4170+
assert ff_rebuild == ff
4171+
4172+
assert set(ff.factor()[1]) == set(ff.factor()[1])
4173+
assert raises(lambda: R_test([0,0,1]).complex_roots(), DomainError)
4174+
4175+
# truncate things
4176+
f = R_test.random_element()
4177+
g = R_test.random_element()
4178+
h = R_test.random_element()
4179+
x = R_test.gen()
4180+
f_trunc = f % x**3
4181+
4182+
assert f.equal_trunc(f_trunc, 3)
4183+
assert not f.equal_trunc("A", 3)
4184+
assert not f.equal_trunc(f_cmp, 3)
4185+
4186+
assert raises(lambda: f.add_trunc("A", 1), TypeError)
4187+
assert raises(lambda: f.add_trunc(f_cmp, 1), ValueError)
4188+
assert f.add_trunc(g, 3) == (f + g) % x**3
4189+
4190+
assert raises(lambda: f.sub_trunc("A", 1), TypeError)
4191+
assert raises(lambda: f.sub_trunc(f_cmp, 1), ValueError)
4192+
assert f.sub_trunc(g, 3) == (f - g) % x**3
4193+
4194+
assert raises(lambda: f.mul_low("A", h), TypeError)
4195+
assert raises(lambda: f.mul_low(g, "A"), TypeError)
4196+
assert f.mul_low(g, 3) == (f * g) % x**3
4197+
4198+
assert raises(lambda: f.pow_trunc(-1, 5), ValueError)
4199+
38294200
def test_all_tests():
38304201
test_funcs = {f for name, f in globals().items() if name.startswith("test_")}
38314202
untested = test_funcs - set(all_tests)
@@ -3892,6 +4263,7 @@ def test_all_tests():
38924263
test_matrices_solve,
38934264

38944265
test_fq_default,
4266+
test_fq_default_poly,
38954267

38964268
test_arb,
38974269

0 commit comments

Comments
 (0)