123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- /**
- * @file llsimdtypes.h
- * @brief Declaration of basic SIMD math related types
- *
- * $LicenseInfo:firstyear=2010&license=viewergpl$
- *
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #ifndef LL_SIMD_TYPES_H
- #define LL_SIMD_TYPES_H
- #if LL_DEBUG
- # include "llmemory.h" // For ll_assert_aligned()
- #endif
- typedef __m128 LLQuad;
- #if LL_WINDOWS
- # pragma warning(push)
- // Disable warning about casting int to bool for this class.
- # pragma warning( disable : 4800 3 )
- #endif // LL_WINDOWS
- class LLBool32
- {
- public:
- LL_INLINE LLBool32()
- {
- }
- LL_INLINE LLBool32(int rhs)
- : mBool(rhs)
- {
- }
- LL_INLINE LLBool32(unsigned int rhs)
- : mBool(rhs)
- {
- }
- LL_INLINE LLBool32(bool rhs)
- : mBool((int)rhs)
- {
- }
- LL_INLINE LLBool32& operator=(bool rhs)
- {
- mBool = (int)rhs;
- return *this;
- }
- LL_INLINE bool operator==(bool rhs) const
- {
- return (const bool&)mBool == rhs;
- }
- LL_INLINE bool operator!=(bool rhs) const
- {
- return (const bool&)mBool != rhs;
- }
- LL_INLINE operator bool() const
- {
- return (const bool&)mBool;
- }
- private:
- int mBool;
- };
- #if LL_WINDOWS
- # pragma warning(pop)
- #endif
- class alignas(16) LLSimdScalar
- {
- public:
- LL_INLINE LLSimdScalar() noexcept
- {
- }
- LL_INLINE LLSimdScalar(LLQuad q) noexcept
- {
- mQ = q;
- }
- LL_INLINE LLSimdScalar(F32 f) noexcept
- {
- mQ = _mm_set_ss(f);
- }
- LL_INLINE F32 getF32() const
- {
- F32 ret;
- _mm_store_ss(&ret, mQ);
- return ret;
- }
- LL_INLINE LLSimdScalar getAbs() const
- {
- alignas(16) thread_local const U32 F_ABS_MASK_4A[4] = {
- 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF
- };
- #if LL_DEBUG
- ll_assert_aligned(F_ABS_MASK_4A, 16);
- #endif
- return _mm_and_ps(mQ, *reinterpret_cast<const LLQuad*>(F_ABS_MASK_4A));
- }
- LL_INLINE void setMax(const LLSimdScalar& a, const LLSimdScalar& b)
- {
- mQ = _mm_max_ss(a, b);
- }
- LL_INLINE void setMin(const LLSimdScalar& a, const LLSimdScalar& b)
- {
- mQ = _mm_min_ss(a, b);
- }
- LL_INLINE LLSimdScalar& operator=(F32 rhs)
- {
- mQ = _mm_set_ss(rhs);
- return *this;
- }
- LL_INLINE LLSimdScalar& operator+=(const LLSimdScalar& rhs)
- {
- mQ = _mm_add_ss(mQ, rhs);
- return *this;
- }
- LL_INLINE LLSimdScalar& operator-=(const LLSimdScalar& rhs)
- {
- mQ = _mm_sub_ss(mQ, rhs);
- return *this;
- }
- LL_INLINE LLSimdScalar& operator*=(const LLSimdScalar& rhs)
- {
- mQ = _mm_mul_ss(mQ, rhs);
- return *this;
- }
- LL_INLINE LLSimdScalar& operator/=(const LLSimdScalar& rhs)
- {
- mQ = _mm_div_ss(mQ, rhs);
- return *this;
- }
- LL_INLINE operator LLQuad() const
- {
- return mQ;
- }
- LL_INLINE const LLQuad& getQuad() const
- {
- return mQ;
- }
- LL_INLINE LLBool32 isApproximatelyEqual(const LLSimdScalar& rhs,
- F32 tolerance = F_APPROXIMATELY_ZERO) const
- {
- const LLSimdScalar tol(tolerance);
- const LLSimdScalar diff = _mm_sub_ss(mQ, rhs.mQ);
- const LLSimdScalar abs_diff = diff.getAbs();
- return _mm_comile_ss(abs_diff, tol); // return abs_diff <= tol;
- }
- static LL_INLINE const LLSimdScalar& getZero()
- {
- extern const LLQuad F_ZERO_4A;
- return reinterpret_cast<const LLSimdScalar&>(F_ZERO_4A);
- }
- private:
- LLQuad mQ;
- };
- LL_INLINE LLSimdScalar operator+(const LLSimdScalar& a, const LLSimdScalar& b)
- {
- LLSimdScalar t(a);
- t += b;
- return t;
- }
- LL_INLINE LLSimdScalar operator-(const LLSimdScalar& a, const LLSimdScalar& b)
- {
- LLSimdScalar t(a);
- t -= b;
- return t;
- }
- LL_INLINE LLSimdScalar operator*(const LLSimdScalar& a, const LLSimdScalar& b)
- {
- LLSimdScalar t(a);
- t *= b;
- return t;
- }
- LL_INLINE LLSimdScalar operator/(const LLSimdScalar& a, const LLSimdScalar& b)
- {
- LLSimdScalar t(a);
- t /= b;
- return t;
- }
- LL_INLINE LLSimdScalar operator-(const LLSimdScalar& a)
- {
- alignas(16) thread_local const U32 signMask[4] = {
- 0x80000000, 0x80000000, 0x80000000, 0x80000000
- };
- #if LL_DEBUG
- ll_assert_aligned(signMask, 16);
- #endif
- return _mm_xor_ps(*reinterpret_cast<const LLQuad*>(signMask), a);
- }
- LL_INLINE LLBool32 operator==(const LLSimdScalar& a, const LLSimdScalar& b)
- {
- return _mm_comieq_ss(a, b);
- }
- LL_INLINE LLBool32 operator!=(const LLSimdScalar& a, const LLSimdScalar& b)
- {
- return _mm_comineq_ss(a, b);
- }
- LL_INLINE LLBool32 operator<(const LLSimdScalar& a, const LLSimdScalar& b)
- {
- return _mm_comilt_ss(a, b);
- }
- LL_INLINE LLBool32 operator<=(const LLSimdScalar& a, const LLSimdScalar& b)
- {
- return _mm_comile_ss(a, b);
- }
- LL_INLINE LLBool32 operator>(const LLSimdScalar& a, const LLSimdScalar& b)
- {
- return _mm_comigt_ss(a, b);
- }
- LL_INLINE LLBool32 operator>=(const LLSimdScalar& a, const LLSimdScalar& b)
- {
- return _mm_comige_ss(a, b);
- }
- #endif //LL_SIMD_TYPES_H
|