Skip to content

Commit 0872a58

Browse files
authored
Merge pull request #45 from SwayamInSync/arr_nonzero
FEAT: Implementing `PyArray_ArrFuncs_nonzero`
2 parents ef0530f + 34f0dba commit 0872a58

2 files changed

Lines changed: 44 additions & 0 deletions

File tree

src/csrc/dtype.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,25 @@ quadprec_fromstr(char *s, void *dptr, char **endptr, PyArray_Descr *descr_generi
390390
return 0;
391391
}
392392

393+
static npy_bool
394+
quadprec_nonzero(void *data, void *arr)
395+
{
396+
PyArrayObject *arr_obj = (PyArrayObject *)arr;
397+
QuadPrecDTypeObject *descr = (QuadPrecDTypeObject *)PyArray_DESCR(arr_obj);
398+
QuadBackendType backend = descr->backend;
399+
400+
if (backend == BACKEND_SLEEF) {
401+
Sleef_quad val;
402+
memcpy(&val, data, sizeof(Sleef_quad));
403+
return !Sleef_icmpeqq1(val, QUAD_PRECISION_ZERO);
404+
}
405+
else {
406+
long double val;
407+
memcpy(&val, data, sizeof(long double));
408+
return val != 0.0L;
409+
}
410+
}
411+
393412
/*
394413
* Compare function for sorting operations (argsort, sort, etc.)
395414
* Implements PyArray_CompareFunc.
@@ -632,6 +651,7 @@ static PyType_Slot QuadPrecDType_Slots[] = {
632651
{NPY_DT_getitem, &quadprec_getitem},
633652
{NPY_DT_default_descr, &quadprec_default_descr},
634653
{NPY_DT_get_constant, &quadprec_get_constant},
654+
{NPY_DT_PyArray_ArrFuncs_nonzero, &quadprec_nonzero},
635655
{NPY_DT_PyArray_ArrFuncs_compare, &quadprec_compare},
636656
{NPY_DT_PyArray_ArrFuncs_argmax, &quadprec_argmax},
637657
{NPY_DT_PyArray_ArrFuncs_argmin, &quadprec_argmin},

tests/test_quaddtype.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,6 +1531,30 @@ def test_unary_logical_not(x):
15311531
assert isinstance(quad_result, (bool, np.bool_)), f"Result should be bool, got {type(quad_result)}"
15321532

15331533

1534+
@pytest.mark.parametrize("val,expected", [
1535+
("1.0", True),
1536+
("0.5", True),
1537+
("1e-100", True),
1538+
("-1.0", True),
1539+
("0.0", False),
1540+
("-0.0", False),
1541+
])
1542+
def test_bool_0d_array(val, expected):
1543+
"""
1544+
Test boolean conversion on 0-d QuadPrecision arrays.
1545+
1546+
This tests that bool(np.array(QuadPrecision(x))) works correctly
1547+
and doesn't segfault due to missing dtype nonzero function.
1548+
"""
1549+
quad_scalar = QuadPrecision(val)
1550+
arr_0d = np.array(quad_scalar)
1551+
# Ensure it's actually a 0-d array
1552+
assert arr_0d.ndim == 0, f"Expected 0-d array, got {arr_0d.ndim}-d"
1553+
1554+
# This should not segfault
1555+
result = bool(arr_0d)
1556+
assert result == expected, f"bool(np.array(QuadPrecision({val}))) should be {expected}, got {result}"
1557+
15341558
@pytest.mark.parametrize("val", [
15351559
# Small positive values that truncate to 0 when cast to int
15361560
0.5, 0.1, 0.01, 0.001, 0.0001,

0 commit comments

Comments
 (0)