Skip to content

Commit f698111

Browse files
authored
fmod logaddexp floor_divide remainder support for binaryop (#6549)
1 parent b88e091 commit f698111

31 files changed

Lines changed: 1709 additions & 12 deletions

src/layer/arm/binaryop_arm.cpp

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,15 @@ MAKE_FUNCTION(binary_op_rdiv, y / x, vdivq_f32(y, x))
272272
MAKE_FUNCTION(binary_op_rdiv, y / x, div_ps(y, x))
273273
#endif
274274
MAKE_FUNCTION(binary_op_rpow, (float)powf(y, x), pow_ps(y, x))
275-
MAKE_FUNCTION(binary_op_atan2, (float)atan2f(x, y), atan2_ps(x, y))
276-
MAKE_FUNCTION(binary_op_ratan2, (float)atan2f(y, x), atan2_ps(y, x))
275+
MAKE_FUNCTION(binary_op_atan2, atan2f(x, y), atan2_ps(x, y))
276+
MAKE_FUNCTION(binary_op_ratan2, atan2f(y, x), atan2_ps(y, x))
277+
MAKE_FUNCTION(binary_op_fmod, (float)fmodf(x, y), fmod_ps(x, y))
278+
MAKE_FUNCTION(binary_op_rfmod, (float)fmodf(y, x), fmod_ps(y, x))
279+
MAKE_FUNCTION(binary_op_logaddexp, (float)(std::max(x, y) + log1pf(expf(std::min(x, y) - std::max(x, y)))), logaddexp_ps(x, y))
280+
MAKE_FUNCTION(binary_op_floor_divide, (float)floorf(x / y), floor_divide_ps(x, y))
281+
MAKE_FUNCTION(binary_op_rfloor_divide, (float)floorf(y / x), floor_divide_ps(y, x))
282+
MAKE_FUNCTION(binary_op_remainder, (float)remainderf(x, y), remainder_ps(x, y))
283+
MAKE_FUNCTION(binary_op_rremainder, (float)remainderf(y, x), remainder_ps(y, x))
277284
// *INDENT-ON*
278285
// clang-format on
279286

@@ -297,6 +304,13 @@ static void binary_op_vector(const float* ptr, const float* ptr1, float* outptr,
297304
if (op_type == BinaryOp::Operation_RPOW) return binary_op_vector<binary_op_rpow>(ptr, ptr1, outptr, aw, bw, ap, bp);
298305
if (op_type == BinaryOp::Operation_ATAN2) return binary_op_vector<binary_op_atan2>(ptr, ptr1, outptr, aw, bw, ap, bp);
299306
if (op_type == BinaryOp::Operation_RATAN2) return binary_op_vector<binary_op_ratan2>(ptr, ptr1, outptr, aw, bw, ap, bp);
307+
if (op_type == BinaryOp::Operation_FMOD) return binary_op_vector<binary_op_fmod>(ptr, ptr1, outptr, aw, bw, ap, bp);
308+
if (op_type == BinaryOp::Operation_RFMOD) return binary_op_vector<binary_op_rfmod>(ptr, ptr1, outptr, aw, bw, ap, bp);
309+
if (op_type == BinaryOp::Operation_LOGADDEXP) return binary_op_vector<binary_op_logaddexp>(ptr, ptr1, outptr, aw, bw, ap, bp);
310+
if (op_type == BinaryOp::Operation_FLOOR_DIVIDE) return binary_op_vector<binary_op_floor_divide>(ptr, ptr1, outptr, aw, bw, ap, bp);
311+
if (op_type == BinaryOp::Operation_RFLOOR_DIVIDE) return binary_op_vector<binary_op_rfloor_divide>(ptr, ptr1, outptr, aw, bw, ap, bp);
312+
if (op_type == BinaryOp::Operation_REMAINDER) return binary_op_vector<binary_op_remainder>(ptr, ptr1, outptr, aw, bw, ap, bp);
313+
if (op_type == BinaryOp::Operation_RREMAINDER) return binary_op_vector<binary_op_rremainder>(ptr, ptr1, outptr, aw, bw, ap, bp);
300314

301315
// should never reach here
302316
}
@@ -441,10 +455,18 @@ static int get_reverse_op_type(int op_type)
441455
if (op_type == BinaryOp::Operation_DIV) return BinaryOp::Operation_RDIV;
442456
if (op_type == BinaryOp::Operation_POW) return BinaryOp::Operation_RPOW;
443457
if (op_type == BinaryOp::Operation_ATAN2) return BinaryOp::Operation_RATAN2;
458+
if (op_type == BinaryOp::Operation_FMOD) return BinaryOp::Operation_RFMOD;
459+
if (op_type == BinaryOp::Operation_FLOOR_DIVIDE) return BinaryOp::Operation_RFLOOR_DIVIDE;
460+
if (op_type == BinaryOp::Operation_REMAINDER) return BinaryOp::Operation_RREMAINDER;
461+
444462
if (op_type == BinaryOp::Operation_RSUB) return BinaryOp::Operation_SUB;
445463
if (op_type == BinaryOp::Operation_RDIV) return BinaryOp::Operation_DIV;
446464
if (op_type == BinaryOp::Operation_RPOW) return BinaryOp::Operation_POW;
447465
if (op_type == BinaryOp::Operation_RATAN2) return BinaryOp::Operation_ATAN2;
466+
if (op_type == BinaryOp::Operation_RFMOD) return BinaryOp::Operation_FMOD;
467+
if (op_type == BinaryOp::Operation_RFLOOR_DIVIDE) return BinaryOp::Operation_FLOOR_DIVIDE;
468+
if (op_type == BinaryOp::Operation_RREMAINDER) return BinaryOp::Operation_REMAINDER;
469+
448470
return op_type;
449471
}
450472

