Skip to content

Commit b8e95bb

Browse files
committed
dirichlet: add type stubs and tests
1 parent e8a296a commit b8e95bb

5 files changed

Lines changed: 107 additions & 2 deletions

File tree

src/flint/test/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ pyfiles = [
1616
'test_fmpq_vec.py',
1717
'test_fmpz_vec.py',
1818
'test_docstrings.py',
19+
'test_dirichlet.py',
1920
]
2021

2122
py.install_sources(

src/flint/test/test_dirichlet.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
from __future__ import annotations
2+
3+
from flint import dirichlet_char, dirichlet_group, fmpz
4+
from flint.test.helpers import is_close_acb, raises
5+
6+
7+
def test_dirichlet_group_basics() -> None:
8+
g = dirichlet_group(5)
9+
assert g.size() == 4
10+
assert g.q == 5
11+
assert g.exponent() == 4
12+
assert repr(g) == "Dirichlet group mod q = 5"
13+
assert str(g) == "Dirichlet group mod q = 5"
14+
15+
assert raises(lambda: dirichlet_group(0), AssertionError)
16+
17+
18+
def test_dirichlet_char_properties() -> None:
19+
chi = dirichlet_char(7, 3)
20+
21+
assert isinstance(chi.group(), dirichlet_group)
22+
assert chi.index() == 1
23+
assert chi.modulus() == 7
24+
assert chi.number() == 3
25+
assert chi.order() == 6
26+
assert chi.is_real() is False
27+
assert chi.is_primitive() is True
28+
assert chi.conductor() == 7
29+
assert chi.is_principal() is False
30+
assert chi.parity() == 1
31+
32+
assert repr(chi) == "dirichlet_char(7, 3)"
33+
assert str(chi) == "dirichlet_char(7, 3)"
34+
35+
assert raises(lambda: dirichlet_char(8, 2), AssertionError)
36+
37+
38+
def test_dirichlet_char_values_and_mul() -> None:
39+
chi = dirichlet_char(7, 3)
40+
principal = dirichlet_char(7, 1)
41+
chi5 = dirichlet_char(7, 5)
42+
43+
assert is_close_acb(chi(7), 0)
44+
assert is_close_acb(chi(2), -0.5 + 0.866025403784439j, tol=1e-12, rel_tol=1e-12)
45+
assert is_close_acb(chi(fmpz(2)), -0.5 + 0.866025403784439j, tol=1e-12, rel_tol=1e-12)
46+
47+
assert chi.chi_exponent(7) is None
48+
assert chi.chi_exponent(2) == 2
49+
assert principal.chi_exponent(2) == 0
50+
51+
prod = chi * chi5
52+
assert prod.number() == 1
53+
for n in [1, 2, 3, 4, 5, 6, 7, 8]:
54+
assert is_close_acb(prod(n), chi(n) * chi5(n), tol=1e-12, rel_tol=1e-12)
55+
56+
assert raises(lambda: chi * dirichlet_char(5, 1), AssertionError)
57+
assert raises(lambda: chi(object()), TypeError) # type: ignore[arg-type]
58+
assert raises(lambda: chi.chi_exponent(object()), TypeError) # type: ignore[arg-type]
59+
60+
61+
def test_dirichlet_char_special_functions() -> None:
62+
chi = dirichlet_char(7, 3)
63+
assert is_close_acb(chi.l_function(2), 0.902247025301257 + 0.232548981277895j, tol=1e-12, rel_tol=1e-12)
64+
assert is_close_acb(chi.l(2), chi.l_function(2), tol=1e-12, rel_tol=1e-12)
65+
66+
zeta_chi = dirichlet_char(1, 1)
67+
assert is_close_acb(zeta_chi.hardy_z(1), -0.736305462867318, tol=1e-12, rel_tol=1e-12)

src/flint/types/acb_series.pyi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ from .acb_poly import acb_poly
88
from .arb import arb
99
from .arb_poly import arb_poly
1010
from .arb_series import arb_series
11+
from .dirichlet import dirichlet_char
1112
from .fmpq import fmpq
1213
from .fmpq_poly import fmpq_poly
1314
from .fmpq_series import fmpq_series
@@ -76,7 +77,7 @@ class acb_series(flint_series[acb]):
7677
def lgamma(self) -> acb_series: ...
7778
def rising(self, n: int, /) -> acb_series: ...
7879
def zeta(self, a: iacb = ..., deflate: bool = ...) -> acb_series: ...
79-
def dirichlet_l(self, chi: tuple[int, int], deflate: bool = ...) -> acb_series: ...
80+
def dirichlet_l(self, chi: dirichlet_char | tuple[int, int], deflate: bool = ...) -> acb_series: ...
8081

8182
@classmethod
8283
def polylog(cls, s: iacb_series, z: iacb) -> acb_series: ...

src/flint/types/dirichlet.pyi

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from __future__ import annotations
2+
3+
from flint.types.acb import acb
4+
from flint.types.fmpz import fmpz
5+
6+
7+
class dirichlet_group:
8+
def __init__(self, q: int, /) -> None: ...
9+
def size(self) -> int: ...
10+
@property
11+
def q(self) -> fmpz: ...
12+
def exponent(self) -> fmpz: ...
13+
def __repr__(self) -> str: ...
14+
def __str__(self) -> str: ...
15+
16+
17+
class dirichlet_char:
18+
def __init__(self, q: int, l: int = 1, /) -> None: ...
19+
def group(self) -> dirichlet_group: ...
20+
def index(self) -> int: ...
21+
def modulus(self) -> fmpz: ...
22+
def number(self) -> int: ...
23+
def order(self) -> int: ...
24+
def is_real(self) -> bool: ...
25+
def is_primitive(self) -> bool: ...
26+
def conductor(self) -> int: ...
27+
def is_principal(self) -> bool: ...
28+
def parity(self) -> int: ...
29+
def __repr__(self) -> str: ...
30+
def __str__(self) -> str: ...
31+
def __mul__(self, other: dirichlet_char, /) -> dirichlet_char: ...
32+
def __call__(self, n: int | fmpz, /) -> acb: ...
33+
def chi_exponent(self, n: int | fmpz, /) -> fmpz | None: ...
34+
def l_function(self, s: int | float | complex | str | acb | fmpz, /) -> acb: ...
35+
def l(self, s: int | float | complex | str | acb | fmpz, /) -> acb: ...
36+
def hardy_z(self, s: int | float | complex | str | acb | fmpz, /) -> acb: ...

src/flint/types/meson.build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ pyfiles = [
4343
'acb_mat.pyi',
4444
'acb_series.pyi',
4545
#
46-
# 'dirichlet.pyi',
46+
'dirichlet.pyi',
4747
#
4848
# '_gr.pyi',
4949
]

0 commit comments

Comments
 (0)