vec: some useful functions (#103)

These functions are added:
- abs(): absolute value
- fract(): fractional part
- norm_one(): L1 norm
- norm_inf(): infinity norm
- hadd(): horizontal add
- hmax(): horizontal max
This commit is contained in:
Luigi Castelli
2019-08-31 23:30:15 +02:00
committed by Recep Aslantas
parent 6af1f5af04
commit 27cc9c3351
14 changed files with 552 additions and 0 deletions

View File

@@ -13,6 +13,12 @@
#define glmm_load(p) vld1q_f32(p)
#define glmm_store(p, a) vst1q_f32(p, a)
static inline
float32x4_t
glmm_abs(float32x4_t v) {
return vabsq_f32(v);
}
static inline
float
glmm_hadd(float32x4_t v) {
@@ -25,6 +31,22 @@ glmm_hadd(float32x4_t v) {
#endif
}
static inline
float
glmm_hmin(float32x4_t v) {
v = vpmin_f32(vget_low_f32(v), vget_high_f32(v));
v = vpmin_f32(v, v);
return vget_lane_f32(v, 0);
}
static inline
float
glmm_hmax(float32x4_t v) {
v = vpmax_f32(vget_low_f32(v), vget_high_f32(v));
v = vpmax_f32(v, v);
return vget_lane_f32(v, 0);
}
static inline
float
glmm_dot(float32x4_t a, float32x4_t b) {
@@ -43,5 +65,17 @@ glmm_norm2(float32x4_t a) {
return glmm_dot(a, a);
}
static inline
float
glmm_norm_one(float32x4_t a) {
return glmm_hadd(glmm_abs(a));
}
static inline
float
glmm_norm_inf(float32x4_t a) {
return glmm_hmax(glmm_abs(a));
}
#endif
#endif /* cglm_simd_arm_h */

View File

@@ -42,6 +42,12 @@
# endif
#endif
static inline
__m128
glmm_abs(__m128 x) {
return _mm_andnot_ps(_mm_set1_ps(-0.0f), x);
}
static inline
__m128
glmm_vhadds(__m128 v) {
@@ -68,6 +74,38 @@ glmm_hadd(__m128 v) {
return _mm_cvtss_f32(glmm_vhadds(v));
}
static inline
__m128
glmm_vhmin(__m128 v) {
__m128 x0, x1, x2;
x0 = _mm_movehl_ps(v, v); /* [2, 3, 2, 3] */
x1 = _mm_min_ps(x0, v); /* [0|2, 1|3, 2|2, 3|3] */
x2 = glmm_shuff1x(x1, 1); /* [1|3, 1|3, 1|3, 1|3] */
return _mm_min_ss(x1, x2);
}
static inline
float
glmm_hmin(__m128 v) {
return _mm_cvtss_f32(glmm_vhmin(v));
}
static inline
__m128
glmm_vhmax(__m128 v) {
__m128 x0, x1, x2;
x0 = _mm_movehl_ps(v, v); /* [2, 3, 2, 3] */
x1 = _mm_max_ps(x0, v); /* [0|2, 1|3, 2|2, 3|3] */
x2 = glmm_shuff1x(x1, 1); /* [1|3, 1|3, 1|3, 1|3] */
return _mm_max_ss(x1, x2);
}
static inline
float
glmm_hmax(__m128 v) {
return _mm_cvtss_f32(glmm_vhmax(v));
}
static inline
__m128
glmm_vdots(__m128 a, __m128 b) {
@@ -119,6 +157,18 @@ glmm_norm2(__m128 a) {
return _mm_cvtss_f32(glmm_vhadds(_mm_mul_ps(a, a)));
}
static inline
float
glmm_norm_one(__m128 a) {
return _mm_cvtss_f32(glmm_vhadds(glmm_abs(a)));
}
static inline
float
glmm_norm_inf(__m128 a) {
return _mm_cvtss_f32(glmm_vhmax(glmm_abs(a)));
}
static inline
__m128
glmm_load3(float v[3]) {