@@ -844,6 +866,13 @@ static void binary_op_vector_bf16s(const unsigned short* ptr, const unsigned sho
844866
if (op_type == BinaryOp::Operation_RPOW) return binary_op_vector_bf16s<binary_op_rpow>(ptr, ptr1, outptr, aw, bw, ap, bp);
845867
if (op_type == BinaryOp::Operation_ATAN2) return binary_op_vector_bf16s<binary_op_atan2>(ptr, ptr1, outptr, aw, bw, ap, bp);
846868
if (op_type == BinaryOp::Operation_RATAN2) return binary_op_vector_bf16s<binary_op_ratan2>(ptr, ptr1, outptr, aw, bw, ap, bp);
869+
if (op_type == BinaryOp::Operation_FMOD) return binary_op_vector_bf16s<binary_op_fmod>(ptr, ptr1, outptr, aw, bw, ap, bp);
870+
if (op_type == BinaryOp::Operation_RFMOD) return binary_op_vector_bf16s<binary_op_rfmod>(ptr, ptr1, outptr, aw, bw, ap, bp);
871+
if (op_type == BinaryOp::Operation_LOGADDEXP) return binary_op_vector_bf16s<binary_op_logaddexp>(ptr, ptr1, outptr, aw, bw, ap, bp);
872+
if (op_type == BinaryOp::Operation_FLOOR_DIVIDE) return binary_op_vector_bf16s<binary_op_floor_divide>(ptr, ptr1, outptr, aw, bw, ap, bp);
873+
if (op_type == BinaryOp::Operation_RFLOOR_DIVIDE) return binary_op_vector_bf16s<binary_op_rfloor_divide>(ptr, ptr1, outptr, aw, bw, ap, bp);
874+
if (op_type == BinaryOp::Operation_REMAINDER) return binary_op_vector_bf16s<binary_op_remainder>(ptr, ptr1, outptr, aw, bw, ap, bp);
875+
if (op_type == BinaryOp::Operation_RREMAINDER) return binary_op_vector_bf16s<binary_op_rremainder>(ptr, ptr1, outptr, aw, bw, ap, bp);
847876

848877
// should never reach here
849878
}
@@ -889,6 +918,13 @@ static void binary_op_vector_scalar_b_bf16s(const unsigned short* ptr, float b,
889918
if (op_type == BinaryOp::Operation_RPOW) return binary_op_vector_scalar_b_bf16s<binary_op_rpow>(ptr, b, outptr, size);
890919
if (op_type == BinaryOp::Operation_ATAN2) return binary_op_vector_scalar_b_bf16s<binary_op_atan2>(ptr, b, outptr, size);
891920
if (op_type == BinaryOp::Operation_RATAN2) return binary_op_vector_scalar_b_bf16s<binary_op_ratan2>(ptr, b, outptr, size);
921+
if (op_type == BinaryOp::Operation_FMOD) return binary_op_vector_scalar_b_bf16s<binary_op_fmod>(ptr, b, outptr, size);
922+
if (op_type == BinaryOp::Operation_RFMOD) return binary_op_vector_scalar_b_bf16s<binary_op_rfmod>(ptr, b, outptr, size);
923+
if (op_type == BinaryOp::Operation_LOGADDEXP) return binary_op_vector_scalar_b_bf16s<binary_op_logaddexp>(ptr, b, outptr, size);
924+
if (op_type == BinaryOp::Operation_FLOOR_DIVIDE) return binary_op_vector_scalar_b_bf16s<binary_op_floor_divide>(ptr, b, outptr, size);
925+
if (op_type == BinaryOp::Operation_RFLOOR_DIVIDE) return binary_op_vector_scalar_b_bf16s<binary_op_rfloor_divide>(ptr, b, outptr, size);
926+
if (op_type == BinaryOp::Operation_REMAINDER) return binary_op_vector_scalar_b_bf16s<binary_op_remainder>(ptr, b, outptr, size);
927+
if (op_type == BinaryOp::Operation_RREMAINDER) return binary_op_vector_scalar_b_bf16s<binary_op_rremainder>(ptr, b, outptr, size);
892928

893929
// should never reach here
894930
}

