quakeforge/include/QF/simd/vec2f.h
Bill Currie 9084121ad2 [simd] Correct result for dot2f
It turns out gcc optimizes the obvious code nicely. It doesn't do so
well for cmul, but I decided to use obvious code anyway (the instruction
counts were the same, so maybe it doesn't get better for a single pair
of operands).
2022-01-03 23:27:01 +09:00

161 lines
3.3 KiB
C

/*
QF/simd/vec2f.h
Vector functions for vec2f_t (ie, float precision)
Copyright (C) 2020 Bill Currie <bill@taniwha.org>
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifndef __QF_simd_vec2f_h
#define __QF_simd_vec2f_h
#include <immintrin.h>
#include <math.h>
#include "QF/simd/types.h"
GNU89INLINE inline vec2f_t vabs2f (vec2f_t v) __attribute__((const));
GNU89INLINE inline vec2f_t vsqrt2f (vec2f_t v) __attribute__((const));
GNU89INLINE inline vec2f_t vceil2f (vec2f_t v) __attribute__((const));
GNU89INLINE inline vec2f_t vfloor2f (vec2f_t v) __attribute__((const));
GNU89INLINE inline vec2f_t vtrunc2f (vec2f_t v) __attribute__((const));
/** 2D vector dot product.
*/
GNU89INLINE inline vec2f_t dot2f (vec2f_t a, vec2f_t b) __attribute__((const));
GNU89INLINE inline vec2f_t cmulf (vec2f_t a, vec2f_t b) __attribute__((const));
GNU89INLINE inline vec2f_t normal2f (vec2f_t v) __attribute__((pure));
GNU89INLINE inline vec2f_t magnitude2f (vec2f_t v) __attribute__((pure));
#ifndef IMPLEMENT_VEC2F_Funcs
GNU89INLINE inline
#else
VISIBLE
#endif
vec2f_t
vabs2f (vec2f_t v)
{
const uint32_t nan = ~0u >> 1;
const vec2i_t abs = { nan, nan };
return (vec2f_t) ((vec2i_t) v & abs);
}
#ifndef IMPLEMENT_VEC2F_Funcs
GNU89INLINE inline
#else
VISIBLE
#endif
vec2f_t
vsqrt2f (vec2f_t v)
{
vec4f_t t = { v[0], v[1], 0, 0 };
t = _mm_sqrt_ps (t);
return (vec2f_t) { t[0], t[1] };
}
#ifndef IMPLEMENT_VEC2F_Funcs
GNU89INLINE inline
#else
VISIBLE
#endif
vec2f_t
vceil2f (vec2f_t v)
{
vec4f_t t = { v[0], v[1], 0, 0 };
t = _mm_ceil_ps (t);
return (vec2f_t) { t[0], t[1] };
}
#ifndef IMPLEMENT_VEC2F_Funcs
GNU89INLINE inline
#else
VISIBLE
#endif
vec2f_t
vfloor2f (vec2f_t v)
{
vec4f_t t = { v[0], v[1], 0, 0 };
t = _mm_floor_ps (t);
return (vec2f_t) { t[0], t[1] };
}
#ifndef IMPLEMENT_VEC2F_Funcs
GNU89INLINE inline
#else
VISIBLE
#endif
vec2f_t
vtrunc2f (vec2f_t v)
{
vec4f_t t = { v[0], v[1], 0, 0 };
t = _mm_round_ps (t, _MM_FROUND_TRUNC);
return (vec2f_t) { t[0], t[1] };
}
#ifndef IMPLEMENT_VEC2F_Funcs
GNU89INLINE inline
#else
VISIBLE
#endif
vec2f_t
dot2f (vec2f_t a, vec2f_t b)
{
vec2f_t c = a * b;
return (vec2f_t) { c[0] + c[1], c[0] + c[1] };
}
#ifndef IMPLEMENT_VEC2F_Funcs
GNU89INLINE inline
#else
VISIBLE
#endif
vec2f_t
cmulf (vec2f_t a, vec2f_t b)
{
vec2f_t c1 = a * b[0];
vec2f_t c2 = a * b[1];
return (vec2f_t) { c1[0] - c2[1], c1[1] + c2[0] };
}
#ifndef IMPLEMENT_VEC2F_Funcs
GNU89INLINE inline
#else
VISIBLE
#endif
vec2f_t
normal2f (vec2f_t v)
{
return v / vsqrt2f (dot2f (v, v));
}
#ifndef IMPLEMENT_VEC2F_Funcs
GNU89INLINE inline
#else
VISIBLE
#endif
vec2f_t
magnitude2f (vec2f_t v)
{
return vsqrt2f (dot2f (v, v));
}
#endif//__QF_simd_vec2f_h