Skip to content

Commit 021c770

Browse files
committed
Implement signbit ufunc
1 parent 2360f75 commit 021c770

File tree

3 files changed

+26
-3
lines changed

3 files changed

+26
-3
lines changed

quaddtype/numpy_quaddtype/src/ops.hpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,24 @@ quad_positive(Sleef_quad *op)
2020
static inline Sleef_quad
2121
quad_sign(Sleef_quad *op)
2222
{
23-
int32_t sign = Sleef_icmpq1(*op, Sleef_cast_from_doubleq1(0.0));
23+
Sleef_quad zero = Sleef_cast_from_doubleq1(0.0);
24+
int32_t sign = Sleef_icmpq1(*op, zero);
2425
// sign(x=NaN) = x; otherwise sign(x) in { -1.0; 0.0; +1.0 }
2526
return Sleef_iunordq1(*op, *op) ? *op : Sleef_cast_from_int64q1(sign);
2627
}
2728

29+
static inline int32_t
30+
quad_signbit(Sleef_quad *op)
31+
{
32+
// FIXME @juntyr or @SwayamInSync: replace with binary implementation
33+
// once we test big and little endian in CI
34+
Sleef_quad zero = Sleef_cast_from_doubleq1(0.0);
35+
Sleef_quad one = Sleef_cast_from_doubleq1(1.0);
36+
Sleef_quad one_signed = Sleef_copysignq1(one, *op);
37+
// signbit(x) = 1 iff copysign(1, x) == -1
38+
return Sleef_icmpltq1(one_signed, zero);
39+
}
40+
2841
static inline Sleef_quad
2942
quad_absolute(Sleef_quad *op)
3043
{
@@ -170,6 +183,12 @@ ld_sign(long double *op)
170183
return *op;
171184
}
172185

186+
static inline int32_t
187+
ld_signbit(long double *op)
188+
{
189+
return signbit(*op);
190+
}
191+
173192
static inline long double
174193
ld_rint(long double *op)
175194
{

quaddtype/numpy_quaddtype/src/umath.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,9 @@ init_quad_unary_ops(PyObject *numpy)
214214
if (create_quad_unary_ufunc<quad_sign, ld_sign>(numpy, "sign") < 0) {
215215
return -1;
216216
}
217+
if (create_quad_unary_ufunc<quad_signbit, ld_signbit>(numpy, "signbit") < 0) {
218+
return -1;
219+
}
217220
if (create_quad_unary_ufunc<quad_rint, ld_rint>(numpy, "rint") < 0) {
218221
return -1;
219222
}

quaddtype/tests/test_quaddtype.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ def test_array_aminmax(op, a, b):
107107
assert np.all((quad_res == float_res) | ((quad_res != quad_res) & (float_res != float_res)))
108108

109109

110-
@pytest.mark.parametrize("op,nop", [("neg", "negative"), ("pos", "positive"), ("abs", "absolute"), (None, "sign")])
110+
@pytest.mark.parametrize("op,nop", [("neg", "negative"), ("pos", "positive"), ("abs", "absolute"), (None, "sign"), (None, "signbit")])
111111
@pytest.mark.parametrize("val", ["3.0", "-3.0", "12.5", "100.0", "0.0", "-0.0", "inf", "-inf", "nan", "-nan"])
112112
def test_unary_ops(op, nop, val):
113113
op_func = None if op is None else getattr(operator, op)
@@ -124,11 +124,12 @@ def test_unary_ops(op, nop, val):
124124
float_result = op_func(float_val)
125125

126126
# FIXME: @juntyr: replace with array_equal once isnan is supported
127-
# FIXME: @juntyr: also check the signbit once that is supported
128127
with np.errstate(invalid="ignore"):
129128
assert (
130129
(np.float64(quad_result) == float_result) or
131130
((float_result != float_result) and (quad_result != quad_result))
131+
) and (
132+
np.signbit(float_result) == np.signbit(quad_result)
132133
), f"{op}({val}) should be {float_result}, but got {quad_result}"
133134

134135

0 commit comments

Comments
 (0)