src/layer/arm/binaryop_arm_asimdhp.cpp

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,87 @@
1212
namespace ncnn {
1313

1414
#if __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
15+
static inline float16x4_t fmod_f16(const float16x4_t& x, const float16x4_t& y)
16+
{
17+
float32x4_t fx = vcvt_f32_f16(x);
18+
float32x4_t fy = vcvt_f32_f16(y);
19+
return vcvt_f16_f32(fmod_ps(fx, fy));
20+
}
21+
22+
static inline float16x8_t fmodq_f16(const float16x8_t& x, const float16x8_t& y)
23+
{
24+
float16x4_t xl = vget_low_f16(x);
25+
float16x4_t xh = vget_high_f16(x);
26+
float16x4_t yl = vget_low_f16(y);
27+
float16x4_t yh = vget_high_f16(y);
28+
29+
float16x4_t rl = fmod_f16(xl, yl);
30+
float16x4_t rh = fmod_f16(xh, yh);
31+
return vcombine_f16(rl, rh);
32+
}
33+
34+
static inline float16x4_t round_f16(const float16x4_t& x)
35+
{
36+
return vcvt_f16_f32(round_ps(vcvt_f32_f16(x)));
37+
}
38+
39+
static inline float16x8_t roundq_f16(const float16x8_t& x)
40+
{
41+
float16x4_t xl = vget_low_f16(x);
42+
float16x4_t xh = vget_high_f16(x);
43+
float16x4_t rl = round_f16(xl);
44+
float16x4_t rh = round_f16(xh);
45+
return vcombine_f16(rl, rh);
46+
}
47+
48+
static inline float16x4_t logaddexp_f16(const float16x4_t& x, const float16x4_t& y)
49+
{
50+
return vcvt_f16_f32(logaddexp_ps(vcvt_f32_f16(x), vcvt_f32_f16(y)));
51+
}
52+
53+
static inline float16x8_t logaddexpq_f16(const float16x8_t& x, const float16x8_t& y)
54+
{
55+
float16x4_t xl = vget_low_f16(x);
56+
float16x4_t xh = vget_high_f16(x);
57+
float16x4_t yl = vget_low_f16(y);
58+
float16x4_t yh = vget_high_f16(y);
59+
float16x4_t rl = logaddexp_f16(xl, yl);
60+
float16x4_t rh = logaddexp_f16(xh, yh);
61+
return vcombine_f16(rl, rh);
62+
}
63+
64+
static inline float16x4_t floor_divide_f16(const float16x4_t& x, const float16x4_t& y)
65+
{
66+
return vcvt_f16_f32(floor_divide_ps(vcvt_f32_f16(x), vcvt_f32_f16(y)));
67+
}
68+
69+
static inline float16x8_t floor_divideq_f16(const float16x8_t& x, const float16x8_t& y)
70+
{
71+
float16x4_t xl = vget_low_f16(x);
72+
float16x4_t xh = vget_high_f16(x);
73+
float16x4_t yl = vget_low_f16(y);
74+
float16x4_t yh = vget_high_f16(y);
75+
float16x4_t rl = floor_divide_f16(xl, yl);
76+
float16x4_t rh = floor_divide_f16(xh, yh);
77+
return vcombine_f16(rl, rh);
78+
}
79+
80+
static inline float16x4_t remainder_f16(const float16x4_t& x, const float16x4_t& y)
81+
{
82+
return vcvt_f16_f32(remainder_ps(vcvt_f32_f16(x), vcvt_f32_f16(y)));
83+
}
84+
85+
static inline float16x8_t remainderq_f16(const float16x8_t& x, const float16x8_t& y)
86+
{
87+
float16x4_t xl = vget_low_f16(x);
88+
float16x4_t xh = vget_high_f16(x);
89+
float16x4_t yl = vget_low_f16(y);
90+
float16x4_t yh = vget_high_f16(y);
91+
float16x4_t rl = remainder_f16(xl, yl);
92+
float16x4_t rh = remainder_f16(xh, yh);
93+
return vcombine_f16(rl, rh);
94+
}
95+
1596
template<typename Op>
1697
static void binary_op_vector_no_broadcast_fp16s(const __fp16* ptr, const __fp16* ptr1, __fp16* outptr, int size)
1798
{
@@ -318,6 +399,13 @@ MAKE_FUNCTION(binary_op_rdiv_fp16s, y / x, vdiv_f16(y, x), vdivq_f16(y, x))
318399
MAKE_FUNCTION(binary_op_rpow_fp16s, (__fp16)powf(y, x), vcvt_f16_f32(pow_ps(vcvt_f32_f16(y), vcvt_f32_f16(x))), vcombine_f16(vcvt_f16_f32(pow_ps(vcvt_f32_f16(vget_low_f16(y)), vcvt_f32_f16(vget_low_f16(x)))), vcvt_f16_f32(pow_ps(vcvt_f32_f16(vget_high_f16(y)), vcvt_f32_f16(vget_high_f16(x))))))
319400
MAKE_FUNCTION(binary_op_atan2_fp16s, (__fp16)atan2f(x, y), vcvt_f16_f32(atan2_ps(vcvt_f32_f16(x), vcvt_f32_f16(y))), vcombine_f16(vcvt_f16_f32(atan2_ps(vcvt_f32_f16(vget_low_f16(x)), vcvt_f32_f16(vget_low_f16(y)))), vcvt_f16_f32(atan2_ps(vcvt_f32_f16(vget_high_f16(x)), vcvt_f32_f16(vget_high_f16(y))))))
320401
MAKE_FUNCTION(binary_op_ratan2_fp16s, (__fp16)atan2f(y, x), vcvt_f16_f32(atan2_ps(vcvt_f32_f16(y), vcvt_f32_f16(x))), vcombine_f16(vcvt_f16_f32(atan2_ps(vcvt_f32_f16(vget_low_f16(y)), vcvt_f32_f16(vget_low_f16(x)))), vcvt_f16_f32(atan2_ps(vcvt_f32_f16(vget_high_f16(y)), vcvt_f32_f16(vget_high_f16(x))))))
402+
MAKE_FUNCTION(binary_op_fmod_fp16s, (__fp16)fmodf((float)x, (float)y), fmod_f16(x, y), fmodq_f16(x, y))
403+
MAKE_FUNCTION(binary_op_rfmod_fp16s, (__fp16)fmodf((float)y, (float)x), fmod_f16(y, x), fmodq_f16(y, x))
404+
MAKE_FUNCTION(binary_op_logaddexp_fp16s, (__fp16)(std::max((float)x, (float)y) + log1pf(expf(std::min((float)x, (float)y) - std::max((float)x, (float)y)))), logaddexp_f16(x, y), logaddexpq_f16(x, y))
405+
MAKE_FUNCTION(binary_op_floor_divide_fp16s, (__fp16)floorf((float)x / (float)y), floor_divide_f16(x, y), floor_divideq_f16(x, y))
406+
MAKE_FUNCTION(binary_op_rfloor_divide_fp16s, (__fp16)floorf((float)y / (float)x), floor_divide_f16(y, x), floor_divideq_f16(y, x))
407+
MAKE_FUNCTION(binary_op_remainder_fp16s, (__fp16)remainderf((float)x, (float)y), remainder_f16(x, y), remainderq_f16(x, y))
408+
MAKE_FUNCTION(binary_op_rremainder_fp16s, (__fp16)remainderf((float)y, (float)x), remainder_f16(y, x), remainderq_f16(y, x))
321409
// *INDENT-ON*
322410
// clang-format on
323411

@@ -341,6 +429,13 @@ static void binary_op_vector_fp16s(const __fp16* ptr, const __fp16* ptr1, __fp16
341429
if (op_type == BinaryOp::Operation_RPOW) return binary_op_vector_fp16s<binary_op_rpow_fp16s>(ptr, ptr1, outptr, aw, bw, ap, bp);
342430
if (op_type == BinaryOp::Operation_ATAN2) return binary_op_vector_fp16s<binary_op_atan2_fp16s>(ptr, ptr1, outptr, aw, bw, ap, bp);
343431
if (op_type == BinaryOp::Operation_RATAN2) return binary_op_vector_fp16s<binary_op_ratan2_fp16s>(ptr, ptr1, outptr, aw, bw, ap, bp);
432+
if (op_type == BinaryOp::Operation_FMOD) return binary_op_vector_fp16s<binary_op_fmod_fp16s>(ptr, ptr1, outptr, aw, bw, ap, bp);
433+
if (op_type == BinaryOp::Operation_RFMOD) return binary_op_vector_fp16s<binary_op_rfmod_fp16s>(ptr, ptr1, outptr, aw, bw, ap, bp);
434+
if (op_type == BinaryOp::Operation_LOGADDEXP) return binary_op_vector_fp16s<binary_op_logaddexp_fp16s>(ptr, ptr1, outptr, aw, bw, ap, bp);
435+
if (op_type == BinaryOp::Operation_FLOOR_DIVIDE) return binary_op_vector_fp16s<binary_op_floor_divide_fp16s>(ptr, ptr1, outptr, aw, bw, ap, bp);
436+
if (op_type == BinaryOp::Operation_RFLOOR_DIVIDE) return binary_op_vector_fp16s<binary_op_rfloor_divide_fp16s>(ptr, ptr1, outptr, aw, bw, ap, bp);
437+
if (op_type == BinaryOp::Operation_REMAINDER) return binary_op_vector_fp16s<binary_op_remainder_fp16s>(ptr, ptr1, outptr, aw, bw, ap, bp);
438+
if (op_type == BinaryOp::Operation_RREMAINDER) return binary_op_vector_fp16s<binary_op_rremainder_fp16s>(ptr, ptr1, outptr, aw, bw, ap, bp);
344439

345440
// should never reach here
346441
}
@@ -485,10 +580,18 @@ static int get_reverse_op_type(int op_type)
485580
if (op_type == BinaryOp::Operation_DIV) return BinaryOp::Operation_RDIV;
486581
if (op_type == BinaryOp::Operation_POW) return BinaryOp::Operation_RPOW;
487582
if (op_type == BinaryOp::Operation_ATAN2) return BinaryOp::Operation_RATAN2;
583+
if (op_type == BinaryOp::Operation_FMOD) return BinaryOp::Operation_RFMOD;
584+
if (op_type == BinaryOp::Operation_FLOOR_DIVIDE) return BinaryOp::Operation_RFLOOR_DIVIDE;
585+
if (op_type == BinaryOp::Operation_REMAINDER) return BinaryOp::Operation_RREMAINDER;
586+
488587
if (op_type == BinaryOp::Operation_RSUB) return BinaryOp::Operation_SUB;
489588
if (op_type == BinaryOp::Operation_RDIV) return BinaryOp::Operation_DIV;
490589
if (op_type == BinaryOp::Operation_RPOW) return BinaryOp::Operation_POW;
491590
if (op_type == BinaryOp::Operation_RATAN2) return BinaryOp::Operation_ATAN2;
591+
if (op_type == BinaryOp::Operation_RFMOD) return BinaryOp::Operation_FMOD;
592+
if (op_type == BinaryOp::Operation_RFLOOR_DIVIDE) return BinaryOp::Operation_FLOOR_DIVIDE;
593+
if (op_type == BinaryOp::Operation_RREMAINDER) return BinaryOp::Operation_REMAINDER;
594+
492595
return op_type;
493596
}
494597

src/layer/arm/neon_mathfun.h

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,95 @@ static inline float32x4_t atan2_ps(float32x4_t a, float32x4_t b)
404404
return vld1q_f32(tmpx);
405405
}
406406

