1
- """
2
- Tests for elementwise functions
3
-
4
- https://data-apis.github.io/array-api/latest/API_specification/elementwise_functions.html
5
-
6
- This tests behavior that is explicitly mentioned in the spec. Note that the
7
- spec does not make any accuracy requirements for functions, so this does not
8
- test that. Tests for the special cases are generated and tested separately in
9
- special_cases/
10
- """
11
-
12
1
import math
13
2
import operator
14
3
from enum import Enum , auto
@@ -41,13 +30,6 @@ def boolean_and_all_integer_dtypes() -> st.SearchStrategy[DataType]:
41
30
return xps .boolean_dtypes () | all_integer_dtypes ()
42
31
43
32
44
- def isclose (a : float , b : float , rel_tol : float = 0.25 , abs_tol : float = 1 ) -> bool :
45
- """Wraps math.isclose with more generous defaults."""
46
- if not (math .isfinite (a ) and math .isfinite (b )):
47
- raise ValueError (f"{ a = } and { b = } , but input must be finite" )
48
- return math .isclose (a , b , rel_tol = rel_tol , abs_tol = abs_tol )
49
-
50
-
51
33
def mock_int_dtype (n : int , dtype : DataType ) -> int :
52
34
"""Returns equivalent of `n` that mocks `dtype` behaviour."""
53
35
nbits = dh .dtype_nbits [dtype ]
@@ -60,6 +42,40 @@ def mock_int_dtype(n: int, dtype: DataType) -> int:
60
42
return n
61
43
62
44
45
+ # This module tests elementwise functions/operators against a reference
46
+ # implementation. We iterate through the input array(s) and resulting array,
47
+ # casting the indexed arrays to Python scalars and calculating the expected
48
+ # output with `refimpl` function.
49
+ #
50
+ # This is finicky to refactor, but possible and ultimately worthwhile - hence
51
+ # why these *_assert_again_refimpl() utilities exist.
52
+ #
53
+ # Values which are special-cased are generated and passed, but are filtered by
54
+ # the `filter_` callable before they can be asserted against `refimpl`. We
55
+ # automatically generate tests for special cases in the special_cases/ dir. We
56
+ # still pass them here so as to ensure their presence doesn't affect the outputs
57
+ # respective to non-special-cased elements.
58
+ #
59
+ # By default, results are casted to scalars the same way that the inputs are.
60
+ # You can specify a cast via `res_stype, i.e. when a function accepts numerical
61
+ # inputs but returns boolean arrays.
62
+ #
63
+ # By default, floating-point functions/methods are loosely asserted against. Use
64
+ # `strict_check=True` when they should be strictly asserted against, i.e.
65
+ # when a function should return intergrals.
66
+
67
+
68
+ def isclose (a : float , b : float , rel_tol : float = 0.25 , abs_tol : float = 1 ) -> bool :
69
+ """Wraps math.isclose with very generous defaults.
70
+
71
+ This is useful for many floating-point operations where the spec does not
72
+ make accuracy requirements.
73
+ """
74
+ if not (math .isfinite (a ) and math .isfinite (b )):
75
+ raise ValueError (f"{ a = } and { b = } , but input must be finite" )
76
+ return math .isclose (a , b , rel_tol = rel_tol , abs_tol = abs_tol )
77
+
78
+
63
79
def default_filter (s : Scalar ) -> bool :
64
80
"""Returns False when s is a non-finite or a signed zero.
65
81
@@ -168,14 +184,14 @@ def binary_assert_against_refimpl(
168
184
# elementwise methods. We do this by parametrizing a generalised test method
169
185
# with every relevant method and operator.
170
186
#
171
- # Notable arguments in the parameter:
187
+ # Notable arguments in the parameter's context object :
172
188
# - The function object, which for operator test cases is a wrapper that allows
173
189
# test logic to be generalised.
174
190
# - The argument strategies, which can be used to draw arguments for the test
175
191
# case. They may require additional filtering for certain test cases.
176
- # - right_is_scalar (binary parameters), which denotes if the right argument is
177
- # a scalar in a test case. This can be used to appropiately adjust draw
178
- # filtering and test logic.
192
+ # - right_is_scalar (binary parameters only ), which denotes if the right
193
+ # argument is a scalar in a test case. This can be used to appropiately adjust
194
+ # draw filtering and test logic.
179
195
180
196
181
197
func_to_op = {v : k for k , v in dh .op_to_func .items ()}
0 commit comments