Skip to content

Commit 08fa7e6

Browse files
committed
ENH: Add SIMD operation signbit
1 parent 3712815 commit 08fa7e6

File tree

7 files changed

+77
-0
lines changed

7 files changed

+77
-0
lines changed

numpy/core/src/_simd/_simd.dispatch.c.src

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,10 @@ SIMD_IMPL_INTRIN_2(@intrin@_@sfx@, v@sfx@, v@sfx@, v@sfx@)
316316

317317
SIMD_IMPL_INTRIN_1(not_@sfx@, v@sfx@, v@sfx@)
318318

319+
#if @fp_only@
320+
SIMD_IMPL_INTRIN_1(signbit_@sfx@, v@bsfx@, v@sfx@)
321+
#endif
322+
319323
/**begin repeat1
320324
* #intrin = cmpeq, cmpneq, cmpgt, cmpge, cmplt, cmple#
321325
*/
@@ -551,6 +555,10 @@ SIMD_INTRIN_DEF(@intrin@_@sfx@)
551555
/**end repeat1**/
552556
#endif // shl_imm
553557

558+
#if @fp_only@
559+
SIMD_INTRIN_DEF(signbit_@sfx@)
560+
#endif
561+
554562
/**begin repeat1
555563
* #intrin = and, or, xor, not, cmpeq, cmpneq, cmpgt, cmpge, cmplt, cmple#
556564
*/

numpy/core/src/common/simd/avx2/operators.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,4 +219,12 @@ NPY_FINLINE npyv_b32 npyv_notnan_f32(npyv_f32 a)
219219
NPY_FINLINE npyv_b64 npyv_notnan_f64(npyv_f64 a)
220220
{ return _mm256_castpd_si256(_mm256_cmp_pd(a, a, _CMP_ORD_Q)); }
221221

222+
// signbit
223+
NPY_FINLINE npyv_b32 npyv_signbit_f32(npyv_f32 a) {
224+
return (npyv_shri_s32(_mm256_castps_si256(a), 31));
225+
}
226+
NPY_FINLINE npyv_b64 npyv_signbit_f64(npyv_f64 a) {
227+
return (npyv_shri_s64(_mm256_castpd_si256(a), 63));
228+
}
229+
222230
#endif // _NPY_SIMD_AVX2_OPERATORS_H

numpy/core/src/common/simd/avx512/operators.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#ifndef _NPY_SIMD_AVX512_OPERATORS_H
66
#define _NPY_SIMD_AVX512_OPERATORS_H
77

8+
#include "conversion.h"
9+
810
/***************************
911
* Shifting
1012
***************************/
@@ -321,4 +323,12 @@ NPY_FINLINE npyv_b32 npyv_notnan_f32(npyv_f32 a)
321323
NPY_FINLINE npyv_b64 npyv_notnan_f64(npyv_f64 a)
322324
{ return _mm512_cmp_pd_mask(a, a, _CMP_ORD_Q); }
323325

326+
// signbit
327+
NPY_FINLINE npyv_b32 npyv_signbit_f32(npyv_f32 a) {
328+
return npyv_cvt_b32_s32(npyv_shri_s32(_mm512_castps_si512(a), 31));
329+
}
330+
NPY_FINLINE npyv_b64 npyv_signbit_f64(npyv_f64 a) {
331+
return npyv_cvt_b64_s64(npyv_shri_s64(_mm512_castpd_si512(a), 63));
332+
}
333+
324334
#endif // _NPY_SIMD_AVX512_OPERATORS_H

numpy/core/src/common/simd/neon/operators.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#ifndef _NPY_SIMD_NEON_OPERATORS_H
66
#define _NPY_SIMD_NEON_OPERATORS_H
77

8+
#include "conversion.h"
9+
810
/***************************
911
* Shifting
1012
***************************/
@@ -240,4 +242,14 @@ NPY_FINLINE npyv_b32 npyv_notnan_f32(npyv_f32 a)
240242
{ return vceqq_f64(a, a); }
241243
#endif
242244

