123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803 |
- /*
- ===========================================================================
- Doom 3 BFG Edition GPL Source Code
- Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
- Doom 3 BFG Edition Source Code 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 3 of the License, or
- (at your option) any later version.
- Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- #ifndef __MATH_VECX_H__
- #define __MATH_VECX_H__
- /*
- ===============================================================================
- idVecX - arbitrary sized vector
- The vector lives on 16 byte aligned and 16 byte padded memory.
- NOTE: due to the temporary memory pool idVecX cannot be used by multiple threads
- ===============================================================================
- */
- #define VECX_MAX_TEMP 1024
- #define VECX_QUAD( x ) ( ( ( ( x ) + 3 ) & ~3 ) * sizeof( float ) )
- #define VECX_CLEAREND() int s = size; while( s < ( ( s + 3) & ~3 ) ) { p[s++] = 0.0f; }
- #define VECX_ALLOCA( n ) ( (float *) _alloca16( VECX_QUAD( n ) ) )
- #define VECX_SIMD
- class idVecX {
- friend class idMatX;
- public:
- ID_INLINE idVecX();
- ID_INLINE explicit idVecX( int length );
- ID_INLINE explicit idVecX( int length, float *data );
- ID_INLINE ~idVecX();
- ID_INLINE float Get( int index ) const;
- ID_INLINE float & Get( int index );
- ID_INLINE float operator[]( const int index ) const;
- ID_INLINE float & operator[]( const int index );
- ID_INLINE idVecX operator-() const;
- ID_INLINE idVecX & operator=( const idVecX &a );
- ID_INLINE idVecX operator*( const float a ) const;
- ID_INLINE idVecX operator/( const float a ) const;
- ID_INLINE float operator*( const idVecX &a ) const;
- ID_INLINE idVecX operator-( const idVecX &a ) const;
- ID_INLINE idVecX operator+( const idVecX &a ) const;
- ID_INLINE idVecX & operator*=( const float a );
- ID_INLINE idVecX & operator/=( const float a );
- ID_INLINE idVecX & operator+=( const idVecX &a );
- ID_INLINE idVecX & operator-=( const idVecX &a );
- friend ID_INLINE idVecX operator*( const float a, const idVecX &b );
- ID_INLINE bool Compare( const idVecX &a ) const; // exact compare, no epsilon
- ID_INLINE bool Compare( const idVecX &a, const float epsilon ) const; // compare with epsilon
- ID_INLINE bool operator==( const idVecX &a ) const; // exact compare, no epsilon
- ID_INLINE bool operator!=( const idVecX &a ) const; // exact compare, no epsilon
- ID_INLINE void SetSize( int size );
- ID_INLINE void ChangeSize( int size, bool makeZero = false );
- ID_INLINE int GetSize() const { return size; }
- ID_INLINE void SetData( int length, float *data );
- ID_INLINE void Zero();
- ID_INLINE void Zero( int length );
- ID_INLINE void Random( int seed, float l = 0.0f, float u = 1.0f );
- ID_INLINE void Random( int length, int seed, float l = 0.0f, float u = 1.0f );
- ID_INLINE void Negate();
- ID_INLINE void Clamp( float min, float max );
- ID_INLINE idVecX & SwapElements( int e1, int e2 );
- ID_INLINE float Length() const;
- ID_INLINE float LengthSqr() const;
- ID_INLINE idVecX Normalize() const;
- ID_INLINE float NormalizeSelf();
- ID_INLINE int GetDimension() const;
- ID_INLINE void AddScaleAdd( const float scale, const idVecX & v0, const idVecX & v1 );
- ID_INLINE const idVec3 & SubVec3( int index ) const;
- ID_INLINE idVec3 & SubVec3( int index );
- ID_INLINE const idVec6 & SubVec6( int index = 0 ) const;
- ID_INLINE idVec6 & SubVec6( int index = 0 );
- ID_INLINE const float * ToFloatPtr() const;
- ID_INLINE float * ToFloatPtr();
- const char * ToString( int precision = 2 ) const;
- private:
- int size; // size of the vector
- int alloced; // if -1 p points to data set with SetData
- float * p; // memory the vector is stored
- static float temp[VECX_MAX_TEMP+4]; // used to store intermediate results
- static float * tempPtr; // pointer to 16 byte aligned temporary memory
- static int tempIndex; // index into memory pool, wraps around
- ID_INLINE void SetTempSize( int size );
- };
- /*
- ========================
- idVecX::idVecX
- ========================
- */
- ID_INLINE idVecX::idVecX() {
- size = alloced = 0;
- p = NULL;
- }
- /*
- ========================
- idVecX::idVecX
- ========================
- */
- ID_INLINE idVecX::idVecX( int length ) {
- size = alloced = 0;
- p = NULL;
- SetSize( length );
- }
- /*
- ========================
- idVecX::idVecX
- ========================
- */
- ID_INLINE idVecX::idVecX( int length, float *data ) {
- size = alloced = 0;
- p = NULL;
- SetData( length, data );
- }
- /*
- ========================
- idVecX::~idVecX
- ========================
- */
- ID_INLINE idVecX::~idVecX() {
- // if not temp memory
- if ( p && ( p < idVecX::tempPtr || p >= idVecX::tempPtr + VECX_MAX_TEMP ) && alloced != -1 ) {
- Mem_Free16( p );
- }
- }
- /*
- ========================
- idVecX::Get
- ========================
- */
- ID_INLINE float idVecX::Get( int index ) const {
- assert( index >= 0 && index < size );
- return p[index];
- }
- /*
- ========================
- idVecX::Get
- ========================
- */
- ID_INLINE float & idVecX::Get( int index ) {
- assert( index >= 0 && index < size );
- return p[index];
- }
- /*
- ========================
- idVecX::operator[]
- ========================
- */
- ID_INLINE float idVecX::operator[]( int index ) const {
- return Get( index );
- }
- /*
- ========================
- idVecX::operator[]
- ========================
- */
- ID_INLINE float & idVecX::operator[]( int index ) {
- return Get( index );
- }
- /*
- ========================
- idVecX::operator-
- ========================
- */
- ID_INLINE idVecX idVecX::operator-() const {
- idVecX m;
- m.SetTempSize( size );
- #if defined(ID_WIN_X86_SSE_INTRIN) && defined(VECX_SIMD)
- ALIGN16( unsigned int signBit[4] ) = { IEEE_FLT_SIGN_MASK, IEEE_FLT_SIGN_MASK, IEEE_FLT_SIGN_MASK, IEEE_FLT_SIGN_MASK };
- for ( int i = 0; i < size; i += 4 ) {
- _mm_store_ps( m.p + i, _mm_xor_ps( _mm_load_ps( p + i ), (__m128 &) signBit[0] ) );
- }
- #else
- for ( int i = 0; i < size; i++ ) {
- m.p[i] = -p[i];
- }
- #endif
- return m;
- }
- /*
- ========================
- idVecX::operator=
- ========================
- */
- ID_INLINE idVecX &idVecX::operator=( const idVecX &a ) {
- SetSize( a.size );
- #if defined(ID_WIN_X86_SSE_INTRIN) && defined(VECX_SIMD)
- for ( int i = 0; i < a.size; i += 4 ) {
- _mm_store_ps( p + i, _mm_load_ps( a.p + i ) );
- }
- #else
- memcpy( p, a.p, a.size * sizeof( float ) );
- #endif
- idVecX::tempIndex = 0;
- return *this;
- }
- /*
- ========================
- idVecX::operator+
- ========================
- */
- ID_INLINE idVecX idVecX::operator+( const idVecX &a ) const {
- idVecX m;
- assert( size == a.size );
- m.SetTempSize( size );
- #if defined(ID_WIN_X86_SSE_INTRIN) && defined(VECX_SIMD)
- for ( int i = 0; i < size; i += 4 ) {
- _mm_store_ps( m.p + i, _mm_add_ps( _mm_load_ps( p + i ), _mm_load_ps( a.p + i ) ) );
- }
- #else
- for ( int i = 0; i < size; i++ ) {
- m.p[i] = p[i] + a.p[i];
- }
- #endif
- return m;
- }
- /*
- ========================
- idVecX::operator-
- ========================
- */
- ID_INLINE idVecX idVecX::operator-( const idVecX &a ) const {
- idVecX m;
- assert( size == a.size );
- m.SetTempSize( size );
- #if defined(ID_WIN_X86_SSE_INTRIN) && defined(VECX_SIMD)
- for ( int i = 0; i < size; i += 4 ) {
- _mm_store_ps( m.p + i, _mm_sub_ps( _mm_load_ps( p + i ), _mm_load_ps( a.p + i ) ) );
- }
- #else
- for ( int i = 0; i < size; i++ ) {
- m.p[i] = p[i] - a.p[i];
- }
- #endif
- return m;
- }
- /*
- ========================
- idVecX::operator+=
- ========================
- */
- ID_INLINE idVecX &idVecX::operator+=( const idVecX &a ) {
- assert( size == a.size );
- #if defined(ID_WIN_X86_SSE_INTRIN) && defined(VECX_SIMD)
- for ( int i = 0; i < size; i += 4 ) {
- _mm_store_ps( p + i, _mm_add_ps( _mm_load_ps( p + i ), _mm_load_ps( a.p + i ) ) );
- }
- #else
- for ( int i = 0; i < size; i++ ) {
- p[i] += a.p[i];
- }
- #endif
- idVecX::tempIndex = 0;
- return *this;
- }
- /*
- ========================
- idVecX::operator-=
- ========================
- */
- ID_INLINE idVecX &idVecX::operator-=( const idVecX &a ) {
- assert( size == a.size );
- #if defined(ID_WIN_X86_SSE_INTRIN) && defined(VECX_SIMD)
- for ( int i = 0; i < size; i += 4 ) {
- _mm_store_ps( p + i, _mm_sub_ps( _mm_load_ps( p + i ), _mm_load_ps( a.p + i ) ) );
- }
- #else
- for ( int i = 0; i < size; i++ ) {
- p[i] -= a.p[i];
- }
- #endif
- idVecX::tempIndex = 0;
- return *this;
- }
- /*
- ========================
- idVecX::operator*
- ========================
- */
- ID_INLINE idVecX idVecX::operator*( const float a ) const {
- idVecX m;
- m.SetTempSize( size );
- #if defined(ID_WIN_X86_SSE_INTRIN) && defined(VECX_SIMD)
- __m128 va = _mm_load1_ps( & a );
- for ( int i = 0; i < size; i += 4 ) {
- _mm_store_ps( m.p + i, _mm_mul_ps( _mm_load_ps( p + i ), va ) );
- }
- #else
- for ( int i = 0; i < size; i++ ) {
- m.p[i] = p[i] * a;
- }
- #endif
- return m;
- }
- /*
- ========================
- idVecX::operator*=
- ========================
- */
- ID_INLINE idVecX &idVecX::operator*=( const float a ) {
- #if defined(ID_WIN_X86_SSE_INTRIN) && defined(VECX_SIMD)
- __m128 va = _mm_load1_ps( & a );
- for ( int i = 0; i < size; i += 4 ) {
- _mm_store_ps( p + i, _mm_mul_ps( _mm_load_ps( p + i ), va ) );
- }
- #else
- for ( int i = 0; i < size; i++ ) {
- p[i] *= a;
- }
- #endif
- return *this;
- }
- /*
- ========================
- idVecX::operator/
- ========================
- */
- ID_INLINE idVecX idVecX::operator/( const float a ) const {
- assert( fabs( a ) > idMath::FLT_SMALLEST_NON_DENORMAL );
- return (*this) * ( 1.0f / a );
- }
- /*
- ========================
- idVecX::operator/=
- ========================
- */
- ID_INLINE idVecX &idVecX::operator/=( const float a ) {
- assert( fabs( a ) > idMath::FLT_SMALLEST_NON_DENORMAL );
- (*this) *= ( 1.0f / a );
- return *this;
- }
- /*
- ========================
- operator*
- ========================
- */
- ID_INLINE idVecX operator*( const float a, const idVecX &b ) {
- return b * a;
- }
- /*
- ========================
- idVecX::operator*
- ========================
- */
- ID_INLINE float idVecX::operator*( const idVecX &a ) const {
- assert( size == a.size );
- float sum = 0.0f;
- for ( int i = 0; i < size; i++ ) {
- sum += p[i] * a.p[i];
- }
- return sum;
- }
- /*
- ========================
- idVecX::Compare
- ========================
- */
- ID_INLINE bool idVecX::Compare( const idVecX &a ) const {
- assert( size == a.size );
- for ( int i = 0; i < size; i++ ) {
- if ( p[i] != a.p[i] ) {
- return false;
- }
- }
- return true;
- }
- /*
- ========================
- idVecX::Compare
- ========================
- */
- ID_INLINE bool idVecX::Compare( const idVecX &a, const float epsilon ) const {
- assert( size == a.size );
- for ( int i = 0; i < size; i++ ) {
- if ( idMath::Fabs( p[i] - a.p[i] ) > epsilon ) {
- return false;
- }
- }
- return true;
- }
- /*
- ========================
- idVecX::operator==
- ========================
- */
- ID_INLINE bool idVecX::operator==( const idVecX &a ) const {
- return Compare( a );
- }
- /*
- ========================
- idVecX::operator!=
- ========================
- */
- ID_INLINE bool idVecX::operator!=( const idVecX &a ) const {
- return !Compare( a );
- }
- /*
- ========================
- idVecX::SetSize
- ========================
- */
- ID_INLINE void idVecX::SetSize( int newSize ) {
- //assert( p < idVecX::tempPtr || p > idVecX::tempPtr + VECX_MAX_TEMP );
- if ( newSize != size || p == NULL ) {
- int alloc = ( newSize + 3 ) & ~3;
- if ( alloc > alloced && alloced != -1 ) {
- if ( p ) {
- Mem_Free16( p );
- }
- p = (float *) Mem_Alloc16( alloc * sizeof( float ), TAG_MATH );
- alloced = alloc;
- }
- size = newSize;
- VECX_CLEAREND();
- }
- }
- /*
- ========================
- idVecX::ChangeSize
- ========================
- */
- ID_INLINE void idVecX::ChangeSize( int newSize, bool makeZero ) {
- if ( newSize != size ) {
- int alloc = ( newSize + 3 ) & ~3;
- if ( alloc > alloced && alloced != -1 ) {
- float *oldVec = p;
- p = (float *) Mem_Alloc16( alloc * sizeof( float ), TAG_MATH );
- alloced = alloc;
- if ( oldVec ) {
- for ( int i = 0; i < size; i++ ) {
- p[i] = oldVec[i];
- }
- Mem_Free16( oldVec );
- }
- if ( makeZero ) {
- // zero any new elements
- for ( int i = size; i < newSize; i++ ) {
- p[i] = 0.0f;
- }
- }
- }
- size = newSize;
- VECX_CLEAREND();
- }
- }
- /*
- ========================
- idVecX::SetTempSize
- ========================
- */
- ID_INLINE void idVecX::SetTempSize( int newSize ) {
- size = newSize;
- alloced = ( newSize + 3 ) & ~3;
- assert( alloced < VECX_MAX_TEMP );
- if ( idVecX::tempIndex + alloced > VECX_MAX_TEMP ) {
- idVecX::tempIndex = 0;
- }
- p = idVecX::tempPtr + idVecX::tempIndex;
- idVecX::tempIndex += alloced;
- VECX_CLEAREND();
- }
- /*
- ========================
- idVecX::SetData
- ========================
- */
- ID_INLINE void idVecX::SetData( int length, float *data ) {
- if ( p != NULL && ( p < idVecX::tempPtr || p >= idVecX::tempPtr + VECX_MAX_TEMP ) && alloced != -1 ) {
- Mem_Free16( p );
- }
- assert_16_byte_aligned( data ); // data must be 16 byte aligned
- p = data;
- size = length;
- alloced = -1;
- VECX_CLEAREND();
- }
- /*
- ========================
- idVecX::Zero
- ========================
- */
- ID_INLINE void idVecX::Zero() {
- #if defined(ID_WIN_X86_SSE_INTRIN) && defined(VECX_SIMD)
- for ( int i = 0; i < size; i += 4 ) {
- _mm_store_ps( p + i, _mm_setzero_ps() );
- }
- #else
- memset( p, 0, size * sizeof( float ) );
- #endif
- }
- /*
- ========================
- idVecX::Zero
- ========================
- */
- ID_INLINE void idVecX::Zero( int length ) {
- SetSize( length );
- #if defined(ID_WIN_X86_SSE_INTRIN) && defined(VECX_SIMD)
- for ( int i = 0; i < length; i += 4 ) {
- _mm_store_ps( p + i, _mm_setzero_ps() );
- }
- #else
- memset( p, 0, length * sizeof( float ) );
- #endif
- }
- /*
- ========================
- idVecX::Random
- ========================
- */
- ID_INLINE void idVecX::Random( int seed, float l, float u ) {
- idRandom rnd( seed );
- float c = u - l;
- for ( int i = 0; i < size; i++ ) {
- p[i] = l + rnd.RandomFloat() * c;
- }
- }
- /*
- ========================
- idVecX::Random
- ========================
- */
- ID_INLINE void idVecX::Random( int length, int seed, float l, float u ) {
- idRandom rnd( seed );
- SetSize( length );
- float c = u - l;
- for ( int i = 0; i < size; i++ ) {
- p[i] = l + rnd.RandomFloat() * c;
- }
- }
- /*
- ========================
- idVecX::Negate
- ========================
- */
- ID_INLINE void idVecX::Negate() {
- #if defined(ID_WIN_X86_SSE_INTRIN) && defined(VECX_SIMD)
- ALIGN16( const unsigned int signBit[4] ) = { IEEE_FLT_SIGN_MASK, IEEE_FLT_SIGN_MASK, IEEE_FLT_SIGN_MASK, IEEE_FLT_SIGN_MASK };
- for ( int i = 0; i < size; i += 4 ) {
- _mm_store_ps( p + i, _mm_xor_ps( _mm_load_ps( p + i ), (__m128 &) signBit[0] ) );
- }
- #else
- for ( int i = 0; i < size; i++ ) {
- p[i] = -p[i];
- }
- #endif
- }
- /*
- ========================
- idVecX::Clamp
- ========================
- */
- ID_INLINE void idVecX::Clamp( float min, float max ) {
- for ( int i = 0; i < size; i++ ) {
- if ( p[i] < min ) {
- p[i] = min;
- } else if ( p[i] > max ) {
- p[i] = max;
- }
- }
- }
- /*
- ========================
- idVecX::SwapElements
- ========================
- */
- ID_INLINE idVecX &idVecX::SwapElements( int e1, int e2 ) {
- float tmp;
- tmp = p[e1];
- p[e1] = p[e2];
- p[e2] = tmp;
- return *this;
- }
- /*
- ========================
- idVecX::Length
- ========================
- */
- ID_INLINE float idVecX::Length() const {
- float sum = 0.0f;
- for ( int i = 0; i < size; i++ ) {
- sum += p[i] * p[i];
- }
- return idMath::Sqrt( sum );
- }
- /*
- ========================
- idVecX::LengthSqr
- ========================
- */
- ID_INLINE float idVecX::LengthSqr() const {
- float sum = 0.0f;
- for ( int i = 0; i < size; i++ ) {
- sum += p[i] * p[i];
- }
- return sum;
- }
- /*
- ========================
- idVecX::Normalize
- ========================
- */
- ID_INLINE idVecX idVecX::Normalize() const {
- idVecX m;
- m.SetTempSize( size );
- float sum = 0.0f;
- for ( int i = 0; i < size; i++ ) {
- sum += p[i] * p[i];
- }
- float invSqrt = idMath::InvSqrt( sum );
- for ( int i = 0; i < size; i++ ) {
- m.p[i] = p[i] * invSqrt;
- }
- return m;
- }
- /*
- ========================
- idVecX::NormalizeSelf
- ========================
- */
- ID_INLINE float idVecX::NormalizeSelf() {
- float sum = 0.0f;
- for ( int i = 0; i < size; i++ ) {
- sum += p[i] * p[i];
- }
- float invSqrt = idMath::InvSqrt( sum );
- for ( int i = 0; i < size; i++ ) {
- p[i] *= invSqrt;
- }
- return invSqrt * sum;
- }
- /*
- ========================
- idVecX::GetDimension
- ========================
- */
- ID_INLINE int idVecX::GetDimension() const {
- return size;
- }
- /*
- ========================
- idVecX::SubVec3
- ========================
- */
- ID_INLINE idVec3 &idVecX::SubVec3( int index ) {
- assert( index >= 0 && index * 3 + 3 <= size );
- return *reinterpret_cast<idVec3 *>(p + index * 3);
- }
- /*
- ========================
- idVecX::SubVec3
- ========================
- */
- ID_INLINE const idVec3 &idVecX::SubVec3( int index ) const {
- assert( index >= 0 && index * 3 + 3 <= size );
- return *reinterpret_cast<const idVec3 *>(p + index * 3);
- }
- /*
- ========================
- idVecX::SubVec6
- ========================
- */
- ID_INLINE idVec6 &idVecX::SubVec6( int index ) {
- assert( index >= 0 && index * 6 + 6 <= size );
- return *reinterpret_cast<idVec6 *>(p + index * 6);
- }
- /*
- ========================
- idVecX::SubVec6
- ========================
- */
- ID_INLINE const idVec6 &idVecX::SubVec6( int index ) const {
- assert( index >= 0 && index * 6 + 6 <= size );
- return *reinterpret_cast<const idVec6 *>(p + index * 6);
- }
- /*
- ========================
- idVecX::ToFloatPtr
- ========================
- */
- ID_INLINE const float *idVecX::ToFloatPtr() const {
- return p;
- }
- /*
- ========================
- idVecX::ToFloatPtr
- ========================
- */
- ID_INLINE float *idVecX::ToFloatPtr() {
- return p;
- }
- /*
- ========================
- idVecX::AddScaleAdd
- ========================
- */
- ID_INLINE void idVecX::AddScaleAdd( const float scale, const idVecX &v0, const idVecX &v1 ) {
- assert( GetSize() == v0.GetSize() );
- assert( GetSize() == v1.GetSize() );
- const float * v0Ptr = v0.ToFloatPtr();
- const float * v1Ptr = v1.ToFloatPtr();
- float * dstPtr = ToFloatPtr();
- for ( int i = 0; i < size; i++ ) {
- dstPtr[i] += scale * ( v0Ptr[i] + v1Ptr[i] );
- }
- }
- #endif // !__MATH_VECTORX_H__
|