Skip to content

Commit c715d51

Browse files
committed
add tests for fmpq_series
1 parent be98a9e commit c715d51

File tree

3 files changed

+201
-5
lines changed

3 files changed

+201
-5
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ MANIFEST
1414
.local
1515
*.egg-info
1616
.coverage
17+
*.swp

src/flint/fmpq_series.pyx

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ cdef fmpq_series_coerce_operands(x, y):
1919
return acb_series(x), acb_series(y)
2020
return NotImplemented, NotImplemented
2121

22+
cdef any_as_fmpq_series(obj):
23+
if typecheck(obj, fmpq_series):
24+
return obj
25+
if typecheck(obj, fmpz_series):
26+
return fmpq_series(obj)
27+
return NotImplemented
28+
2229
cdef class fmpq_series(flint_series):
2330

2431
cdef fmpq_poly_t val
@@ -41,7 +48,7 @@ cdef class fmpq_series(flint_series):
4148
if val is not None:
4249
if typecheck(val, fmpq_series):
4350
fmpq_poly_set(self.val, (<fmpq_series>val).val)
44-
self.prec = min((<fmpz_series>val).prec, getcap())
51+
self.prec = min((<fmpq_series>val).prec, getcap())
4552
elif typecheck(val, fmpz_series):
4653
fmpq_poly_set_fmpz_poly(self.val, (<fmpz_series>val).val)
4754
self.prec = min((<fmpz_series>val).prec, getcap())
@@ -62,6 +69,23 @@ cdef class fmpq_series(flint_series):
6269
raise ZeroDivisionError("cannot create fmpq_series with zero denominator")
6370
fmpq_poly_scalar_div_fmpz(self.val, self.val, (<fmpz>den).val)
6471

72+
def __richcmp__(s, t, int op):
73+
cdef bint r
74+
if op != 2 and op != 3:
75+
raise TypeError("series cannot be ordered")
76+
s = any_as_fmpq_series(s)
77+
if t is NotImplemented:
78+
return s
79+
t = any_as_fmpq_series(t)
80+
if t is NotImplemented:
81+
return t
82+
r = fmpq_poly_equal((<fmpq_series>s).val, (<fmpq_series>t).val)
83+
if r:
84+
r = (<fmpq_series>s).prec == (<fmpq_series>t).prec
85+
if op == 3:
86+
r = not r
87+
return r
88+
6589
def __len__(self):
6690
return fmpq_poly_length(self.val)
6791

@@ -197,7 +221,7 @@ cdef class fmpq_series(flint_series):
197221
u = fmpq_series.__new__(fmpq_series)
198222

199223
if fmpq_poly_is_zero((<fmpq_series>s).val):
200-
u.cap = cap
224+
(<fmpq_series>u).prec = cap
201225
return u
202226

203227
sval = (<fmpq_series>s).valuation()
@@ -236,6 +260,7 @@ cdef class fmpq_series(flint_series):
236260
return fmpq_series._div_(s, t)
237261

238262
# generic exponentiation (fallback code)
263+
# XXX: use fmpq_poly_pow_trunc instead?
239264
def __pow__(s, ulong exp, mod):
240265
if mod is not None:
241266
raise NotImplementedError("modular exponentiation")
@@ -308,7 +333,7 @@ cdef class fmpq_series(flint_series):
308333
cdef bint one_constant_term(s):
309334
if fmpq_poly_is_zero((<fmpq_series>s).val):
310335
return False
311-
if fmpz_is_one(&((<fmpq_series>s).val.coeffs[0])):
336+
if fmpz_equal(&((<fmpq_series>s).val.coeffs[0]), (<fmpq_series>s).val.den):
312337
return True
313338
return False
314339

test/test.py

Lines changed: 172 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -969,8 +969,178 @@ def set_bad(i):
969969
assert M3.minpoly() == flint.fmpq_poly([1,-4,4]) / 4
970970