245+
// signbit
246+
NPY_FINLINE npyv_b32 npyv_signbit_f32(npyv_f32 a) {
247+
return (vrshrq_n_u32(vreinterpretq_u32_f32(a), 31));
248+
}
249+
#if NPY_SIMD_F64
250+
NPY_FINLINE npyv_b64 npyv_signbit_f64(npyv_f64 a) {
251+
return (vrshrq_n_u64(vreinterpretq_u64_f64(a), 63));
252+
}
253+
#endif
254+
243255
#endif // _NPY_SIMD_NEON_OPERATORS_H

numpy/core/src/common/simd/sse/operators.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,4 +277,12 @@ NPY_FINLINE npyv_b32 npyv_notnan_f32(npyv_f32 a)
277277
NPY_FINLINE npyv_b64 npyv_notnan_f64(npyv_f64 a)
278278
{ return _mm_castpd_si128(_mm_cmpord_pd(a, a)); }
279279

280+
// signbit
281+
NPY_FINLINE npyv_b32 npyv_signbit_f32(npyv_f32 a) {
282+
return (npyv_shri_s32(_mm_castps_si128(a), 31));
283+
}
284+
NPY_FINLINE npyv_b64 npyv_signbit_f64(npyv_f64 a) {
285+
return (npyv_shri_s64(_mm_castpd_si128(a), 63));
286+
}
287+
280288
#endif // _NPY_SIMD_SSE_OPERATORS_H

numpy/core/src/common/simd/vsx/operators.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#ifndef _NPY_SIMD_VSX_OPERATORS_H
66
#define _NPY_SIMD_VSX_OPERATORS_H
77

8+
#include "conversion.h"
9+
810
/***************************
911
* Shifting
1012
***************************/
@@ -241,4 +243,12 @@ NPY_FINLINE npyv_b32 npyv_notnan_f32(npyv_f32 a)
241243
NPY_FINLINE npyv_b64 npyv_notnan_f64(npyv_f64 a)
242244
{ return vec_cmpeq(a, a); }
243245

246+
// signbit
247+
NPY_FINLINE npyv_b32 npyv_signbit_f32(npyv_f32 a) {
248+
return npyv_cvt_b32_f32(npyv_and_f32(a, npyv_cvt_f32_b32(npyv_setall_u32(0x80000000))));
249+
}
250+
NPY_FINLINE npyv_b64 npyv_signbit_f64(npyv_f64 a) {
251+
return npyv_cvt_b64_f64(npyv_and_f64(a, npyv_cvt_f64_b64(npyv_setall_u64(0x8000000000000000))));
252+
}
253+
244254
#endif // _NPY_SIMD_VSX_OPERATORS_H

numpy/core/tests/test_simd.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,27 @@ def test_max(self):
361361
_max = self.max(vdata_a, vdata_b)
362362
assert _max == data_max
363363

364+
def test_signbit(self):
365+
pinf, ninf, nan = self._pinfinity(), self._ninfinity(), self._nan()
366+
data = self._data()
367+
vdata = self.load(data)
368+
369+
mask_true = self._true_mask()
370+
371+
def to_bool(vector):
372+
return [lane == mask_true for lane in vector]
373+
374+
signbit_cases = ((nan, False), (-nan, True), (pinf, False),
375+
(ninf, True))
376+
for case, desired in signbit_cases:
377+
_data_signbit = [desired]*self.nlanes
378+
vsignbit = to_bool(self.signbit(self.setall(case)))
379+
assert vsignbit == pytest.approx(_data_signbit, nan_ok=True)
380+
381+
data_signbit = [a < 0 for a in data]
382+
vadata_signbit = to_bool(self.signbit(vdata))
383+
assert vadata_signbit == data_signbit
384+
364385
def test_min(self):
365386
"""
366387
Test intrinsics:

0 commit comments

Comments
 (0)