VecX.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. 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.
  17. 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.
  18. ===========================================================================
  19. */
  20. #ifndef __MATH_VECX_H__
  21. #define __MATH_VECX_H__
  22. /*
  23. ===============================================================================
  24. idVecX - arbitrary sized vector
  25. The vector lives on 16 byte aligned and 16 byte padded memory.
  26. NOTE: due to the temporary memory pool idVecX cannot be used by multiple threads
  27. ===============================================================================
  28. */
  29. #define VECX_MAX_TEMP 1024
  30. #define VECX_QUAD( x ) ( ( ( ( x ) + 3 ) & ~3 ) * sizeof( float ) )
  31. #define VECX_CLEAREND() int s = size; while( s < ( ( s + 3) & ~3 ) ) { p[s++] = 0.0f; }
  32. #define VECX_ALLOCA( n ) ( (float *) _alloca16( VECX_QUAD( n ) ) )
  33. #define VECX_SIMD
  34. class idVecX {
  35. friend class idMatX;
  36. public:
  37. ID_INLINE idVecX();
  38. ID_INLINE explicit idVecX( int length );
  39. ID_INLINE explicit idVecX( int length, float *data );
  40. ID_INLINE ~idVecX();
  41. ID_INLINE float Get( int index ) const;
  42. ID_INLINE float & Get( int index );
  43. ID_INLINE float operator[]( const int index ) const;
  44. ID_INLINE float & operator[]( const int index );
  45. ID_INLINE idVecX operator-() const;
  46. ID_INLINE idVecX & operator=( const idVecX &a );
  47. ID_INLINE idVecX operator*( const float a ) const;
  48. ID_INLINE idVecX operator/( const float a ) const;
  49. ID_INLINE float operator*( const idVecX &a ) const;
  50. ID_INLINE idVecX operator-( const idVecX &a ) const;
  51. ID_INLINE idVecX operator+( const idVecX &a ) const;
  52. ID_INLINE idVecX & operator*=( const float a );
  53. ID_INLINE idVecX & operator/=( const float a );
  54. ID_INLINE idVecX & operator+=( const idVecX &a );
  55. ID_INLINE idVecX & operator-=( const idVecX &a );
  56. friend ID_INLINE idVecX operator*( const float a, const idVecX &b );
  57. ID_INLINE bool Compare( const idVecX &a ) const; // exact compare, no epsilon
  58. ID_INLINE bool Compare( const idVecX &a, const float epsilon ) const; // compare with epsilon
  59. ID_INLINE bool operator==( const idVecX &a ) const; // exact compare, no epsilon
  60. ID_INLINE bool operator!=( const idVecX &a ) const; // exact compare, no epsilon
  61. ID_INLINE void SetSize( int size );
  62. ID_INLINE void ChangeSize( int size, bool makeZero = false );
  63. ID_INLINE int GetSize() const { return size; }
  64. ID_INLINE void SetData( int length, float *data );
  65. ID_INLINE void Zero();
  66. ID_INLINE void Zero( int length );
  67. ID_INLINE void Random( int seed, float l = 0.0f, float u = 1.0f );
  68. ID_INLINE void Random( int length, int seed, float l = 0.0f, float u = 1.0f );
  69. ID_INLINE void Negate();
  70. ID_INLINE void Clamp( float min, float max );
  71. ID_INLINE idVecX & SwapElements( int e1, int e2 );
  72. ID_INLINE float Length() const;
  73. ID_INLINE float LengthSqr() const;
  74. ID_INLINE idVecX Normalize() const;
  75. ID_INLINE float NormalizeSelf();
  76. ID_INLINE int GetDimension() const;
  77. ID_INLINE void AddScaleAdd( const float scale, const idVecX & v0, const idVecX & v1 );
  78. ID_INLINE const idVec3 & SubVec3( int index ) const;
  79. ID_INLINE idVec3 & SubVec3( int index );
  80. ID_INLINE const idVec6 & SubVec6( int index = 0 ) const;
  81. ID_INLINE idVec6 & SubVec6( int index = 0 );
  82. ID_INLINE const float * ToFloatPtr() const;
  83. ID_INLINE float * ToFloatPtr();
  84. const char * ToString( int precision = 2 ) const;
  85. private:
  86. int size; // size of the vector
  87. int alloced; // if -1 p points to data set with SetData
  88. float * p; // memory the vector is stored
  89. static float temp[VECX_MAX_TEMP+4]; // used to store intermediate results
  90. static float * tempPtr; // pointer to 16 byte aligned temporary memory
  91. static int tempIndex; // index into memory pool, wraps around
  92. ID_INLINE void SetTempSize( int size );
  93. };
  94. /*
  95. ========================
  96. idVecX::idVecX
  97. ========================
  98. */
  99. ID_INLINE idVecX::idVecX() {
  100. size = alloced = 0;
  101. p = NULL;
  102. }
  103. /*
  104. ========================
  105. idVecX::idVecX
  106. ========================
  107. */
  108. ID_INLINE idVecX::idVecX( int length ) {
  109. size = alloced = 0;
  110. p = NULL;
  111. SetSize( length );
  112. }
  113. /*
  114. ========================
  115. idVecX::idVecX
  116. ========================
  117. */
  118. ID_INLINE idVecX::idVecX( int length, float *data ) {
  119. size = alloced = 0;
  120. p = NULL;
  121. SetData( length, data );
  122. }
  123. /*
  124. ========================
  125. idVecX::~idVecX
  126. ========================
  127. */
  128. ID_INLINE idVecX::~idVecX() {
  129. // if not temp memory
  130. if ( p && ( p < idVecX::tempPtr || p >= idVecX::tempPtr + VECX_MAX_TEMP ) && alloced != -1 ) {
  131. Mem_Free16( p );
  132. }
  133. }
  134. /*
  135. ========================
  136. idVecX::Get
  137. ========================
  138. */
  139. ID_INLINE float idVecX::Get( int index ) const {
  140. assert( index >= 0 && index < size );
  141. return p[index];
  142. }
  143. /*
  144. ========================
  145. idVecX::Get
  146. ========================
  147. */
  148. ID_INLINE float & idVecX::Get( int index ) {
  149. assert( index >= 0 && index < size );
  150. return p[index];
  151. }
  152. /*
  153. ========================
  154. idVecX::operator[]
  155. ========================
  156. */
  157. ID_INLINE float idVecX::operator[]( int index ) const {
  158. return Get( index );
  159. }
  160. /*
  161. ========================
  162. idVecX::operator[]
  163. ========================
  164. */
  165. ID_INLINE float & idVecX::operator[]( int index ) {
  166. return Get( index );
  167. }
  168. /*
  169. ========================
  170. idVecX::operator-
  171. ========================
  172. */
  173. ID_INLINE idVecX idVecX::operator-() const {
  174. idVecX m;
  175. m.SetTempSize( size );
  176. #if defined(ID_WIN_X86_SSE_INTRIN) && defined(VECX_SIMD)
  177. ALIGN16( unsigned int signBit[4] ) = { IEEE_FLT_SIGN_MASK, IEEE_FLT_SIGN_MASK, IEEE_FLT_SIGN_MASK, IEEE_FLT_SIGN_MASK };
  178. for ( int i = 0; i < size; i += 4 ) {
  179. _mm_store_ps( m.p + i, _mm_xor_ps( _mm_load_ps( p + i ), (__m128 &) signBit[0] ) );
  180. }
  181. #else
  182. for ( int i = 0; i < size; i++ ) {
  183. m.p[i] = -p[i];
  184. }
  185. #endif
  186. return m;
  187. }
  188. /*
  189. ========================
  190. idVecX::operator=
  191. ========================
  192. */
  193. ID_INLINE idVecX &idVecX::operator=( const idVecX &a ) {
  194. SetSize( a.size );
  195. #if defined(ID_WIN_X86_SSE_INTRIN) && defined(VECX_SIMD)
  196. for ( int i = 0; i < a.size; i += 4 ) {
  197. _mm_store_ps( p + i, _mm_load_ps( a.p + i ) );
  198. }
  199. #else
  200. memcpy( p, a.p, a.size * sizeof( float ) );
  201. #endif
  202. idVecX::tempIndex = 0;
  203. return *this;
  204. }
  205. /*
  206. ========================
  207. idVecX::operator+
  208. ========================
  209. */
  210. ID_INLINE idVecX idVecX::operator+( const idVecX &a ) const {
  211. idVecX m;
  212. assert( size == a.size );
  213. m.SetTempSize( size );
  214. #if defined(ID_WIN_X86_SSE_INTRIN) && defined(VECX_SIMD)
  215. for ( int i = 0; i < size; i += 4 ) {
  216. _mm_store_ps( m.p + i, _mm_add_ps( _mm_load_ps( p + i ), _mm_load_ps( a.p + i ) ) );
  217. }
  218. #else
  219. for ( int i = 0; i < size; i++ ) {
  220. m.p[i] = p[i] + a.p[i];
  221. }
  222. #endif
  223. return m;
  224. }
  225. /*
  226. ========================
  227. idVecX::operator-
  228. ========================
  229. */
  230. ID_INLINE idVecX idVecX::operator-( const idVecX &a ) const {
  231. idVecX m;
  232. assert( size == a.size );
  233. m.SetTempSize( size );
  234. #if defined(ID_WIN_X86_SSE_INTRIN) && defined(VECX_SIMD)
  235. for ( int i = 0; i < size; i += 4 ) {
  236. _mm_store_ps( m.p + i, _mm_sub_ps( _mm_load_ps( p + i ), _mm_load_ps( a.p + i ) ) );
  237. }
  238. #else
  239. for ( int i = 0; i < size; i++ ) {
  240. m.p[i] = p[i] - a.p[i];
  241. }
  242. #endif
  243. return m;
  244. }
  245. /*
  246. ========================
  247. idVecX::operator+=
  248. ========================
  249. */
  250. ID_INLINE idVecX &idVecX::operator+=( const idVecX &a ) {
  251. assert( size == a.size );
  252. #if defined(ID_WIN_X86_SSE_INTRIN) && defined(VECX_SIMD)
  253. for ( int i = 0; i < size; i += 4 ) {
  254. _mm_store_ps( p + i, _mm_add_ps( _mm_load_ps( p + i ), _mm_load_ps( a.p + i ) ) );
  255. }
  256. #else
  257. for ( int i = 0; i < size; i++ ) {
  258. p[i] += a.p[i];
  259. }
  260. #endif
  261. idVecX::tempIndex = 0;
  262. return *this;
  263. }
  264. /*
  265. ========================
  266. idVecX::operator-=
  267. ========================
  268. */
  269. ID_INLINE idVecX &idVecX::operator-=( const idVecX &a ) {
  270. assert( size == a.size );
  271. #if defined(ID_WIN_X86_SSE_INTRIN) && defined(VECX_SIMD)
  272. for ( int i = 0; i < size; i += 4 ) {
  273. _mm_store_ps( p + i, _mm_sub_ps( _mm_load_ps( p + i ), _mm_load_ps( a.p + i ) ) );
  274. }
  275. #else
  276. for ( int i = 0; i < size; i++ ) {
  277. p[i] -= a.p[i];
  278. }
  279. #endif
  280. idVecX::tempIndex = 0;
  281. return *this;
  282. }
  283. /*
  284. ========================
  285. idVecX::operator*
  286. ========================
  287. */
  288. ID_INLINE idVecX idVecX::operator*( const float a ) const {
  289. idVecX m;
  290. m.SetTempSize( size );
  291. #if defined(ID_WIN_X86_SSE_INTRIN) && defined(VECX_SIMD)
  292. __m128 va = _mm_load1_ps( & a );
  293. for ( int i = 0; i < size; i += 4 ) {
  294. _mm_store_ps( m.p + i, _mm_mul_ps( _mm_load_ps( p + i ), va ) );
  295. }
  296. #else
  297. for ( int i = 0; i < size; i++ ) {
  298. m.p[i] = p[i] * a;
  299. }
  300. #endif
  301. return m;
  302. }
  303. /*
  304. ========================
  305. idVecX::operator*=
  306. ========================
  307. */
  308. ID_INLINE idVecX &idVecX::operator*=( const float a ) {
  309. #if defined(ID_WIN_X86_SSE_INTRIN) && defined(VECX_SIMD)
  310. __m128 va = _mm_load1_ps( & a );
  311. for ( int i = 0; i < size; i += 4 ) {
  312. _mm_store_ps( p + i, _mm_mul_ps( _mm_load_ps( p + i ), va ) );
  313. }
  314. #else
  315. for ( int i = 0; i < size; i++ ) {
  316. p[i] *= a;
  317. }
  318. #endif
  319. return *this;
  320. }
  321. /*
  322. ========================
  323. idVecX::operator/
  324. ========================
  325. */
  326. ID_INLINE idVecX idVecX::operator/( const float a ) const {
  327. assert( fabs( a ) > idMath::FLT_SMALLEST_NON_DENORMAL );
  328. return (*this) * ( 1.0f / a );
  329. }
  330. /*
  331. ========================
  332. idVecX::operator/=
  333. ========================
  334. */
  335. ID_INLINE idVecX &idVecX::operator/=( const float a ) {
  336. assert( fabs( a ) > idMath::FLT_SMALLEST_NON_DENORMAL );
  337. (*this) *= ( 1.0f / a );
  338. return *this;
  339. }
  340. /*
  341. ========================
  342. operator*
  343. ========================
  344. */
  345. ID_INLINE idVecX operator*( const float a, const idVecX &b ) {
  346. return b * a;
  347. }
  348. /*
  349. ========================
  350. idVecX::operator*
  351. ========================
  352. */
  353. ID_INLINE float idVecX::operator*( const idVecX &a ) const {
  354. assert( size == a.size );
  355. float sum = 0.0f;
  356. for ( int i = 0; i < size; i++ ) {
  357. sum += p[i] * a.p[i];
  358. }
  359. return sum;
  360. }
  361. /*
  362. ========================
  363. idVecX::Compare
  364. ========================
  365. */
  366. ID_INLINE bool idVecX::Compare( const idVecX &a ) const {
  367. assert( size == a.size );
  368. for ( int i = 0; i < size; i++ ) {
  369. if ( p[i] != a.p[i] ) {
  370. return false;
  371. }
  372. }
  373. return true;
  374. }
  375. /*
  376. ========================
  377. idVecX::Compare
  378. ========================
  379. */
  380. ID_INLINE bool idVecX::Compare( const idVecX &a, const float epsilon ) const {
  381. assert( size == a.size );
  382. for ( int i = 0; i < size; i++ ) {
  383. if ( idMath::Fabs( p[i] - a.p[i] ) > epsilon ) {
  384. return false;
  385. }
  386. }
  387. return true;
  388. }
  389. /*
  390. ========================
  391. idVecX::operator==
  392. ========================
  393. */
  394. ID_INLINE bool idVecX::operator==( const idVecX &a ) const {
  395. return Compare( a );
  396. }
  397. /*
  398. ========================
  399. idVecX::operator!=
  400. ========================
  401. */
  402. ID_INLINE bool idVecX::operator!=( const idVecX &a ) const {
  403. return !Compare( a );
  404. }
  405. /*
  406. ========================
  407. idVecX::SetSize
  408. ========================
  409. */
  410. ID_INLINE void idVecX::SetSize( int newSize ) {
  411. //assert( p < idVecX::tempPtr || p > idVecX::tempPtr + VECX_MAX_TEMP );
  412. if ( newSize != size || p == NULL ) {
  413. int alloc = ( newSize + 3 ) & ~3;
  414. if ( alloc > alloced && alloced != -1 ) {
  415. if ( p ) {
  416. Mem_Free16( p );
  417. }
  418. p = (float *) Mem_Alloc16( alloc * sizeof( float ), TAG_MATH );
  419. alloced = alloc;
  420. }
  421. size = newSize;
  422. VECX_CLEAREND();
  423. }
  424. }
  425. /*
  426. ========================
  427. idVecX::ChangeSize
  428. ========================
  429. */
  430. ID_INLINE void idVecX::ChangeSize( int newSize, bool makeZero ) {
  431. if ( newSize != size ) {
  432. int alloc = ( newSize + 3 ) & ~3;
  433. if ( alloc > alloced && alloced != -1 ) {
  434. float *oldVec = p;
  435. p = (float *) Mem_Alloc16( alloc * sizeof( float ), TAG_MATH );
  436. alloced = alloc;
  437. if ( oldVec ) {
  438. for ( int i = 0; i < size; i++ ) {
  439. p[i] = oldVec[i];
  440. }
  441. Mem_Free16( oldVec );
  442. }
  443. if ( makeZero ) {
  444. // zero any new elements
  445. for ( int i = size; i < newSize; i++ ) {
  446. p[i] = 0.0f;
  447. }
  448. }
  449. }
  450. size = newSize;
  451. VECX_CLEAREND();
  452. }
  453. }
  454. /*
  455. ========================
  456. idVecX::SetTempSize
  457. ========================
  458. */
  459. ID_INLINE void idVecX::SetTempSize( int newSize ) {
  460. size = newSize;
  461. alloced = ( newSize + 3 ) & ~3;
  462. assert( alloced < VECX_MAX_TEMP );
  463. if ( idVecX::tempIndex + alloced > VECX_MAX_TEMP ) {
  464. idVecX::tempIndex = 0;
  465. }
  466. p = idVecX::tempPtr + idVecX::tempIndex;
  467. idVecX::tempIndex += alloced;
  468. VECX_CLEAREND();
  469. }
  470. /*
  471. ========================
  472. idVecX::SetData
  473. ========================
  474. */
  475. ID_INLINE void idVecX::SetData( int length, float *data ) {
  476. if ( p != NULL && ( p < idVecX::tempPtr || p >= idVecX::tempPtr + VECX_MAX_TEMP ) && alloced != -1 ) {
  477. Mem_Free16( p );
  478. }
  479. assert_16_byte_aligned( data ); // data must be 16 byte aligned
  480. p = data;
  481. size = length;
  482. alloced = -1;
  483. VECX_CLEAREND();
  484. }
  485. /*
  486. ========================
  487. idVecX::Zero
  488. ========================
  489. */
  490. ID_INLINE void idVecX::Zero() {
  491. #if defined(ID_WIN_X86_SSE_INTRIN) && defined(VECX_SIMD)
  492. for ( int i = 0; i < size; i += 4 ) {
  493. _mm_store_ps( p + i, _mm_setzero_ps() );
  494. }
  495. #else
  496. memset( p, 0, size * sizeof( float ) );
  497. #endif
  498. }
  499. /*
  500. ========================
  501. idVecX::Zero
  502. ========================
  503. */
  504. ID_INLINE void idVecX::Zero( int length ) {
  505. SetSize( length );
  506. #if defined(ID_WIN_X86_SSE_INTRIN) && defined(VECX_SIMD)
  507. for ( int i = 0; i < length; i += 4 ) {
  508. _mm_store_ps( p + i, _mm_setzero_ps() );
  509. }
  510. #else
  511. memset( p, 0, length * sizeof( float ) );
  512. #endif
  513. }
  514. /*
  515. ========================
  516. idVecX::Random
  517. ========================
  518. */
  519. ID_INLINE void idVecX::Random( int seed, float l, float u ) {
  520. idRandom rnd( seed );
  521. float c = u - l;
  522. for ( int i = 0; i < size; i++ ) {
  523. p[i] = l + rnd.RandomFloat() * c;
  524. }
  525. }
  526. /*
  527. ========================
  528. idVecX::Random
  529. ========================
  530. */
  531. ID_INLINE void idVecX::Random( int length, int seed, float l, float u ) {
  532. idRandom rnd( seed );
  533. SetSize( length );
  534. float c = u - l;
  535. for ( int i = 0; i < size; i++ ) {
  536. p[i] = l + rnd.RandomFloat() * c;
  537. }
  538. }
  539. /*
  540. ========================
  541. idVecX::Negate
  542. ========================
  543. */
  544. ID_INLINE void idVecX::Negate() {
  545. #if defined(ID_WIN_X86_SSE_INTRIN) && defined(VECX_SIMD)
  546. ALIGN16( const unsigned int signBit[4] ) = { IEEE_FLT_SIGN_MASK, IEEE_FLT_SIGN_MASK, IEEE_FLT_SIGN_MASK, IEEE_FLT_SIGN_MASK };
  547. for ( int i = 0; i < size; i += 4 ) {
  548. _mm_store_ps( p + i, _mm_xor_ps( _mm_load_ps( p + i ), (__m128 &) signBit[0] ) );
  549. }
  550. #else
  551. for ( int i = 0; i < size; i++ ) {
  552. p[i] = -p[i];
  553. }
  554. #endif
  555. }
  556. /*
  557. ========================
  558. idVecX::Clamp
  559. ========================
  560. */
  561. ID_INLINE void idVecX::Clamp( float min, float max ) {
  562. for ( int i = 0; i < size; i++ ) {
  563. if ( p[i] < min ) {
  564. p[i] = min;
  565. } else if ( p[i] > max ) {
  566. p[i] = max;
  567. }
  568. }
  569. }
  570. /*
  571. ========================
  572. idVecX::SwapElements
  573. ========================
  574. */
  575. ID_INLINE idVecX &idVecX::SwapElements( int e1, int e2 ) {
  576. float tmp;
  577. tmp = p[e1];
  578. p[e1] = p[e2];
  579. p[e2] = tmp;
  580. return *this;
  581. }
  582. /*
  583. ========================
  584. idVecX::Length
  585. ========================
  586. */
  587. ID_INLINE float idVecX::Length() const {
  588. float sum = 0.0f;
  589. for ( int i = 0; i < size; i++ ) {
  590. sum += p[i] * p[i];
  591. }
  592. return idMath::Sqrt( sum );
  593. }
  594. /*
  595. ========================
  596. idVecX::LengthSqr
  597. ========================
  598. */
  599. ID_INLINE float idVecX::LengthSqr() const {
  600. float sum = 0.0f;
  601. for ( int i = 0; i < size; i++ ) {
  602. sum += p[i] * p[i];
  603. }
  604. return sum;
  605. }
  606. /*
  607. ========================
  608. idVecX::Normalize
  609. ========================
  610. */
  611. ID_INLINE idVecX idVecX::Normalize() const {
  612. idVecX m;
  613. m.SetTempSize( size );
  614. float sum = 0.0f;
  615. for ( int i = 0; i < size; i++ ) {
  616. sum += p[i] * p[i];
  617. }
  618. float invSqrt = idMath::InvSqrt( sum );
  619. for ( int i = 0; i < size; i++ ) {
  620. m.p[i] = p[i] * invSqrt;
  621. }
  622. return m;
  623. }
  624. /*
  625. ========================
  626. idVecX::NormalizeSelf
  627. ========================
  628. */
  629. ID_INLINE float idVecX::NormalizeSelf() {
  630. float sum = 0.0f;
  631. for ( int i = 0; i < size; i++ ) {
  632. sum += p[i] * p[i];
  633. }
  634. float invSqrt = idMath::InvSqrt( sum );
  635. for ( int i = 0; i < size; i++ ) {
  636. p[i] *= invSqrt;
  637. }
  638. return invSqrt * sum;
  639. }
  640. /*
  641. ========================
  642. idVecX::GetDimension
  643. ========================
  644. */
  645. ID_INLINE int idVecX::GetDimension() const {
  646. return size;
  647. }
  648. /*
  649. ========================
  650. idVecX::SubVec3
  651. ========================
  652. */
  653. ID_INLINE idVec3 &idVecX::SubVec3( int index ) {
  654. assert( index >= 0 && index * 3 + 3 <= size );
  655. return *reinterpret_cast<idVec3 *>(p + index * 3);
  656. }
  657. /*
  658. ========================
  659. idVecX::SubVec3
  660. ========================
  661. */
  662. ID_INLINE const idVec3 &idVecX::SubVec3( int index ) const {
  663. assert( index >= 0 && index * 3 + 3 <= size );
  664. return *reinterpret_cast<const idVec3 *>(p + index * 3);
  665. }
  666. /*
  667. ========================
  668. idVecX::SubVec6
  669. ========================
  670. */
  671. ID_INLINE idVec6 &idVecX::SubVec6( int index ) {
  672. assert( index >= 0 && index * 6 + 6 <= size );
  673. return *reinterpret_cast<idVec6 *>(p + index * 6);
  674. }
  675. /*
  676. ========================
  677. idVecX::SubVec6
  678. ========================
  679. */
  680. ID_INLINE const idVec6 &idVecX::SubVec6( int index ) const {
  681. assert( index >= 0 && index * 6 + 6 <= size );
  682. return *reinterpret_cast<const idVec6 *>(p + index * 6);
  683. }
  684. /*
  685. ========================
  686. idVecX::ToFloatPtr
  687. ========================
  688. */
  689. ID_INLINE const float *idVecX::ToFloatPtr() const {
  690. return p;
  691. }
  692. /*
  693. ========================
  694. idVecX::ToFloatPtr
  695. ========================
  696. */
  697. ID_INLINE float *idVecX::ToFloatPtr() {
  698. return p;
  699. }
  700. /*
  701. ========================
  702. idVecX::AddScaleAdd
  703. ========================
  704. */
  705. ID_INLINE void idVecX::AddScaleAdd( const float scale, const idVecX &v0, const idVecX &v1 ) {
  706. assert( GetSize() == v0.GetSize() );
  707. assert( GetSize() == v1.GetSize() );
  708. const float * v0Ptr = v0.ToFloatPtr();
  709. const float * v1Ptr = v1.ToFloatPtr();
  710. float * dstPtr = ToFloatPtr();
  711. for ( int i = 0; i < size; i++ ) {
  712. dstPtr[i] += scale * ( v0Ptr[i] + v1Ptr[i] );
  713. }
  714. }
  715. #endif // !__MATH_VECTORX_H__