971971
def test_fmpq_series():
972-
Z = flint.fmpq_series
973-
Z([1,2])
972+
Qp = flint.fmpq_poly
973+
Q = flint.fmpq_series
974+
Zp = flint.fmpz_poly
975+
Z = flint.fmpz_series
976+
ctx = flint.ctx
977+
assert ctx.cap == 10
978+
s1 = Q([1,2])
979+
s2 = Q([1,2])
980+
s3 = Q([1,1])
981+
s4 = Q([1,2],1,11)
982+
p1 = Qp([1,2])
983+
sz1 = Z([1,2])
984+
sz2 = Z([1,1])
985+
sz3 = Z([1,1],11)
986+
assert (s1 == s2) is True
987+
assert (s1 != s2) is False
988+
assert (s1 == s3) is False
989+
assert (s1 != s3) is True
990+
assert (s1 == s4) is False
991+
assert (s1 != s4) is True
992+
assert (s1 == p1) is False
993+
assert (s1 != p1) is True
994+
assert (s1 == sz1) is True
995+
assert (s1 != sz1) is False
996+
assert (s1 == sz2) is False
997+
assert (s1 != sz2) is True
998+
assert (s1 == sz3) is False
999+
assert (s1 != sz3) is True
1000+
assert (Q([1]) == flint.fmpq(1)) is False
1001+
assert (Q([1]) != flint.fmpq(1)) is True
1002+
assert (Q([1]) == 1) is False
1003+
assert (Q([1]) != 1) is True
1004+
# XXX: These are invalid power series. Should they compare "equal"?
1005+
assert (Q([],-1) == Q([],-1)) is True
1006+
assert (Q([],-1) != Q([],-1)) is False
1007+
assert (Q([],-2) == Q([],-1)) is True
1008+
assert (Q([],-2) != Q([],-1)) is False
1009+
assert (Q([],-1) == Q([],-2)) is True
1010+
assert (Q([],-1) != Q([],-2)) is False
1011+
# XXX: this gives a core dump:
1012+
# s = Q([1,2])
1013+
# s[10**10] = 1
1014+
assert Q([]) == Q([0])
1015+
assert Q([1]) != Q([0])
1016+
assert Q(Q([1])) == Q([1])
1017+
assert Q(Qp([1])) == Q([1])
1018+
assert Q(Zp([1])) == Q([1])
1019+
assert Q(Z([1])) == Q([1])
1020+
assert Q(1) == Q([1])
1021+
assert Q([1],1) == Q([1])
1022+
assert Q([1],2) == Q([flint.fmpq(1,2)])
1023+
assert Q([1],1,10) != Q([1],1,11)
1024+
assert Q([1,2],3) == Q([flint.fmpq(1,3), flint.fmpq(2,3)])
1025+
assert raises(lambda: Q([1],[]), TypeError)
1026+
assert raises(lambda: Q([1],0), ZeroDivisionError)
1027+
assert raises(lambda: Q([1]) < Q([1]), TypeError)
1028+
assert len(Q([1,2])) == 2
1029+
assert Q([1,2]).length() == 2
1030+
s5 = Q([1,2])
1031+
assert s5[1] == 2
1032+
assert s5[2] == 0
1033+
assert s5[-1] == 0
1034+
# XXX: This goes beyond cap. Should it give an error?
1035+
assert s5[100] == 0
1036+
s5[2] = -1
1037+
assert s5[2] == -1
1038+
assert s5 == Q([1,2,-1])
1039+
def set_bad():
1040+
s5[-1] = 3
1041+
assert raises(set_bad, ValueError)
1042+
assert Q([1,2,0,4]).str() == "1 + 2*x + 4*x^3 + O(x^10)"
1043+
assert Q([1,2,0,4]).repr() == "fmpq_series([1, 2, 0, 4], 1, prec=10)"
1044+
assert Q([],1,0).str() == "O(x^0)"
1045+
assert Q([],1,-1).str() == "(invalid power series)"
1046+
assert +Q([1,2]) == Q([1,2])
1047+
assert -Q([1,2]) == Q([-1,-2])
1048+
assert Q([1,2]) + Q([3,4,5]) == Q([4,6,5])
1049+
assert Q([1,2]) + 1 == Q([2,2])
1050+
assert Q([1,2]) + Qp([3,4,5]) == Q([4,6,5])
1051+
assert 1 + Q([1,2]) == Q([2,2])
1052+
assert Qp([1,2]) + Q([3,4,5]) == Q([4,6,5])
1053+
assert raises(lambda: Q([1,2]) + [], TypeError)
1054+
assert raises(lambda: [] + Q([1,2]), TypeError)
1055+
assert Q([1,2]) - Q([3,5]) == Q([-2,-3])
1056+
assert Q([1,2]) - 1 == Q([0,2])
1057+
assert 1 - Q([1,2]) == Q([0,-2])
1058+
assert raises(lambda: [] - Q([1,2]), TypeError)
1059+
assert raises(lambda: Q([1,2]) - [], TypeError)
1060+
assert Q([1,2]) * Q([1,2]) == Q([1,4,4])
1061+
assert 2 * Q([1,2]) == Q([2,4])
1062+
assert Q([1,2]) * 2 == Q([2,4])
1063+
assert raises(lambda: [] * Q([1,2]), TypeError)
1064+
assert raises(lambda: Q([1,2]) * [], TypeError)
1065+
assert Q([1,2]).valuation() == 0
1066+
assert Q([0,2]).valuation() == 1
1067+
assert Q([0,0]).valuation() == -1
1068+
assert Q([1,1]) / Q([1,-1]) == Q([1,2,2,2,2,2,2,2,2,2])
1069+
assert raises(lambda: Q([1,1]) / Q([]), ZeroDivisionError)
1070+
assert Q([],1) / Q([1,-1]) == Q([],1)
1071+
# quotient would not be a power series
1072+
assert raises(lambda: Q([1,1]) / Q([0,1]), ValueError)
1073+
assert Q([1,1]) / Q([2,1]) == Q([512, 256, -128, 64, -32, 16, -8, 4, -2, 1], 1024)
1074+
assert Q([0,1,1]) / Q([0,1,-1]) == Q([1,2,2,2,2,2,2,2,2],1,9)
1075+
assert Q([2,4]) / 2 == Q([1,2])
1076+
assert Q([1,4]) / 2 == Q([1,4],2)
1077+
assert Q([1,1]) / -1 == Q([-1,-1])
1078+
assert raises(lambda: Q([1,1]) / [], TypeError)
1079+
assert raises(lambda: [] / Q([1,1]), TypeError)
1080+
q = Q([1,2],3)
1081+
assert q ** 0 == Q([1])
1082+
assert q ** 1 == q
1083+
assert q ** 2 == Q([1,4,4],9)
1084+
assert q ** 3 == Q([1,6,12,8],27)
1085+
assert q ** 4 == Q([1, 8, 24, 32, 16], 81)
1086+
assert Q([1,2]) ** 2 == Q([1,4,4])
1087+
assert Q([1,2]) ** 2 == Q([1,4,4])
1088+
assert raises(lambda: pow(Q([1,2]), 3, 5), NotImplementedError)
1089+
assert Q([1,2])(Q([0,1,2])) == Q([1,2,4])
1090+
assert raises(lambda: Q([1,2])(Q([1,2])), ValueError)
1091+
assert raises(lambda: Q([1,2])([]), TypeError)
1092+
coeffs = [0, 1, -2, 8, -40, 224, -1344, 8448, -54912, 366080]
1093+
assert Q([0,1,2]).reversion() == Q(coeffs)
1094+
# power series reversion must have valuation 1
1095+
assert raises(lambda: Q([1,1]).reversion(), ValueError)
1096+
assert Q([0,2,1]).reversion() == \
1097+
Q([0,32768,-8192,4096,-2560,1792,-1344,1056,-858,715],65536,10)
1098+
x = Q([0,1])
1099+
expx = x.exp()
1100+
assert expx == Q([362880,362880,181440,60480,15120,3024,504,72,9,1],362880)
1101+
assert expx.inv() == Q([362880,-362880,181440,-60480,15120,-3024,504,-72,9,-1], 362880)
1102+
assert expx.derivative() == Q([40320,40320,20160,6720,1680,336,56,8,1],40320,prec=9)
1103+
assert Q([1,1]).integral() == Q([0,2,1],2)
1104+
assert expx.sqrt() == \
1105+
Q([185794560,92897280,23224320,3870720,483840,48384,4032,288,18,1],185794560)
1106+
assert expx.rsqrt() == \
1107+
Q([185794560,-92897280,23224320,-3870720,483840,-48384,4032,-288,18,-1],185794560)
1108+
assert expx.log() == x
1109+
zero = Q()
1110+
one = Q([1])
1111+
assert zero.exp() == one
1112+
assert one.log() == zero
1113+
assert x.atan() == Q([0,315,0,-105,0,63,0,-45,0,35],315)
1114+
assert x.atanh() == Q([0,315,0,105,0,63,0,45,0,35],315)
1115+
assert x.asin() == Q([0,40320,0,6720,0,3024,0,1800,0,1225],40320)
1116+
assert x.asinh() == Q([0,40320,0,-6720,0,3024,0,-1800,0,1225],40320)
1117+
assert x.sin() == Q([0,362880,0,-60480,0,3024,0,-72,0,1],362880)
1118+
assert x.cos() == Q([40320,0,-20160,0,1680,0,-56,0,1],40320)
1119+
assert x.tan() == Q([0,2835,0,945,0,378,0,153,0,62],2835)
1120+
assert x.sinh() == Q([0,362880,0,60480,0,3024,0,72,0,1],362880)
1121+
assert x.cosh() == Q([40320,0,20160,0,1680,0,56,0,1],40320)
1122+
assert x.tanh() == Q([0,2835,0,-945,0,378,0,-153,0,62],2835)
1123+
# Constant term must be nonzero
1124+
assert raises(lambda: Q([0,1]).inv(), ValueError)
1125+
# Constant term must be 1
1126+
assert raises(lambda: Q([2,1]).sqrt(), ValueError)
1127+
assert raises(lambda: Q([2,1]).rsqrt(), ValueError)
1128+
assert raises(lambda: Q([2,1]).log(), ValueError)
1129+
assert raises(lambda: Q([]).sqrt(), ValueError)
1130+
assert raises(lambda: Q([]).rsqrt(), ValueError)
1131+
assert raises(lambda: Q([]).log(), ValueError)
1132+
# Constant term must be 0
1133+
assert raises(lambda: Q([1,1]).exp(), ValueError)
1134+
assert raises(lambda: Q([1,1]).atan(), ValueError)
1135+
assert raises(lambda: Q([1,1]).atanh(), ValueError)
1136+
assert raises(lambda: Q([1,1]).asin(), ValueError)
1137+
assert raises(lambda: Q([1,1]).asinh(), ValueError)
1138+
assert raises(lambda: Q([1,1]).sin(), ValueError)
1139+
assert raises(lambda: Q([1,1]).cos(), ValueError)
1140+
assert raises(lambda: Q([1,1]).tan(), ValueError)
1141+
assert raises(lambda: Q([1,1]).sinh(), ValueError)
1142+
assert raises(lambda: Q([1,1]).cosh(), ValueError)
1143+
assert raises(lambda: Q([1,1]).tanh(), ValueError)
9741144

9751145
def test_nmod():
9761146
G = flint.nmod

0 commit comments

Comments
 (0)