Skip to content

Commit 57fdfe0

Browse files
committed
TYP: Static typing support for numpy_quaddtype
1 parent c3dd685 commit 57fdfe0

File tree

5 files changed

+213
-6
lines changed

5 files changed

+213
-6
lines changed

quaddtype/meson.build

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ if openmp_dep.found()
3535
dependencies += openmp_dep
3636
endif
3737

38-
# compiler flags for QBLAS compatibility
38+
# compiler flags for QBLAS compatibility
3939
if not is_windows
4040
# QBLAS requires extended numeric literals for Q suffix support
4141
# if compiler supports (usually gcc)
@@ -61,14 +61,14 @@ foreach optional_attr: optional_variable_attributes
6161
code = '''
6262
#pragma GCC diagnostic error "-Wattributes"
6363
#pragma clang diagnostic error "-Wattributes"
64-
64+
6565
int @0@ foo;
66-
66+
6767
int main() {
6868
return 0;
6969
}
7070
'''.format(attr)
71-
71+
7272
if c.compiles(code, name: optional_attr[0])
7373
cdata.set10(optional_attr[1], true)
7474
message('Thread-local storage support found: @0@'.format(attr))
@@ -122,6 +122,9 @@ srcs = [
122122
py.install_sources(
123123
[
124124
'numpy_quaddtype/__init__.py',
125+
'numpy_quaddtype/__init__.pyi',
126+
'numpy_quaddtype/_quaddtype_main.pyi',
127+
'numpy_quaddtype/py.typed',
125128
],
126129
subdir: 'numpy_quaddtype',
127130
pure: false
@@ -134,4 +137,4 @@ py.extension_module('_quaddtype_main',
134137
install: true,
135138
subdir: 'numpy_quaddtype',
136139
include_directories: [includes, build_includes],
137-
)
140+
)
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
from typing import Final
2+
3+
from ._quaddtype_main import (
4+
QuadPrecDType,
5+
QuadPrecision,
6+
_IntoQuad, # type-check only # pyright: ignore[reportPrivateUsage]
7+
get_num_threads,
8+
get_quadblas_version,
9+
is_longdouble_128,
10+
set_num_threads,
11+
)
12+
13+
__all__ = [
14+
"QuadPrecision",
15+
"QuadPrecDType",
16+
"SleefQuadPrecision",
17+
"LongDoubleQuadPrecision",
18+
"SleefQuadPrecDType",
19+
"LongDoubleQuadPrecDType",
20+
"is_longdouble_128",
21+
"pi",
22+
"e",
23+
"log2e",
24+
"log10e",
25+
"ln2",
26+
"ln10",
27+
"max_value",
28+
"epsilon",
29+
"smallest_normal",
30+
"smallest_subnormal",
31+
"bits",
32+
"precision",
33+
"resolution",
34+
"set_num_threads",
35+
"get_num_threads",
36+
"get_quadblas_version",
37+
]
38+
39+
def SleefQuadPrecision(value: _IntoQuad) -> QuadPrecision: ...
40+
def LongDoubleQuadPrecision(value: _IntoQuad) -> QuadPrecision: ...
41+
def SleefQuadPrecDType() -> QuadPrecDType: ...
42+
def LongDoubleQuadPrecDType() -> QuadPrecDType: ...
43+
44+
pi: Final[QuadPrecision] = ...
45+
e: Final[QuadPrecision] = ...
46+
log2e: Final[QuadPrecision] = ...
47+
log10e: Final[QuadPrecision] = ...
48+
ln2: Final[QuadPrecision] = ...
49+
ln10: Final[QuadPrecision] = ...
50+
max_value: Final[QuadPrecision] = ...
51+
epsilon: Final[QuadPrecision] = ...
52+
smallest_normal: Final[QuadPrecision] = ...
53+
smallest_subnormal: Final[QuadPrecision] = ...
54+
resolution: Final[QuadPrecision] = ...
55+
bits: Final = 128
56+
precision: Final = 33
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
from typing import Any, Literal, TypeAlias, final
2+
3+
import numpy as np
4+
from typing_extensions import Never, Self, override
5+
6+
_Backend: TypeAlias = Literal["sleef", "longdouble"]
7+
_IntoQuad: TypeAlias = QuadPrecision | float | str
8+
_CastsQuad: TypeAlias = _IntoQuad | np.floating[Any] | np.integer[Any] | np.bool_
9+
10+
@final
11+
class QuadPrecDType(np.dtype[QuadPrecision]): # type: ignore[misc, type-var] # pyright: ignore[reportGeneralTypeIssues, reportInvalidTypeArguments]
12+
def __new__(cls, /, backend: _Backend = "sleef") -> Self: ...
13+
14+
# `numpy.dtype` overrides
15+
names: None # pyright: ignore[reportIncompatibleVariableOverride]
16+
@property
17+
@override
18+
def alignment(self) -> Literal[16]: ...
19+
@property
20+
@override
21+
def itemsize(self) -> Literal[16]: ...
22+
@property
23+
@override
24+
def name(self) -> Literal["QuadPrecDType128"]: ...
25+
@property
26+
@override
27+
def byteorder(self) -> Literal["|"]: ...
28+
@property
29+
@override
30+
def char(self) -> Literal["\x00"]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
31+
@property
32+
@override
33+
def kind(self) -> Literal["\x00"]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
34+
@property
35+
@override
36+
def num(self) -> Literal[-1]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
37+
@property
38+
@override
39+
def shape(self) -> tuple[()]: ...
40+
@property
41+
@override
42+
def ndim(self) -> Literal[0]: ...
43+
@property
44+
@override
45+
def fields(self) -> None: ...
46+
@property
47+
@override
48+
def base(self) -> Self: ...
49+
@property
50+
@override
51+
def subdtype(self) -> None: ...
52+
@property
53+
@override
54+
def hasobject(self) -> Literal[False]: ...
55+
@property
56+
@override
57+
def isbuiltin(self) -> Literal[0]: ...
58+
@property
59+
@override
60+
def isnative(self) -> Literal[True]: ...
61+
@property
62+
@override
63+
def isalignedstruct(self) -> Literal[False]: ...
64+
@override
65+
def __getitem__(self, key: Never, /) -> Self: ... # type: ignore[override]
66+
67+
@final
68+
class QuadPrecision: # NOTE: It doesn't inherit from `np.generic` which is type-unsafe
69+
def __new__(cls, /, value: _IntoQuad, backend: _Backend = "sleef") -> Self: ...
70+
71+
# Rich comparison operators
72+
# NOTE: Unlike other numpy scalars, these return `builtins.bool`, not `np.bool`.
73+
@override
74+
def __eq__(self, other: object, /) -> bool: ...
75+
@override
76+
def __ne__(self, other: object, /) -> bool: ...
77+
def __lt__(self, other: _IntoQuad, /) -> bool: ...
78+
def __le__(self, other: _IntoQuad, /) -> bool: ...
79+
def __gt__(self, other: _IntoQuad, /) -> bool: ...
80+
def __ge__(self, other: _IntoQuad, /) -> bool: ...
81+
82+
# Binary operators
83+
def __add__(self, other: _CastsQuad, /) -> Self: ...
84+
def __radd__(self, other: _CastsQuad, /) -> Self: ... # type: ignore[misc]
85+
def __sub__(self, other: _CastsQuad, /) -> Self: ...
86+
def __rsub__(self, other: _CastsQuad, /) -> Self: ...
87+
def __mul__(self, other: _CastsQuad, /) -> Self: ...
88+
def __rmul__(self, other: _CastsQuad, /) -> Self: ... # type: ignore[misc]
89+
def __pow__(self, other: _CastsQuad, mod: None = None, /) -> Self: ...
90+
def __rpow__(self, other: _CastsQuad, mod: None = None, /) -> Self: ...
91+
def __truediv__(self, other: _CastsQuad, /) -> Self: ...
92+
def __rtruediv__(self, other: _CastsQuad, /) -> Self: ...
93+
94+
# Unary operators
95+
def __neg__(self, /) -> Self: ...
96+
def __pos__(self, /) -> Self: ...
97+
def __abs__(self, /) -> Self: ...
98+
99+
# Conversion methods
100+
def __bool__(self, /) -> bool: ...
101+
def __int__(self, /) -> int: ...
102+
def __float__(self, /) -> float: ...
103+
104+
# String representation
105+
@override
106+
def __repr__(self, /) -> str: ...
107+
@override
108+
def __str__(self, /) -> str: ...
109+
110+
#
111+
def is_longdouble_128() -> bool: ...
112+
def get_sleef_constant(
113+
constant_name: Literal[
114+
"pi",
115+
"e",
116+
"log2e",
117+
"log10e",
118+
"ln2",
119+
"ln10",
120+
"max_value",
121+
"epsilon",
122+
"smallest_normal",
123+
"smallest_subnormal",
124+
"bits",
125+
"precision",
126+
"resolution",
127+
],
128+
/,
129+
) -> QuadPrecision: ...
130+
def set_num_threads(num_threads: int, /) -> None: ...
131+
def get_num_threads() -> int: ...
132+
def get_quadblas_version() -> Literal[
133+
"QuadBLAS 1.0.0 - High Performance Quad Precision BLAS"
134+
]: ...

quaddtype/numpy_quaddtype/py.typed

Whitespace-only changes.

quaddtype/pyproject.toml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,18 @@ dependencies = [
2323
test = [
2424
"pytest",
2525
"pytest-run-parallel"
26-
]
26+
]
27+
28+
[tool.pyright]
29+
include = ["numpy_quaddtype/*.pyi"]
30+
typeCheckingMode = "strict"
31+
enableTypeIgnoreComments = false
32+
reportImplicitOverride = true
33+
reportUnnecessaryTypeIgnoreComment = true
34+
35+
[tool.mypy]
36+
strict = true
37+
strict_equality_for_none = true
38+
exclude = ["build", "numpy_quaddtype/src", "subprojects", "tests"]
39+
enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
40+
warn_unreachable = false

0 commit comments

Comments
 (0)