Skip to content

Commit e5c49a0

Browse files
committed
TYP: QuadPrecision <: numpy.floating
1 parent 7cff6f3 commit e5c49a0

File tree

1 file changed

+74
-39
lines changed

1 file changed

+74
-39
lines changed

quaddtype/numpy_quaddtype/_quaddtype_main.pyi

Lines changed: 74 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from typing import Any, Literal, TypeAlias, final, overload
22

33
import numpy as np
4+
from numpy._typing import _128Bit # pyright: ignore[reportPrivateUsage]
45
from typing_extensions import Never, Self, override
56

67
_Backend: TypeAlias = Literal["sleef", "longdouble"]
@@ -12,9 +13,10 @@ _IntoQuad: TypeAlias = (
1213
| np.integer[Any]
1314
| np.bool_
1415
) # fmt: skip
16+
_ScalarItemArg: TypeAlias = Literal[0, -1] | tuple[Literal[0, -1]] | tuple[()]
1517

1618
@final
17-
class QuadPrecDType(np.dtype[QuadPrecision]): # type: ignore[misc, type-var] # pyright: ignore[reportGeneralTypeIssues, reportInvalidTypeArguments]
19+
class QuadPrecDType(np.dtype[QuadPrecision]): # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
1820
def __new__(cls, /, backend: _Backend = "sleef") -> Self: ...
1921

2022
# `numpy.dtype` overrides
@@ -70,61 +72,94 @@ class QuadPrecDType(np.dtype[QuadPrecision]): # type: ignore[misc, type-var] #
7072
@override
7173
def __getitem__(self, key: Never, /) -> Self: ... # type: ignore[override]
7274

73-
# NOTE: Until `QuadPrecision` will become a subclass of `np.generic`, this class cannot
74-
# be considered "type-safe".
7575
@final
76-
class QuadPrecision:
76+
class QuadPrecision(np.floating[_128Bit]):
7777
# NOTE: At runtime this constructor also accepts array-likes, for which it returns
7878
# `np.ndarray` instances with `dtype=QuadPrecDType()`.
7979
# But because of mypy limitations, it is currently impossible to annotate
8080
# constructors that do no return instances of their class (or a subclass thereof).
8181
# See https://github.com/python/mypy/issues/18343#issuecomment-2571784915
82+
@override
8283
def __new__(cls, /, value: _IntoQuad, backend: _Backend = "sleef") -> Self: ...
8384

84-
# Attributes
85+
# numpy.floating property overrides
86+
8587
@property
88+
@override
89+
def dtype(self) -> QuadPrecDType: ...
90+
@property
91+
@override
8692
def real(self) -> Self: ...
8793
@property
94+
@override
8895
def imag(self) -> Self: ...
8996