407+
static inline float32x4_t trunc_ps(const float32x4_t& x)
408+
{
409+
// truncate toward zero
410+
#if __aarch64__
411+
return vrndq_f32(x);
412+
#else
413+
int32x4_t xi = vcvtq_s32_f32(x);
414+
return vcvtq_f32_s32(xi);
415+
#endif
416+
}
417+
418+
static inline float32x4_t fmod_ps(const float32x4_t& x, const float32x4_t& y)
419+
{
420+
// fmod(x,y) = x - trunc(x/y) * y
421+
#if __aarch64__
422+
float32x4_t q = vdivq_f32(x, y);
423+
#else
424+
float32x4_t q = div_ps(x, y);
425+
#endif
426+
float32x4_t tq = trunc_ps(q);
427+
return vsubq_f32(x, vmulq_f32(tq, y));
428+
}
429+
430+
static inline float32x4_t round_ps(const float32x4_t& x)
431+
{
432+
#if __aarch64__
433+
return vrndnq_f32(x);
434+
#else
435+
float32x4_t half = vdupq_n_f32(0.5f);
436+
float32x4_t one = vdupq_n_f32(1.0f);
437+
uint32x4_t sign_mask = vcltq_f32(x, vdupq_n_f32(0));
438+
float32x4_t abs_x = vabsq_f32(x);
439+
int32x4_t xi = vcvtq_s32_f32(abs_x);
440+
float32x4_t truncated = vcvtq_f32_s32(xi);
441+
float32x4_t diff = vsubq_f32(abs_x, truncated);
442+
uint32x4_t diff_gt_half = vcgtq_f32(diff, half);
443+
uint32x4_t diff_eq_half = vceqq_f32(diff, half);
444+
int32x4_t xi_and_1 = vandq_s32(xi, vdupq_n_s32(1));
445+
uint32x4_t is_odd = vcgtq_s32(xi_and_1, vdupq_n_s32(0));
446+
uint32x4_t round_up = vorrq_u32(diff_gt_half, vandq_u32(diff_eq_half, is_odd));
447+
float32x4_t rounded = vaddq_f32(truncated, vreinterpretq_f32_u32(vandq_u32(round_up, vreinterpretq_u32_f32(one))));
448+
return vbslq_f32(sign_mask, vnegq_f32(rounded), rounded);
449+
#endif
450+
}
451+
452+
static inline float32x4_t logaddexp_ps(const float32x4_t& x, const float32x4_t& y)
453+
{
454+
float32x4_t max_xy = vmaxq_f32(x, y);
455+
float32x4_t min_xy = vminq_f32(x, y);
456+
float32x4_t diff = vsubq_f32(min_xy, max_xy);
457+
float32x4_t exp_diff = exp_ps(diff);
458+
float32x4_t one_plus_exp = vaddq_f32(vdupq_n_f32(1.0f), exp_diff);
459+
float32x4_t log_result = log_ps(one_plus_exp);
460+
return vaddq_f32(max_xy, log_result);
461+
}
462+
463+
static inline float32x4_t floor_ps(const float32x4_t& x)
464+
{
465+
#if __aarch64__
466+
return vrndmq_f32(x);
467+
#else
468+
float32x4_t truncated = vcvtq_f32_s32(vcvtq_s32_f32(x));
469+
uint32x4_t need_adjust = vcltq_f32(x, truncated);
470+
float32x4_t adjusted = vsubq_f32(truncated, vdupq_n_f32(1.0f));
471+
return vbslq_f32(need_adjust, adjusted, truncated);
472+
#endif
473+
}
474+
475+
static inline float32x4_t floor_divide_ps(const float32x4_t& x, const float32x4_t& y)
476+
{
477+
#if __aarch64__
478+
float32x4_t q = vdivq_f32(x, y);
479+
#else
480+
float32x4_t q = div_ps(x, y);
481+
#endif
482+
return floor_ps(q);
483+
}
484+
485+
static inline float32x4_t remainder_ps(const float32x4_t& x, const float32x4_t& y)
486+
{
487+
#if __aarch64__
488+
float32x4_t q = vdivq_f32(x, y);
489+
#else
490+
float32x4_t q = div_ps(x, y);
491+
#endif
492+
float32x4_t rq = round_ps(q);
493+
return vsubq_f32(x, vmulq_f32(rq, y));
494+
}
495+
407496
#include "neon_mathfun_tanh.h"
408497

409498
// Clean up macros

0 commit comments

Comments
 (0)