diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index a4b5ddf8f3..a1a71dab28 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -139,6 +139,53 @@ jobs: with: toolkit: ${{ matrix.toolkit }} + array_api_test: + name: Array API Tests (Metal) + if: github.repository == 'ml-explore/mlx' + needs: mac_build + runs-on: 'macos-26-xlarge' + steps: + - uses: actions/checkout@v7 + - uses: ./.github/actions/setup + with: + toolkit: 'metal' + use-ccache: false + - uses: actions/download-artifact@v8 + with: + path: artifact + pattern: mlx-metal-* + - name: Checkout array-api-tests + uses: actions/checkout@v7 + with: + repository: data-apis/array-api-tests + ref: 'ef5b39f1190d54dca0d9a12646033d2d123afdd5' # v2026.09.08 + submodules: 'true' + path: 'array-api-tests' + persist-credentials: false + - name: Install dependencies + shell: bash + run: | + uv pip install pytest-xdist -r array-api-tests/requirements.txt + - name: Run the test suite + shell: bash + env: + ARRAY_API_TESTS_MODULE: mlx.core + ARRAY_API_TESTS_SKIP_DTYPES: 'float64,complex128' + PYTHONWARNINGS: 'ignore::UserWarning::,ignore::DeprecationWarning::,ignore::RuntimeWarning::' + METAL_DEBUG_ERROR_MODE: 0 + METAL_DEVICE_WRAPPER_TYPE: 1 + run: | + if [[ -d artifact ]] ; then + for SUBDIR in artifact/*; do + rm -rf build dist + mv "$SUBDIR"/* . + break + done + fi + uv pip install dist/*.whl + cd "${GITHUB_WORKSPACE}/array-api-tests" + pytest array_api_tests -v -c pytest.ini -n 2 --max-examples=1000 --derandomize --disable-data-dependent-shapes --disable-deadline -o strict_xfail=True --xfails-file "${GITHUB_WORKSPACE}/python/tests/xp-tests/xfail.txt" --skips-file "${GITHUB_WORKSPACE}/python/tests/xp-tests/skips.txt" + build_documentation: name: Build Documentation if: github.repository == 'ml-explore/mlx' diff --git a/python/tests/xp-tests/skips.txt b/python/tests/xp-tests/skips.txt new file mode 100644 index 0000000000..2bd738bb74 --- /dev/null +++ b/python/tests/xp-tests/skips.txt @@ -0,0 +1,7 @@ +# 64bit dtype not supported https://github.com/ml-explore/mlx/issues/4300 +array_api_tests/test_creation_functions.py::test_eye + +array_api_tests/test_array_object.py::test_getitem_arrays_and_ints_2[None] +array_api_tests/test_array_object.py::test_getitem_arrays_and_ints_2[1] +array_api_tests/test_array_object.py::test_getitem_arrays_and_ints_1[None] +array_api_tests/test_array_object.py::test_getitem_arrays_and_ints_1[1] \ No newline at end of file diff --git a/python/tests/xp-tests/xfail.txt b/python/tests/xp-tests/xfail.txt new file mode 100644 index 0000000000..448183c4c1 --- /dev/null +++ b/python/tests/xp-tests/xfail.txt @@ -0,0 +1,423 @@ +# test_linalg.py +## Missing Extensions (linalg, fft) +array_api_tests/test_linalg.py::test_cholesky +array_api_tests/test_linalg.py::test_det +array_api_tests/test_linalg.py::test_diagonal +array_api_tests/test_linalg.py::test_eigh +array_api_tests/test_linalg.py::test_eigvalsh +array_api_tests/test_linalg.py::test_eig +array_api_tests/test_linalg.py::test_eigvals +array_api_tests/test_linalg.py::test_inv +array_api_tests/test_linalg.py::test_linalg_matmul +array_api_tests/test_linalg.py::test_matmul +array_api_tests/test_linalg.py::test_matrix_norm +array_api_tests/test_linalg.py::test_matrix_power +array_api_tests/test_linalg.py::test_matrix_rank +array_api_tests/test_linalg.py::test_linalg_matrix_transpose +array_api_tests/test_linalg.py::test_outer +array_api_tests/test_linalg.py::test_pinv +array_api_tests/test_linalg.py::test_qr +array_api_tests/test_linalg.py::test_slogdet +array_api_tests/test_linalg.py::test_solve +array_api_tests/test_linalg.py::test_svd +array_api_tests/test_linalg.py::test_svdvals +array_api_tests/test_linalg.py::test_linalg_tensordot +array_api_tests/test_linalg.py::test_tensordot +array_api_tests/test_linalg.py::test_trace +array_api_tests/test_linalg.py::test_linalg_vecdot +array_api_tests/test_linalg.py::test_vecdot +array_api_tests/test_linalg.py::test_vecdot_conj +array_api_tests/test_linalg.py::test_vector_norm +array_api_tests/test_linalg.py::test_eigvals + +# test_fft.py +## Missing Extensions (linalg, fft) +array_api_tests/test_fft.py::test_hfft +array_api_tests/test_fft.py::test_ihfft +array_api_tests/test_fft.py::test_fftfreq +array_api_tests/test_fft.py::test_rfftfreq + +# test_has_names.py +## Missing Functions +array_api_tests/test_has_names.py::test_has_names[linalg-diagonal] +array_api_tests/test_has_names.py::test_has_names[linalg-matmul] +array_api_tests/test_has_names.py::test_has_names[linalg-matrix_norm] +array_api_tests/test_has_names.py::test_has_names[linalg-matrix_power] +array_api_tests/test_has_names.py::test_has_names[linalg-matrix_rank] +array_api_tests/test_has_names.py::test_has_names[linalg-matrix_transpose] +array_api_tests/test_has_names.py::test_has_names[linalg-outer] +array_api_tests/test_has_names.py::test_has_names[linalg-svdvals] +array_api_tests/test_has_names.py::test_has_names[linalg-tensordot] +array_api_tests/test_has_names.py::test_has_names[linalg-trace] +array_api_tests/test_has_names.py::test_has_names[linalg-vecdot] +array_api_tests/test_has_names.py::test_has_names[linalg-vector_norm] +array_api_tests/test_has_names.py::test_has_names[fft-hfft] +array_api_tests/test_has_names.py::test_has_names[fft-ihfft] +array_api_tests/test_has_names.py::test_has_names[elementwise-copysign] +array_api_tests/test_has_names.py::test_has_names[elementwise-hypot] +array_api_tests/test_has_names.py::test_has_names[elementwise-nextafter] +array_api_tests/test_has_names.py::test_has_names[elementwise-signbit] +array_api_tests/test_has_names.py::test_has_names[array_method-__pos__] +array_api_tests/test_has_names.py::test_has_names[array_method-to_device] +array_api_tests/test_has_names.py::test_has_names[array_attribute-device] +array_api_tests/test_has_names.py::test_has_names[set-isin] +array_api_tests/test_has_names.py::test_has_names[set-unique_all] +array_api_tests/test_has_names.py::test_has_names[set-unique_counts] +array_api_tests/test_has_names.py::test_has_names[set-unique_inverse] +array_api_tests/test_has_names.py::test_has_names[set-unique_values] +array_api_tests/test_has_names.py::test_has_names[searching-nonzero] + +# test_signatures.py +## Missing Extensions (linalg, fft) +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.cholesky] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.det] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.diagonal] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.eigh] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.eigvalsh] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.inv] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.matmul] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.matrix_norm] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.matrix_power] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.matrix_rank] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.matrix_transpose] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.outer] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.pinv] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.qr] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.slogdet] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.solve] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.svd] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.svdvals] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.tensordot] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.trace] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.vecdot] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.vector_norm] +array_api_tests/test_signatures.py::test_extension_func_signature[fft.hfft] +array_api_tests/test_signatures.py::test_extension_func_signature[fft.ihfft] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.cholesky] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.det] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.eigh] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.eigvalsh] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.inv] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.slogdet] +array_api_tests/test_signatures.py::test_extension_func_signature[linalg.solve] + +## Missing functions +array_api_tests/test_signatures.py::test_array_method_signature[__pos__] +array_api_tests/test_signatures.py::test_array_method_signature[to_device] +array_api_tests/test_signatures.py::test_func_signature[signbit] +array_api_tests/test_signatures.py::test_func_signature[nextafter] +array_api_tests/test_signatures.py::test_func_signature[hypot] +array_api_tests/test_signatures.py::test_func_signature[copysign] +array_api_tests/test_signatures.py::test_func_signature[nonzero] +array_api_tests/test_signatures.py::test_func_signature[isin] +array_api_tests/test_signatures.py::test_func_signature[unique_all] +array_api_tests/test_signatures.py::test_func_signature[unique_counts] +array_api_tests/test_signatures.py::test_func_signature[unique_inverse] +array_api_tests/test_signatures.py::test_func_signature[unique_values] + +## Missing arguments +### Missing argument `include_initial` +array_api_tests/test_signatures.py::test_func_signature[cumulative_sum] +### Missing argument `include_initial` +array_api_tests/test_signatures.py::test_func_signature[cumulative_prod] +### Missing argument `dtype` +array_api_tests/test_signatures.py::test_func_signature[prod] +### Missing argument `correction` +array_api_tests/test_signatures.py::test_func_signature[std] +### Missing argument `dtype` +array_api_tests/test_signatures.py::test_func_signature[sum] +### Missing argument `correction` +array_api_tests/test_signatures.py::test_func_signature[var] +### Missing argument `sorter` +array_api_tests/test_signatures.py::test_func_signature[searchsorted] +### Missing argument `device` +array_api_tests/test_signatures.py::test_func_signature[asarray] +### Missing argument `device` +array_api_tests/test_signatures.py::test_func_signature[empty_like] +### Missing argument `device` +array_api_tests/test_signatures.py::test_func_signature[from_dlpack] +### Missing argument `device` +array_api_tests/test_signatures.py::test_func_signature[full_like] +### Missing argument `device` +array_api_tests/test_signatures.py::test_func_signature[ones_like] +### Missing argument `device` +array_api_tests/test_signatures.py::test_func_signature[zeros_like] +### Missing arguments `prepend` `append` +array_api_tests/test_signatures.py::test_func_signature[diff] +### rejects an integer `axes` argument +array_api_tests/test_signatures.py::test_func_signature[permute_dims] +### Missing argument `copy` +array_api_tests/test_signatures.py::test_func_signature[reshape] +### Missing arguments `descending` `stable` +array_api_tests/test_signatures.py::test_func_signature[argsort] +### Missing arguments `descending` `stable` +array_api_tests/test_signatures.py::test_func_signature[sort] +### Missing `min` argument +array_api_tests/test_signatures.py::test_func_signature[clip] + + +# test_operators_and_elementwise_functions.py +## Missing functions +array_api_tests/test_operators_and_elementwise_functions.py::test_copysign +array_api_tests/test_operators_and_elementwise_functions.py::test_hypot +array_api_tests/test_operators_and_elementwise_functions.py::test_nextafter +array_api_tests/test_operators_and_elementwise_functions.py::test_positive[__pos__] +array_api_tests/test_operators_and_elementwise_functions.py::test_signbit +array_api_tests/test_operators_and_elementwise_functions.py::test_binary_with_scalars_real[nextafter] +array_api_tests/test_operators_and_elementwise_functions.py::test_binary_with_scalars_real[hypot] +array_api_tests/test_operators_and_elementwise_functions.py::test_binary_with_scalars_real[copysign] + +## Missing complex kernels +array_api_tests/test_operators_and_elementwise_functions.py::test_acosh +array_api_tests/test_operators_and_elementwise_functions.py::test_asinh +array_api_tests/test_operators_and_elementwise_functions.py::test_atanh +array_api_tests/test_operators_and_elementwise_functions.py::test_expm1 + +## Missing arguments +### edge case +array_api_tests/test_operators_and_elementwise_functions.py::test_clip + +## Loss of precision in the complex plane +array_api_tests/test_operators_and_elementwise_functions.py::test_acos +array_api_tests/test_operators_and_elementwise_functions.py::test_asin +array_api_tests/test_operators_and_elementwise_functions.py::test_atan + +## Other failures +### wraps shift counts instead of returning zero for shifts >= the integer width +array_api_tests/test_operators_and_elementwise_functions.py::test_bitwise_left_shift[bitwise_left_shift(x1, x2)] +### wraps shift counts instead of returning zero for shifts >= the integer width +array_api_tests/test_operators_and_elementwise_functions.py::test_bitwise_left_shift[__lshift__(x1, x2)] +### wraps shift counts instead of returning zero for shifts >= the integer width +array_api_tests/test_operators_and_elementwise_functions.py::test_bitwise_left_shift[__ilshift__(x1, x2)] +### wraps shift counts instead of returning zero for shifts >= the integer width +array_api_tests/test_operators_and_elementwise_functions.py::test_bitwise_right_shift[__rshift__(x1, x2)] +### wraps shift counts instead of returning zero for shifts >= the integer width +array_api_tests/test_operators_and_elementwise_functions.py::test_bitwise_right_shift[__irshift__(x1, x2)] +### wraps shift counts instead of returning zero for shifts >= the integer width +array_api_tests/test_operators_and_elementwise_functions.py::test_divide[divide(x1, x2)] +### wraps shift counts instead of returning zero for shifts >= the integer width +array_api_tests/test_operators_and_elementwise_functions.py::test_divide[__truediv__(x1, x2)] +### wraps shift counts instead of returning zero for shifts >= the integer width +array_api_tests/test_operators_and_elementwise_functions.py::test_divide[__itruediv__(x1, x2)] +### truncates toward zero instead of flooring negative results +array_api_tests/test_operators_and_elementwise_functions.py::test_log1p +### does not accept a scalar argument +array_api_tests/test_operators_and_elementwise_functions.py::test_binary_with_scalars_real[atan2] + +# test_inspection_functions.py +## Missing arguments +### Missing argument `device` +array_api_tests/test_inspection_functions.py::test_array_namespace_info_dtypes + +## Other failures +### Missing attribute '__array_api_version__' +array_api_tests/test_inspection_functions.py::TestInspection::test_capabilities + +# test_statistical_functions.py +## Missing arguments +### Missing argument `correction` +array_api_tests/test_statistical_functions.py::test_std +### Missing argument `correction` +array_api_tests/test_statistical_functions.py::test_var +### Missing argument `include_initial` and does not promote uint8 results to uint32 +array_api_tests/test_statistical_functions.py::test_cumulative_sum +### Missing argument `include_initial` and does not promote uint8 results to uint32 +array_api_tests/test_statistical_functions.py::test_cumulative_prod +### Missing argument `include_initial` and does not promote uint8 results to uint32 +array_api_tests/test_statistical_functions.py::test_prod +### Missing argument `include_initial` and does not promote uint8 results to uint32 +array_api_tests/test_statistical_functions.py::test_sum + +# test_manipulation_functions.py +## Missing arguments +### Missing argument `copy` +array_api_tests/test_manipulation_functions.py::test_reshape + +## Other failures +### `repeats` only accepts int +array_api_tests/test_manipulation_functions.py::test_repeat +### `source` `destination` only accepts ints +array_api_tests/test_manipulation_functions.py::test_moveaxis + +# test_data_type_functions.py +## Missing arguments +### Missing argument `copy` +array_api_tests/test_data_type_functions.py::test_astype +### +array_api_tests/test_data_type_functions.py::test_can_cast +### +array_api_tests/test_data_type_functions.py::test_finfo[dtype0] +### +array_api_tests/test_data_type_functions.py::test_finfo[dtype1] +### Missing attribute `bits` +array_api_tests/test_data_type_functions.py::test_iinfo[dtype0] +### Missing attribute `bits` +array_api_tests/test_data_type_functions.py::test_iinfo[dtype1] +### Missing attribute `bits` +array_api_tests/test_data_type_functions.py::test_iinfo[dtype2] +### Missing attribute `bits` +array_api_tests/test_data_type_functions.py::test_iinfo[dtype3] +### Missing attribute `bits` +array_api_tests/test_data_type_functions.py::test_iinfo[dtype4] +### Missing attribute `bits` +array_api_tests/test_data_type_functions.py::test_iinfo[dtype5] +### Missing attribute `bits` +array_api_tests/test_data_type_functions.py::test_iinfo[dtype6] +### Missing attribute `bits` +array_api_tests/test_data_type_functions.py::test_iinfo[dtype7] + +## Other failures +### MLX result_type() does not accept Python scalar values alongside dtypes +array_api_tests/test_data_type_functions.py::TestResultType::test_with_scalars +### returns a list instead of the required tuple +array_api_tests/test_data_type_functions.py::test_broadcast_arrays +### MLX broadcast_shapes() requires at least one shape +array_api_tests/test_data_type_functions.py::TestBroadcastShapes::test_empty + + +# test_searching_functions.py +## Missing arguments +### Missing argument `sorter` +array_api_tests/test_searching_functions.py::test_searchsorted +### Missing argument `sorter` +array_api_tests/test_searching_functions.py::test_searchsorted_with_scalars + +## Other failures +### returns uint32 indices instead of the required default signed integer dtype +array_api_tests/test_searching_functions.py::test_argmax +### returns uint32 indices instead of the required default signed integer dtype +array_api_tests/test_searching_functions.py::test_argmin + +# test_array_object.py +## Other failures +array_api_tests/test_array_object.py::test_setitem_masking + +# test_utility_functions.py +## Misisng arguments +### Missing argument `append` `prepend` +array_api_tests/test_utility_functions.py::test_diff_append_prepend + +# test_creation_functions.py +## Other failures +### copy=False is not supported, https://github.com/ml-explore/mlx/pull/4036 +array_api_tests/test_creation_functions.py::test_asarray_arrays + +# test_dlpack.py +## Other failures +array_api_tests/test_dlpack.py::test_from_dlpack + +# test_sorting_functions.py +## Missing attributes +### Missing attribute `stable` +array_api_tests/test_sorting_functions.py::test_argsort +### Missing attribute `stable` +array_api_tests/test_sorting_functions.py::test_sort + +# test_special_cases.py +## Special cases +array_api_tests/test_special_cases.py::test_unary[expm1((real(x_i) is +0 or real(x_i) == -0) and imag(x_i) is +0) -> 0 + 0j] +array_api_tests/test_special_cases.py::test_unary[expm1(isfinite(real(x_i)) and imag(x_i) is +infinity) -> NaN + NaN j] +array_api_tests/test_special_cases.py::test_unary[expm1(isfinite(real(x_i)) and imag(x_i) is NaN) -> NaN + NaN j] +array_api_tests/test_special_cases.py::test_unary[expm1(real(x_i) is +infinity and imag(x_i) is +0) -> +infinity + 0j] +array_api_tests/test_special_cases.py::test_unary[expm1(real(x_i) is -infinity and imag(x_i) is +infinity) -> -1 + 0j] +array_api_tests/test_special_cases.py::test_unary[expm1(real(x_i) is +infinity and imag(x_i) is +infinity) -> infinity + NaN j] +array_api_tests/test_special_cases.py::test_unary[expm1(real(x_i) is -infinity and imag(x_i) is NaN) -> -1 + 0j] +array_api_tests/test_special_cases.py::test_unary[expm1(real(x_i) is +infinity and imag(x_i) is NaN) -> infinity + NaN j] +array_api_tests/test_special_cases.py::test_unary[expm1(real(x_i) is NaN and imag(x_i) is +0) -> NaN + 0j] +array_api_tests/test_special_cases.py::test_unary[expm1(real(x_i) is NaN and not imag(x_i) == 0) -> NaN + NaN j] +array_api_tests/test_special_cases.py::test_unary[expm1(real(x_i) is NaN and imag(x_i) is NaN) -> NaN + NaN j] +array_api_tests/test_special_cases.py::test_unary[log1p((real(x_i) is +infinity or real(x_i) == -infinity) and imag(x_i) is NaN) -> +infinity + NaN j] +array_api_tests/test_special_cases.py::test_unary[log1p(real(x_i) is NaN and imag(x_i) is +infinity) -> +infinity + NaN j] +array_api_tests/test_special_cases.py::test_unary[sign(x_i is NaN) -> NaN] +array_api_tests/test_special_cases.py::test_unary[signbit(x_i is +0) -> False] +array_api_tests/test_special_cases.py::test_unary[signbit(x_i is -0) -> True] +array_api_tests/test_special_cases.py::test_unary[signbit(x_i is +infinity) -> False] +array_api_tests/test_special_cases.py::test_unary[signbit(x_i is -infinity) -> True] +array_api_tests/test_special_cases.py::test_unary[signbit(isfinite(x_i) and x_i > 0) -> False] +array_api_tests/test_special_cases.py::test_unary[signbit(isfinite(x_i) and x_i < 0) -> True] +array_api_tests/test_special_cases.py::test_unary[signbit(x_i is +NaN) -> False] +array_api_tests/test_special_cases.py::test_unary[signbit(x_i is -NaN) -> True] +array_api_tests/test_special_cases.py::test_unary[sinh(real(x_i) is +0 and imag(x_i) is +infinity) -> 0 + NaN j] +array_api_tests/test_special_cases.py::test_unary[sinh(real(x_i) is +0 and imag(x_i) is NaN) -> 0 + NaN j] +array_api_tests/test_special_cases.py::test_unary[sinh(real(x_i) is +infinity and imag(x_i) is +0) -> +infinity + 0j] +array_api_tests/test_special_cases.py::test_unary[sinh(real(x_i) is +infinity and imag(x_i) is +infinity) -> infinity + NaN j] +array_api_tests/test_special_cases.py::test_unary[sinh(real(x_i) is +infinity and imag(x_i) is NaN) -> infinity + NaN j] +array_api_tests/test_special_cases.py::test_unary[sinh(real(x_i) is NaN and imag(x_i) is +0) -> NaN + 0j] +array_api_tests/test_special_cases.py::test_unary[sqrt(real(x_i) is +infinity and isfinite(imag(x_i)) and imag(x_i) > 0) -> +infinity + 0 j] +array_api_tests/test_special_cases.py::test_unary[tanh(real(x_i) is +0 and imag(x_i) is +infinity) -> +0 + NaN j] +array_api_tests/test_special_cases.py::test_unary[tanh(real(x_i) is +0 and imag(x_i) is NaN) -> +0 + NaN j] +array_api_tests/test_special_cases.py::test_unary[tanh(real(x_i) is +infinity and imag(x_i) is +infinity) -> 1 + 0j] +array_api_tests/test_special_cases.py::test_unary[tanh(real(x_i) is +infinity and imag(x_i) is NaN) -> 1 + 0j] +array_api_tests/test_special_cases.py::test_unary[tanh(real(x_i) is NaN and imag(x_i) is +0) -> NaN + 0j] +array_api_tests/test_special_cases.py::test_binary[copysign(x1_i is NaN and x2_i < 0) -> NaN] +array_api_tests/test_special_cases.py::test_binary[copysign(x1_i is NaN and x2_i is -0) -> NaN] +array_api_tests/test_special_cases.py::test_binary[copysign(x1_i is NaN and x2_i is +0) -> NaN] +array_api_tests/test_special_cases.py::test_binary[copysign(x1_i is NaN and x2_i > 0) -> NaN] +array_api_tests/test_special_cases.py::test_binary[nextafter(x1_i is NaN or x2_i is NaN) -> NaN] +array_api_tests/test_special_cases.py::test_binary[nextafter(x1_i is -0 and x2_i is +0) -> +0] +array_api_tests/test_special_cases.py::test_binary[nextafter(x1_i is +0 and x2_i is -0) -> -0] +array_api_tests/test_special_cases.py::test_binary[remainder(x1_i is -0 and x2_i > 0) -> +0] +array_api_tests/test_special_cases.py::test_binary[remainder(x1_i is +0 and x2_i < 0) -> -0] +array_api_tests/test_special_cases.py::test_binary[__mod__(x1_i is -0 and x2_i > 0) -> +0] +array_api_tests/test_special_cases.py::test_binary[__mod__(x1_i is +0 and x2_i < 0) -> -0] +array_api_tests/test_special_cases.py::test_iop[__imod__(x1_i is -0 and x2_i > 0) -> +0] +array_api_tests/test_special_cases.py::test_iop[__imod__(x1_i is +0 and x2_i < 0) -> -0] +array_api_tests/test_special_cases.py::test_unary[acos((real(x_i) is +0 or real(x_i) == -0) and imag(x_i) is NaN) -> \u03c0/2 + NaN j] +array_api_tests/test_special_cases.py::test_unary[acos(isfinite(real(x_i)) and imag(x_i) is +infinity) -> \u03c0/2] +array_api_tests/test_special_cases.py::test_unary[acos(real(x_i) is -infinity and isfinite(imag(x_i)) and imag(x_i) > 0) -> \u03c0] +array_api_tests/test_special_cases.py::test_unary[acos(real(x_i) is +infinity and isfinite(imag(x_i)) and imag(x_i) > 0) -> +0] +array_api_tests/test_special_cases.py::test_unary[acos(real(x_i) is -infinity and imag(x_i) is +infinity) -> 3\u03c0/4] +array_api_tests/test_special_cases.py::test_unary[acos(real(x_i) is +infinity and imag(x_i) is +infinity) -> \u03c0/4] +array_api_tests/test_special_cases.py::test_unary[acos((real(x_i) is +infinity or real(x_i) == -infinity) and imag(x_i) is NaN) -> NaN \u00b1 infinity j] +array_api_tests/test_special_cases.py::test_unary[acos(real(x_i) is NaN and imag(x_i) is +infinity) -> NaN] +array_api_tests/test_special_cases.py::test_unary[acosh((real(x_i) is +0 or real(x_i) == -0) and imag(x_i) is +0) -> +0 + \u03c0j/2] +array_api_tests/test_special_cases.py::test_unary[acosh(isfinite(real(x_i)) and imag(x_i) is +infinity) -> +infinity + \u03c0j/2] +array_api_tests/test_special_cases.py::test_unary[acosh(isfinite(real(x_i)) and real(x_i) != 0 and imag(x_i) is NaN) -> NaN + NaN j] +array_api_tests/test_special_cases.py::test_unary[acosh(real(x_i) is +0 and imag(x_i) is NaN) -> NaN \u00b1 \u03c0j/2] +array_api_tests/test_special_cases.py::test_unary[acosh(real(x_i) is -infinity and isfinite(imag(x_i)) and imag(x_i) > 0) -> +infinity + \u03c0j] +array_api_tests/test_special_cases.py::test_unary[acosh(real(x_i) is +infinity and isfinite(imag(x_i)) and imag(x_i) > 0) -> +infinity + 0j] +array_api_tests/test_special_cases.py::test_unary[acosh(real(x_i) is -infinity and imag(x_i) is +infinity) -> +infinity + 3\u03c0j/4] +array_api_tests/test_special_cases.py::test_unary[acosh(real(x_i) is +infinity and imag(x_i) is +infinity) -> +infinity + \u03c0j/4] +array_api_tests/test_special_cases.py::test_unary[acosh((real(x_i) is +infinity or real(x_i) == -infinity) and imag(x_i) is NaN) -> +infinity + NaN j] +array_api_tests/test_special_cases.py::test_unary[acosh(real(x_i) is NaN and isfinite(imag(x_i))) -> NaN + NaN j] +array_api_tests/test_special_cases.py::test_unary[acosh(real(x_i) is NaN and imag(x_i) is +infinity) -> +infinity + NaN j] +array_api_tests/test_special_cases.py::test_unary[acosh(real(x_i) is NaN and imag(x_i) is NaN) -> NaN + NaN j] +array_api_tests/test_special_cases.py::test_unary[asinh(real(x_i) is +0 and imag(x_i) is +0) -> +0 + 0j] +array_api_tests/test_special_cases.py::test_unary[asinh(isfinite(real(x_i)) and real(x_i) > 0 and imag(x_i) is +infinity) -> +infinity + \u03c0j/2] +array_api_tests/test_special_cases.py::test_unary[asinh(isfinite(real(x_i)) and imag(x_i) is NaN) -> NaN + NaN j] +array_api_tests/test_special_cases.py::test_unary[asinh(real(x_i) is +infinity and isfinite(imag(x_i)) and imag(x_i) > 0) -> +infinity + 0j] +array_api_tests/test_special_cases.py::test_unary[asinh(real(x_i) is +infinity and imag(x_i) is +infinity) -> +infinity + \u03c0j/4] +array_api_tests/test_special_cases.py::test_unary[asinh(real(x_i) is NaN and imag(x_i) is +0) -> NaN + 0j] +array_api_tests/test_special_cases.py::test_unary[asinh(real(x_i) is NaN and isfinite(imag(x_i)) and imag(x_i) != 0) -> NaN + NaN j] +array_api_tests/test_special_cases.py::test_unary[asinh(real(x_i) is NaN and imag(x_i) is +infinity) -> \u00b1infinity + NaN j] +array_api_tests/test_special_cases.py::test_unary[asinh(real(x_i) is NaN and imag(x_i) is NaN) -> NaN + NaN j] +array_api_tests/test_special_cases.py::test_unary[atan(x_i is -0) -> -0] +array_api_tests/test_special_cases.py::test_unary[atanh(real(x_i) is +0 and imag(x_i) is +0) -> +0 + 0j] +array_api_tests/test_special_cases.py::test_unary[atanh(real(x_i) is +0 and imag(x_i) is NaN) -> +0 + NaN j] +array_api_tests/test_special_cases.py::test_unary[atanh(real(x_i) is 1 and imag(x_i) is +0) -> +infinity + 0j] +array_api_tests/test_special_cases.py::test_unary[atanh(isfinite(real(x_i)) and real(x_i) > 0 and imag(x_i) is +infinity) -> +0 + \u03c0j/2] +array_api_tests/test_special_cases.py::test_unary[atanh(isfinite(real(x_i)) and real(x_i) != 0 and imag(x_i) is NaN) -> NaN + NaN j] +array_api_tests/test_special_cases.py::test_unary[atanh(real(x_i) is +infinity and isfinite(imag(x_i)) and imag(x_i) > 0) -> +0 + \u03c0j/2] +array_api_tests/test_special_cases.py::test_unary[atanh(real(x_i) is +infinity and imag(x_i) is +infinity) -> +0 + \u03c0j/2] +array_api_tests/test_special_cases.py::test_unary[atanh(real(x_i) is +infinity and imag(x_i) is NaN) -> +0 + NaN j] +array_api_tests/test_special_cases.py::test_unary[atanh(real(x_i) is NaN and isfinite(imag(x_i))) -> NaN + NaN j] +array_api_tests/test_special_cases.py::test_unary[atanh(real(x_i) is NaN and imag(x_i) is +infinity) -> \u00b10 + \u03c0j/2] +array_api_tests/test_special_cases.py::test_unary[atanh(real(x_i) is NaN and imag(x_i) is NaN) -> NaN + NaN j] +array_api_tests/test_special_cases.py::test_unary[clip(x_i is NaN) -> NaN] +array_api_tests/test_special_cases.py::test_unary[cosh(real(x_i) is +0 and imag(x_i) is +infinity) -> NaN + 0j] +array_api_tests/test_special_cases.py::test_unary[cosh(real(x_i) is +0 and imag(x_i) is NaN) -> NaN + 0j] +array_api_tests/test_special_cases.py::test_unary[cosh(real(x_i) is +infinity and imag(x_i) is +0) -> +infinity + 0j] +array_api_tests/test_special_cases.py::test_unary[cosh(real(x_i) is +infinity and imag(x_i) is +infinity) -> +infinity + NaN j] +array_api_tests/test_special_cases.py::test_unary[cosh(real(x_i) is +infinity and imag(x_i) is NaN) -> +infinity + NaN j] +array_api_tests/test_special_cases.py::test_unary[cosh(real(x_i) is NaN and (imag(x_i) is +0 or imag(x_i) == -0)) -> NaN + 0j] +array_api_tests/test_special_cases.py::test_unary[acos((real(x_i) is +infinity or real(x_i) == -infinity) and imag(x_i) is NaN) -> NaN \xb1 infinity j] +array_api_tests/test_special_cases.py::test_unary[acosh(real(x_i) is +0 and imag(x_i) is NaN) -> NaN \xb1 \u03c0j/2] +array_api_tests/test_special_cases.py::test_unary[acos(real(x_i) is +infinity and imag(x_i) is +infinity) -> \u03c0/4 - infinity j] +array_api_tests/test_special_cases.py::test_unary[acos(real(x_i) is -infinity and imag(x_i) is +infinity) -> 3\u03c0/4 - infinity j] +array_api_tests/test_special_cases.py::test_unary[acos(real(x_i) is NaN and imag(x_i) is +infinity) -> NaN - infinity j] +array_api_tests/test_special_cases.py::test_unary[asinh(real(x_i) is NaN and imag(x_i) is +infinity) -> \xb1infinity + NaN j] +array_api_tests/test_special_cases.py::test_unary[atanh(real(x_i) is NaN and imag(x_i) is +infinity) -> \xb10 + \u03c0j/2] +array_api_tests/test_special_cases.py::test_unary[acos(isfinite(real(x_i)) and imag(x_i) is +infinity) -> \u03c0/2 - infinity j] +array_api_tests/test_special_cases.py::test_unary[acos(real(x_i) is -infinity and isfinite(imag(x_i)) and imag(x_i) > 0) -> \u03c0 - infinity j] +array_api_tests/test_special_cases.py::test_unary[acos(real(x_i) is +infinity and isfinite(imag(x_i)) and imag(x_i) > 0) -> +0 - infinity j] +array_api_tests/test_special_cases.py::test_unary[sign((real(x_i) is -0 or real(x_i) == +0) and (imag(x_i) is -0 or imag(x_i) == +0)) -> 0 + 0j] \ No newline at end of file