90-
# Rich comparison operators
91-
# NOTE: Unlike other numpy scalars, these return `builtins.bool`, not `np.bool`.
97+
# numpy.floating method overrides
98+
99+
@override
100+
def item(self, arg0: _ScalarItemArg = ..., /) -> Self: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
101+
@override
102+
def tolist(self, /) -> Self: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
103+
104+
# Equality operators
92105
@override
93106
def __eq__(self, other: object, /) -> bool: ...
94107
@override
95108
def __ne__(self, other: object, /) -> bool: ...
96-
def __lt__(self, other: _IntoQuad, /) -> bool: ...
97-
def __le__(self, other: _IntoQuad, /) -> bool: ...
98-
def __gt__(self, other: _IntoQuad, /) -> bool: ...
99-
def __ge__(self, other: _IntoQuad, /) -> bool: ...
100-
101-
# Binary operators
102-
def __add__(self, other: _IntoQuad, /) -> Self: ...
103-
def __radd__(self, other: _IntoQuad, /) -> Self: ...
104-
def __sub__(self, other: _IntoQuad, /) -> Self: ...
105-
def __rsub__(self, other: _IntoQuad, /) -> Self: ...
106-
def __mul__(self, other: _IntoQuad, /) -> Self: ...
107-
def __rmul__(self, other: _IntoQuad, /) -> Self: ...
108-
def __pow__(self, other: _IntoQuad, mod: None = None, /) -> Self: ...
109-
def __rpow__(self, other: _IntoQuad, mod: None = None, /) -> Self: ...
110-
def __truediv__(self, other: _IntoQuad, /) -> Self: ...
111-
def __rtruediv__(self, other: _IntoQuad, /) -> Self: ...
112-
113-
# Unary operators
114-
def __neg__(self, /) -> Self: ...
115-
def __pos__(self, /) -> Self: ...
116-
def __abs__(self, /) -> Self: ...
117-
118-
# Conversion methods
119-
def __bool__(self, /) -> bool: ...
120-
def __int__(self, /) -> int: ...
121-
def __float__(self, /) -> float: ...
122-
123-
# String representation
124-
@override
125-
def __repr__(self, /) -> str: ...
126-
@override
127-
def __str__(self, /) -> str: ...
109+
110+
# Rich comparison operators
111+
# NOTE: Unlike other numpy scalars, these return `builtins.bool`, not `np.bool`.
112+
@override
113+
def __lt__(self, other: _IntoQuad, /) -> bool: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
114+
@override
115+
def __le__(self, other: _IntoQuad, /) -> bool: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
116+
@override
117+
def __gt__(self, other: _IntoQuad, /) -> bool: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
118+
@override
119+
def __ge__(self, other: _IntoQuad, /) -> bool: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
120+
121+
# Binary arithmetic operators
122+
@override
123+
def __add__(self, other: _IntoQuad, /) -> Self: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
124+
@override
125+
def __radd__(self, other: _IntoQuad, /) -> Self: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
126+
@override
127+
def __sub__(self, other: _IntoQuad, /) -> Self: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
128+
@override
129+
def __rsub__(self, other: _IntoQuad, /) -> Self: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
130+
@override
131+
def __mul__(self, other: _IntoQuad, /) -> Self: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
132+
@override
133+
def __rmul__(self, other: _IntoQuad, /) -> Self: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
134+
@override
135+
def __pow__(self, other: _IntoQuad, mod: None = None, /) -> Self: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
136+
@override
137+
def __rpow__(self, other: _IntoQuad, mod: None = None, /) -> Self: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
138+
@override
139+
def __truediv__(self, other: _IntoQuad, /) -> Self: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
140+
@override
141+
def __rtruediv__(self, other: _IntoQuad, /) -> Self: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
142+
143+
# Binary modulo operators
144+
@override
145+
def __floordiv__(self, other: _IntoQuad, /) -> Self: ...
146+
@override
147+
def __rfloordiv__(self, other: _IntoQuad, /) -> Self: ...
148+
@override
149+
def __mod__(self, other: _IntoQuad, /) -> Self: ...
150+
@override
151+
def __rmod__(self, other: _IntoQuad, /) -> Self: ...
152+
@override
153+
def __divmod__(self, other: _IntoQuad, /) -> tuple[Self, Self]: ...
154+
@override
155+
def __rdivmod__(self, other: _IntoQuad, /) -> tuple[Self, Self]: ...
156+
157+
# NOTE: is_integer() and as_integer_ratio() are defined on numpy.floating in the
158+
# stubs, but don't exist at runtime. And because QuadPrecision does not have
159+
# implement them, we use this hacky workaround to emulate their abscence.
160+
# TODO: Remove after https://github.com/numpy/numpy-user-dtypes/issues/216
161+
is_integer: Never # pyright: ignore[reportIncompatibleMethodOverride]
162+
as_integer_ratio: Never # pyright: ignore[reportIncompatibleMethodOverride]
128163

129164
#
130165
def is_longdouble_128() -> bool: ...

0 commit comments

Comments
 (0)