DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

MatX.cpp (114641B)


      1 /*
      2 ===========================================================================
      3 
      4 Doom 3 BFG Edition GPL Source Code
      5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 
      6 
      7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").  
      8 
      9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
     10 it under the terms of the GNU General Public License as published by
     11 the Free Software Foundation, either version 3 of the License, or
     12 (at your option) any later version.
     13 
     14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
     15 but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17 GNU General Public License for more details.
     18 
     19 You should have received a copy of the GNU General Public License
     20 along with Doom 3 BFG Edition Source Code.  If not, see <http://www.gnu.org/licenses/>.
     21 
     22 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.
     23 
     24 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.
     25 
     26 ===========================================================================
     27 */
     28 
     29 #pragma hdrstop
     30 #include "../precompiled.h"
     31 
     32 //===============================================================
     33 //
     34 //  idMatX
     35 //
     36 //===============================================================
     37 
     38 float	idMatX::temp[MATX_MAX_TEMP+4];
     39 float *	idMatX::tempPtr = (float *) ( ( (int) idMatX::temp + 15 ) & ~15 );
     40 int		idMatX::tempIndex = 0;
     41 
     42 
     43 /*
     44 ============
     45 idMatX::ChangeSize
     46 ============
     47 */
     48 void idMatX::ChangeSize( int rows, int columns, bool makeZero ) {
     49 	int alloc = ( rows * columns + 3 ) & ~3;
     50 	if ( alloc > alloced && alloced != -1 ) {
     51 		float *oldMat = mat;
     52 		mat = (float *) Mem_Alloc16( alloc * sizeof( float ), TAG_MATH );
     53 		if ( makeZero ) {
     54 			memset( mat, 0, alloc * sizeof( float ) );
     55 		}
     56 		alloced = alloc;
     57 		if ( oldMat ) {
     58 			int minRow = Min( numRows, rows );
     59 			int minColumn = Min( numColumns, columns );
     60 			for ( int i = 0; i < minRow; i++ ) {
     61 				for ( int j = 0; j < minColumn; j++ ) {
     62 					mat[ i * columns + j ] = oldMat[ i * numColumns + j ];
     63 				}
     64 			}
     65 			Mem_Free16( oldMat );
     66 		}
     67 	} else {
     68 		if ( columns < numColumns ) {
     69 			int minRow = Min( numRows, rows );
     70 			for ( int i = 0; i < minRow; i++ ) {
     71 				for ( int j = 0; j < columns; j++ ) {
     72 					mat[ i * columns + j ] = mat[ i * numColumns + j ];
     73 				}
     74 			}
     75 		} else if ( columns > numColumns ) {
     76 			for ( int i = Min( numRows, rows ) - 1; i >= 0; i-- ) {
     77 				if ( makeZero ) {
     78 					for ( int j = columns - 1; j >= numColumns; j-- ) {
     79 						mat[ i * columns + j ] = 0.0f;
     80 					}
     81 				}
     82 				for ( int j = numColumns - 1; j >= 0; j-- ) {
     83 					mat[ i * columns + j ] = mat[ i * numColumns + j ];
     84 				}
     85 			}
     86 		}
     87 		if ( makeZero && rows > numRows ) {
     88 			memset( mat + numRows * columns, 0, ( rows - numRows ) * columns * sizeof( float ) );
     89 		}
     90 	}
     91 	numRows = rows;
     92 	numColumns = columns;
     93 	MATX_CLEAREND();
     94 }
     95 
     96 /*
     97 ============
     98 idMatX::RemoveRow
     99 ============
    100 */
    101 idMatX &idMatX::RemoveRow( int r ) {
    102 	int i;
    103 
    104 	assert( r < numRows );
    105 
    106 	numRows--;
    107 
    108 	for ( i = r; i < numRows; i++ ) {
    109 		memcpy( &mat[i * numColumns], &mat[( i + 1 ) * numColumns], numColumns * sizeof( float ) );
    110 	}
    111 
    112 	return *this;
    113 }
    114 
    115 /*
    116 ============
    117 idMatX::RemoveColumn
    118 ============
    119 */
    120 idMatX &idMatX::RemoveColumn( int r ) {
    121 	int i;
    122 
    123 	assert( r < numColumns );
    124 
    125 	numColumns--;
    126 
    127 	for ( i = 0; i < numRows - 1; i++ ) {
    128 		memmove( &mat[i * numColumns + r], &mat[i * ( numColumns + 1 ) + r + 1], numColumns * sizeof( float ) );
    129 	}
    130 	memmove( &mat[i * numColumns + r], &mat[i * ( numColumns + 1 ) + r + 1], ( numColumns - r ) * sizeof( float ) );
    131 
    132 	return *this;
    133 }
    134 
    135 /*
    136 ============
    137 idMatX::RemoveRowColumn
    138 ============
    139 */
    140 idMatX &idMatX::RemoveRowColumn( int r ) {
    141 	int i;
    142 
    143 	assert( r < numRows && r < numColumns );
    144 
    145 	numRows--;
    146 	numColumns--;
    147 
    148 	if ( r > 0 ) {
    149 		for ( i = 0; i < r - 1; i++ ) {
    150 			memmove( &mat[i * numColumns + r], &mat[i * ( numColumns + 1 ) + r + 1], numColumns * sizeof( float ) );
    151 		}
    152 		memmove( &mat[i * numColumns + r], &mat[i * ( numColumns + 1 ) + r + 1], ( numColumns - r ) * sizeof( float ) );
    153 	}
    154 
    155 	memcpy( &mat[r * numColumns], &mat[( r + 1 ) * ( numColumns + 1 )], r * sizeof( float ) );
    156 
    157 	for ( i = r; i < numRows - 1; i++ ) {
    158 		memcpy( &mat[i * numColumns + r], &mat[( i + 1 ) * ( numColumns + 1 ) + r + 1], numColumns * sizeof( float ) );
    159 	}
    160 	memcpy( &mat[i * numColumns + r], &mat[( i + 1 ) * ( numColumns + 1 ) + r + 1], ( numColumns - r ) * sizeof( float ) );
    161 
    162 	return *this;
    163 }
    164 
    165 /*
    166 ========================
    167 idMatX::CopyLowerToUpperTriangle
    168 ========================
    169 */
    170 void idMatX::CopyLowerToUpperTriangle() {
    171 	assert( ( GetNumColumns() & 3 ) == 0 );
    172 	assert( GetNumColumns() >= GetNumRows() );
    173 
    174 #ifdef ID_WIN_X86_SSE_INTRIN
    175 
    176 	const int n = GetNumColumns();
    177 	const int m = GetNumRows();
    178 
    179 	const int n0 = 0;
    180 	const int n1 = n;
    181 	const int n2 = ( n << 1 );
    182 	const int n3 = ( n << 1 ) + n;
    183 	const int n4 = ( n << 2 );
    184 
    185 	const int b1 = ( ( m - 0 ) >> 1 ) & 1;	// ( m & 3 ) > 1
    186 	const int b2 = ( ( m - 1 ) >> 1 ) & 1;	// ( m & 3 ) > 2 (provided ( m & 3 ) > 0)
    187 
    188 	const int n1_masked = ( n & -b1 );
    189 	const int n2_masked = ( n & -b1 ) + ( n & -b2 );
    190 
    191 	const __m128 mask0 = __m128c( _mm_set_epi32(  0,  0,  0, -1 ) );
    192 	const __m128 mask1 = __m128c( _mm_set_epi32(  0,  0, -1, -1 ) );
    193 	const __m128 mask2 = __m128c( _mm_set_epi32(  0, -1, -1, -1 ) );
    194 	const __m128 mask3 = __m128c( _mm_set_epi32( -1, -1, -1, -1 ) );
    195 
    196 	const __m128 bottomMask[2] = { __m128c( _mm_set1_epi32( 0 ) ), __m128c( _mm_set1_epi32( -1 ) ) };
    197 
    198 	float * __restrict basePtr = ToFloatPtr();
    199 
    200 	for ( int i = 0; i < m - 3; i += 4 ) {
    201 
    202 		// copy top left diagonal 4x4 block elements
    203 		__m128 r0 = _mm_and_ps( _mm_load_ps( basePtr + n0 ), mask0 );
    204 		__m128 r1 = _mm_and_ps( _mm_load_ps( basePtr + n1 ), mask1 );
    205 		__m128 r2 = _mm_and_ps( _mm_load_ps( basePtr + n2 ), mask2 );
    206 		__m128 r3 = _mm_and_ps( _mm_load_ps( basePtr + n3 ), mask3 );
    207 
    208 		__m128 t0 = _mm_unpacklo_ps( r0, r2 );	// x0, z0, x1, z1
    209 		__m128 t1 = _mm_unpackhi_ps( r0, r2 );	// x2, z2, x3, z3
    210 		__m128 t2 = _mm_unpacklo_ps( r1, r3 );	// y0, w0, y1, w1
    211 		__m128 t3 = _mm_unpackhi_ps( r1, r3 );	// y2, w2, y3, w3
    212 
    213 		__m128 s0 = _mm_unpacklo_ps( t0, t2 );	// x0, y0, z0, w0
    214 		__m128 s1 = _mm_unpackhi_ps( t0, t2 );	// x1, y1, z1, w1
    215 		__m128 s2 = _mm_unpacklo_ps( t1, t3 );	// x2, y2, z2, w2
    216 		__m128 s3 = _mm_unpackhi_ps( t1, t3 );	// x3, y3, z3, w3
    217 
    218 		r0 = _mm_or_ps( r0, s0 );
    219 		r1 = _mm_or_ps( r1, s1 );
    220 		r2 = _mm_or_ps( r2, s2 );
    221 		r3 = _mm_or_ps( r3, s3 );
    222 
    223 		_mm_store_ps( basePtr + n0, r0 );
    224 		_mm_store_ps( basePtr + n1, r1 );
    225 		_mm_store_ps( basePtr + n2, r2 );
    226 		_mm_store_ps( basePtr + n3, r3 );
    227 
    228 		// copy one column of 4x4 blocks to one row of 4x4 blocks
    229 		const float * __restrict srcPtr = basePtr;
    230 		float * __restrict dstPtr = basePtr;
    231 
    232 		for ( int j = i + 4; j < m - 3; j += 4 ) {
    233 			srcPtr += n4;
    234 			dstPtr += 4;
    235 
    236 			__m128 r0 = _mm_load_ps( srcPtr + n0 );
    237 			__m128 r1 = _mm_load_ps( srcPtr + n1 );
    238 			__m128 r2 = _mm_load_ps( srcPtr + n2 );
    239 			__m128 r3 = _mm_load_ps( srcPtr + n3 );
    240 
    241 			__m128 t0 = _mm_unpacklo_ps( r0, r2 );	// x0, z0, x1, z1
    242 			__m128 t1 = _mm_unpackhi_ps( r0, r2 );	// x2, z2, x3, z3
    243 			__m128 t2 = _mm_unpacklo_ps( r1, r3 );	// y0, w0, y1, w1
    244 			__m128 t3 = _mm_unpackhi_ps( r1, r3 );	// y2, w2, y3, w3
    245 
    246 			r0 = _mm_unpacklo_ps( t0, t2 );			// x0, y0, z0, w0
    247 			r1 = _mm_unpackhi_ps( t0, t2 );			// x1, y1, z1, w1
    248 			r2 = _mm_unpacklo_ps( t1, t3 );			// x2, y2, z2, w2
    249 			r3 = _mm_unpackhi_ps( t1, t3 );			// x3, y3, z3, w3
    250 
    251 			_mm_store_ps( dstPtr + n0, r0 );
    252 			_mm_store_ps( dstPtr + n1, r1 );
    253 			_mm_store_ps( dstPtr + n2, r2 );
    254 			_mm_store_ps( dstPtr + n3, r3 );
    255 		}
    256 
    257 		// copy the last partial 4x4 block elements
    258 		if ( m & 3 ) {
    259 			srcPtr += n4;
    260 			dstPtr += 4;
    261 
    262 			__m128 r0 = _mm_load_ps( srcPtr + n0 );
    263 			__m128 r1 = _mm_and_ps( _mm_load_ps( srcPtr + n1_masked ), bottomMask[b1] );
    264 			__m128 r2 = _mm_and_ps( _mm_load_ps( srcPtr + n2_masked ), bottomMask[b2] );
    265 			__m128 r3 = _mm_setzero_ps();
    266 
    267 			__m128 t0 = _mm_unpacklo_ps( r0, r2 );	// x0, z0, x1, z1
    268 			__m128 t1 = _mm_unpackhi_ps( r0, r2 );	// x2, z2, x3, z3
    269 			__m128 t2 = _mm_unpacklo_ps( r1, r3 );	// y0, w0, y1, w1
    270 			__m128 t3 = _mm_unpackhi_ps( r1, r3 );	// y2, w2, y3, w3
    271 
    272 			r0 = _mm_unpacklo_ps( t0, t2 );			// x0, y0, z0, w0
    273 			r1 = _mm_unpackhi_ps( t0, t2 );			// x1, y1, z1, w1
    274 			r2 = _mm_unpacklo_ps( t1, t3 );			// x2, y2, z2, w2
    275 			r3 = _mm_unpackhi_ps( t1, t3 );			// x3, y3, z3, w3
    276 
    277 			_mm_store_ps( dstPtr + n0, r0 );
    278 			_mm_store_ps( dstPtr + n1, r1 );
    279 			_mm_store_ps( dstPtr + n2, r2 );
    280 			_mm_store_ps( dstPtr + n3, r3 );
    281 		}
    282 
    283 		basePtr += n4 + 4;
    284 	}
    285 
    286 	// copy the lower right partial diagonal 4x4 block elements
    287 	if ( m & 3 ) {
    288 		__m128 r0 = _mm_and_ps( _mm_load_ps( basePtr + n0 ), mask0 );
    289 		__m128 r1 = _mm_and_ps( _mm_load_ps( basePtr + n1_masked ), _mm_and_ps( mask1, bottomMask[b1] ) );
    290 		__m128 r2 = _mm_and_ps( _mm_load_ps( basePtr + n2_masked ), _mm_and_ps( mask2, bottomMask[b2] ) );
    291 		__m128 r3 = _mm_setzero_ps();
    292 
    293 		__m128 t0 = _mm_unpacklo_ps( r0, r2 );	// x0, z0, x1, z1
    294 		__m128 t1 = _mm_unpackhi_ps( r0, r2 );	// x2, z2, x3, z3
    295 		__m128 t2 = _mm_unpacklo_ps( r1, r3 );	// y0, w0, y1, w1
    296 		__m128 t3 = _mm_unpackhi_ps( r1, r3 );	// y2, w2, y3, w3
    297 
    298 		__m128 s0 = _mm_unpacklo_ps( t0, t2 );	// x0, y0, z0, w0
    299 		__m128 s1 = _mm_unpackhi_ps( t0, t2 );	// x1, y1, z1, w1
    300 		__m128 s2 = _mm_unpacklo_ps( t1, t3 );	// x2, y2, z2, w2
    301 
    302 		r0 = _mm_or_ps( r0, s0 );
    303 		r1 = _mm_or_ps( r1, s1 );
    304 		r2 = _mm_or_ps( r2, s2 );
    305 
    306 		_mm_store_ps( basePtr + n2_masked, r2 );
    307 		_mm_store_ps( basePtr + n1_masked, r1 );
    308 		_mm_store_ps( basePtr + n0, r0 );
    309 	}
    310 
    311 #else
    312 
    313 	const int n = GetNumColumns();
    314 	const int m = GetNumRows();
    315 	for ( int i = 0; i < m; i++ ) {
    316 		const float * __restrict ptr = ToFloatPtr() + ( i + 1 ) * n + i;
    317 		float * __restrict dstPtr = ToFloatPtr() + i * n;
    318 		for ( int j = i + 1; j < m; j++ ) {
    319 			dstPtr[j] = ptr[0];
    320 			ptr += n;
    321 		}
    322 	}
    323 
    324 #endif
    325 
    326 #ifdef _DEBUG
    327 	for ( int i = 0; i < numRows; i++ ) {
    328 		for ( int j = 0; j < numRows; j++ ) {
    329 			assert( mat[ i * numColumns + j ] == mat[ j * numColumns + i ] );
    330 		}
    331 	}
    332 #endif
    333 }
    334 /*
    335 ============
    336 idMatX::IsOrthogonal
    337 
    338   returns true if (*this) * this->Transpose() == Identity
    339 ============
    340 */
    341 bool idMatX::IsOrthogonal( const float epsilon ) const {
    342 	float *ptr1, *ptr2, sum;
    343 
    344 	if ( !IsSquare() ) {
    345 		return false;
    346 	}
    347 
    348 	ptr1 = mat;
    349 	for ( int i = 0; i < numRows; i++ ) {
    350 		for ( int j = 0; j < numColumns; j++ ) {
    351 			ptr2 = mat + j;
    352 			sum = ptr1[0] * ptr2[0] - (float) ( i == j );
    353 			for ( int n = 1; n < numColumns; n++ ) {
    354 				ptr2 += numColumns;
    355 				sum += ptr1[n] * ptr2[0];
    356 			}
    357 			if ( idMath::Fabs( sum ) > epsilon ) {
    358 				return false;
    359 			}
    360 		}
    361 		ptr1 += numColumns;
    362 	}
    363 	return true;
    364 }
    365 
    366 /*
    367 ============
    368 idMatX::IsOrthonormal
    369 
    370   returns true if (*this) * this->Transpose() == Identity and the length of each column vector is 1
    371 ============
    372 */
    373 bool idMatX::IsOrthonormal( const float epsilon ) const {
    374 	float *ptr1, *ptr2, sum;
    375 
    376 	if ( !IsSquare() ) {
    377 		return false;
    378 	}
    379 
    380 	ptr1 = mat;
    381 	for ( int i = 0; i < numRows; i++ ) {
    382 		for ( int j = 0; j < numColumns; j++ ) {
    383 			ptr2 = mat + j;
    384 			sum = ptr1[0] * ptr2[0] - (float) ( i == j );
    385 			for ( int n = 1; n < numColumns; n++ ) {
    386 				ptr2 += numColumns;
    387 				sum += ptr1[n] * ptr2[0];
    388 			}
    389 			if ( idMath::Fabs( sum ) > epsilon ) {
    390 				return false;
    391 			}
    392 		}
    393 		ptr1 += numColumns;
    394 
    395 		ptr2 = mat + i;
    396 		sum = ptr2[0] * ptr2[0] - 1.0f;
    397 		for ( int j = 1; j < numRows; j++ ) {
    398 			ptr2 += numColumns;
    399 			sum += ptr2[j] * ptr2[j];
    400 		}
    401 		if ( idMath::Fabs( sum ) > epsilon ) {
    402 			return false;
    403 		}
    404 	}
    405 	return true;
    406 }
    407 
    408 /*
    409 ============
    410 idMatX::IsPMatrix
    411 
    412   returns true if the matrix is a P-matrix
    413   A square matrix is a P-matrix if all its principal minors are positive.
    414 ============
    415 */
    416 bool idMatX::IsPMatrix( const float epsilon ) const {
    417 	int i, j;
    418 	float d;
    419 	idMatX m;
    420 
    421 	if ( !IsSquare() ) {
    422 		return false;
    423 	}
    424 
    425 	if ( numRows <= 0 ) {
    426 		return true;
    427 	}
    428 
    429 	if ( (*this)[0][0] <= epsilon ) {
    430 		return false;
    431 	}
    432 
    433 	if ( numRows <= 1 ) {
    434 		return true;
    435 	}
    436 
    437 	m.SetData( numRows - 1, numColumns - 1, MATX_ALLOCA( ( numRows - 1 ) * ( numColumns - 1 ) ) );
    438 
    439 	for ( i = 1; i < numRows; i++ ) {
    440 		for ( j = 1; j < numColumns; j++ ) {
    441 			m[i-1][j-1] = (*this)[i][j];
    442 		}
    443 	}
    444 
    445 	if ( !m.IsPMatrix( epsilon ) ) {
    446 		return false;
    447 	}
    448 
    449 	for ( i = 1; i < numRows; i++ ) {
    450 		d = (*this)[i][0] / (*this)[0][0];
    451 		for ( j = 1; j < numColumns; j++ ) {
    452 			m[i-1][j-1] = (*this)[i][j] - d * (*this)[0][j];
    453 		}
    454 	}
    455 
    456 	if ( !m.IsPMatrix( epsilon ) ) {
    457 		return false;
    458 	}
    459 
    460 	return true;
    461 }
    462 
    463 /*
    464 ============
    465 idMatX::IsZMatrix
    466 
    467   returns true if the matrix is a Z-matrix
    468   A square matrix M is a Z-matrix if M[i][j] <= 0 for all i != j.
    469 ============
    470 */
    471 bool idMatX::IsZMatrix( const float epsilon ) const {
    472 	int i, j;
    473 
    474 	if ( !IsSquare() ) {
    475 		return false;
    476 	}
    477 
    478 	for ( i = 0; i < numRows; i++ ) {
    479 		for ( j = 0; j < numColumns; j++ ) {
    480 			if ( (*this)[i][j] > epsilon && i != j ) {
    481 				return false;
    482 			}
    483 		}
    484 	}
    485 	return true;
    486 }
    487 
    488 /*
    489 ============
    490 idMatX::IsPositiveDefinite
    491 
    492   returns true if the matrix is Positive Definite (PD)
    493   A square matrix M of order n is said to be PD if y'My > 0 for all vectors y of dimension n, y != 0.
    494 ============
    495 */
    496 bool idMatX::IsPositiveDefinite( const float epsilon ) const {
    497 	int i, j, k;
    498 	float d, s;
    499 	idMatX m;
    500 
    501 	// the matrix must be square
    502 	if ( !IsSquare() ) {
    503 		return false;
    504 	}
    505 
    506 	// copy matrix
    507 	m.SetData( numRows, numColumns, MATX_ALLOCA( numRows * numColumns ) );
    508 	m = *this;
    509 
    510 	// add transpose
    511 	for ( i = 0; i < numRows; i++ ) {
    512 		for ( j = 0; j < numColumns; j++ ) {
    513 			m[i][j] += (*this)[j][i];
    514 		}
    515 	}
    516 
    517 	// test Positive Definiteness with Gaussian pivot steps
    518 	for ( i = 0; i < numRows; i++ ) {
    519 
    520 		for ( j = i; j < numColumns; j++ ) {
    521 			if ( m[j][j] <= epsilon ) {
    522 				return false;
    523 			}
    524 		}
    525 
    526 		d = 1.0f / m[i][i];
    527 		for ( j = i + 1; j < numColumns; j++ ) {
    528 			s = d * m[j][i];
    529 			m[j][i] = 0.0f;
    530 			for ( k = i + 1; k < numRows; k++ ) {
    531 				m[j][k] -= s * m[i][k];
    532 			}
    533 		}
    534 	}
    535 
    536 	return true;
    537 }
    538 
    539 /*
    540 ============
    541 idMatX::IsSymmetricPositiveDefinite
    542 
    543   returns true if the matrix is Symmetric Positive Definite (PD)
    544 ============
    545 */
    546 bool idMatX::IsSymmetricPositiveDefinite( const float epsilon ) const {
    547 	idMatX m;
    548 
    549 	// the matrix must be symmetric
    550 	if ( !IsSymmetric( epsilon ) ) {
    551 		return false;
    552 	}
    553 
    554 	// copy matrix
    555 	m.SetData( numRows, numColumns, MATX_ALLOCA( numRows * numColumns ) );
    556 	m = *this;
    557 
    558 	// being able to obtain Cholesky factors is both a necessary and sufficient condition for positive definiteness
    559 	return m.Cholesky_Factor();
    560 }
    561 
    562 /*
    563 ============
    564 idMatX::IsPositiveSemiDefinite
    565 
    566   returns true if the matrix is Positive Semi Definite (PSD)
    567   A square matrix M of order n is said to be PSD if y'My >= 0 for all vectors y of dimension n, y != 0.
    568 ============
    569 */
    570 bool idMatX::IsPositiveSemiDefinite( const float epsilon ) const {
    571 	int i, j, k;
    572 	float d, s;
    573 	idMatX m;
    574 
    575 	// the matrix must be square
    576 	if ( !IsSquare() ) {
    577 		return false;
    578 	}
    579 
    580 	// copy original matrix
    581 	m.SetData( numRows, numColumns, MATX_ALLOCA( numRows * numColumns ) );
    582 	m = *this;
    583 
    584 	// add transpose
    585 	for ( i = 0; i < numRows; i++ ) {
    586 		for ( j = 0; j < numColumns; j++ ) {
    587 			m[i][j] += (*this)[j][i];
    588 		}
    589 	}
    590 
    591 	// test Positive Semi Definiteness with Gaussian pivot steps
    592 	for ( i = 0; i < numRows; i++ ) {
    593 
    594 		for ( j = i; j < numColumns; j++ ) {
    595 			if ( m[j][j] < -epsilon ) {
    596 				return false;
    597 			}
    598 			if ( m[j][j] > epsilon ) {
    599 				continue;
    600 			}
    601 			for ( k = 0; k < numRows; k++ ) {
    602 				if ( idMath::Fabs( m[k][j] ) > epsilon ) {
    603 					return false;
    604 				}
    605 				if ( idMath::Fabs( m[j][k] ) > epsilon ) {
    606 					return false;
    607 				}
    608 			}
    609 		}
    610 
    611 		if ( m[i][i] <= epsilon ) {
    612 			continue;
    613 		}
    614 
    615 		d = 1.0f / m[i][i];
    616 		for ( j = i + 1; j < numColumns; j++ ) {
    617 			s = d * m[j][i];
    618 			m[j][i] = 0.0f;
    619 			for ( k = i + 1; k < numRows; k++ ) {
    620 				m[j][k] -= s * m[i][k];
    621 			}
    622 		}
    623 	}
    624 
    625 	return true;
    626 }
    627 
    628 /*
    629 ============
    630 idMatX::IsSymmetricPositiveSemiDefinite
    631 
    632   returns true if the matrix is Symmetric Positive Semi Definite (PSD)
    633 ============
    634 */
    635 bool idMatX::IsSymmetricPositiveSemiDefinite( const float epsilon ) const {
    636 
    637 	// the matrix must be symmetric
    638 	if ( !IsSymmetric( epsilon ) ) {
    639 		return false;
    640 	}
    641 
    642 	return IsPositiveSemiDefinite( epsilon );
    643 }
    644 
    645 /*
    646 ============
    647 idMatX::LowerTriangularInverse
    648 
    649   in-place inversion of the lower triangular matrix
    650 ============
    651 */
    652 bool idMatX::LowerTriangularInverse() {
    653 	int i, j, k;
    654 	double d, sum;
    655 
    656 	for ( i = 0; i < numRows; i++ ) {
    657 		d = (*this)[i][i];
    658 		if ( d == 0.0f ) {
    659 			return false;
    660 		}
    661 		(*this)[i][i] = d = 1.0f / d;
    662 
    663 		for ( j = 0; j < i; j++ ) {
    664 			sum = 0.0f;
    665 			for ( k = j; k < i; k++ ) {
    666 				sum -= (*this)[i][k] * (*this)[k][j];
    667 			}
    668 			(*this)[i][j] = sum * d;
    669 		}
    670 	}
    671 	return true;
    672 }
    673 
    674 /*
    675 ============
    676 idMatX::UpperTriangularInverse
    677 
    678   in-place inversion of the upper triangular matrix
    679 ============
    680 */
    681 bool idMatX::UpperTriangularInverse() {
    682 	int i, j, k;
    683 	double d, sum;
    684 
    685 	for ( i = numRows-1; i >= 0; i-- ) {
    686 		d = (*this)[i][i];
    687 		if ( d == 0.0f ) {
    688 			return false;
    689 		}
    690 		(*this)[i][i] = d = 1.0f / d;
    691 
    692 		for ( j = numRows-1; j > i; j-- ) {
    693 			sum = 0.0f;
    694 			for ( k = j; k > i; k-- ) {
    695 				sum -= (*this)[i][k] * (*this)[k][j];
    696 			}
    697 			(*this)[i][j] = sum * d;
    698 		}
    699 	}
    700 	return true;
    701 }
    702 
    703 /*
    704 =============
    705 idMatX::ToString
    706 =============
    707 */
    708 const char *idMatX::ToString( int precision ) const {
    709 	return idStr::FloatArrayToString( ToFloatPtr(), GetDimension(), precision );
    710 }
    711 
    712 /*
    713 ============
    714 idMatX::Update_RankOne
    715 
    716   Updates the matrix to obtain the matrix: A + alpha * v * w'
    717 ============
    718 */
    719 void idMatX::Update_RankOne( const idVecX &v, const idVecX &w, float alpha ) {
    720 	int i, j;
    721 	float s;
    722 
    723 	assert( v.GetSize() >= numRows );
    724 	assert( w.GetSize() >= numColumns );
    725 
    726 	for ( i = 0; i < numRows; i++ ) {
    727 		s = alpha * v[i];
    728 		for ( j = 0; j < numColumns; j++ ) {
    729 			(*this)[i][j] += s * w[j];
    730 		}
    731 	}
    732 }
    733 
    734 /*
    735 ============
    736 idMatX::Update_RankOneSymmetric
    737 
    738   Updates the matrix to obtain the matrix: A + alpha * v * v'
    739 ============
    740 */
    741 void idMatX::Update_RankOneSymmetric( const idVecX &v, float alpha ) {
    742 	int i, j;
    743 	float s;
    744 
    745 	assert( numRows == numColumns );
    746 	assert( v.GetSize() >= numRows );
    747 
    748 	for ( i = 0; i < numRows; i++ ) {
    749 		s = alpha * v[i];
    750 		for ( j = 0; j < numColumns; j++ ) {
    751 			(*this)[i][j] += s * v[j];
    752 		}
    753 	}
    754 }
    755 
    756 /*
    757 ============
    758 idMatX::Update_RowColumn
    759 
    760   Updates the matrix to obtain the matrix:
    761 
    762       [ 0  a  0 ]
    763   A + [ d  b  e ]
    764       [ 0  c  0 ]
    765 
    766   where: a = v[0,r-1], b = v[r], c = v[r+1,numRows-1], d = w[0,r-1], w[r] = 0.0f, e = w[r+1,numColumns-1]
    767 ============
    768 */
    769 void idMatX::Update_RowColumn( const idVecX &v, const idVecX &w, int r ) {
    770 	int i;
    771 
    772 	assert( w[r] == 0.0f );
    773 	assert( v.GetSize() >= numColumns );
    774 	assert( w.GetSize() >= numRows );
    775 
    776 	for ( i = 0; i < numRows; i++ ) {
    777 		(*this)[i][r] += v[i];
    778 	}
    779 	for ( i = 0; i < numColumns; i++ ) {
    780 		(*this)[r][i] += w[i];
    781 	}
    782 }
    783 
    784 /*
    785 ============
    786 idMatX::Update_RowColumnSymmetric
    787 
    788   Updates the matrix to obtain the matrix:
    789 
    790       [ 0  a  0 ]
    791   A + [ a  b  c ]
    792       [ 0  c  0 ]
    793 
    794   where: a = v[0,r-1], b = v[r], c = v[r+1,numRows-1]
    795 ============
    796 */
    797 void idMatX::Update_RowColumnSymmetric( const idVecX &v, int r ) {
    798 	int i;
    799 
    800 	assert( numRows == numColumns );
    801 	assert( v.GetSize() >= numRows );
    802 
    803 	for ( i = 0; i < r; i++ ) {
    804 		(*this)[i][r] += v[i];
    805 		(*this)[r][i] += v[i];
    806 	}
    807 	(*this)[r][r] += v[r];
    808 	for ( i = r+1; i < numRows; i++ ) {
    809 		(*this)[i][r] += v[i];
    810 		(*this)[r][i] += v[i];
    811 	}
    812 }
    813 
    814 /*
    815 ============
    816 idMatX::Update_Increment
    817 
    818   Updates the matrix to obtain the matrix:
    819 
    820   [ A  a ]
    821   [ c  b ]
    822 
    823   where: a = v[0,numRows-1], b = v[numRows], c = w[0,numColumns-1]], w[numColumns] = 0
    824 ============
    825 */
    826 void idMatX::Update_Increment( const idVecX &v, const idVecX &w ) {
    827 	int i;
    828 
    829 	assert( numRows == numColumns );
    830 	assert( v.GetSize() >= numRows+1 );
    831 	assert( w.GetSize() >= numColumns+1 );
    832 
    833 	ChangeSize( numRows+1, numColumns+1, false );
    834 
    835 	for ( i = 0; i < numRows; i++ ) {
    836 		(*this)[i][numColumns-1] = v[i];
    837 	}
    838 	for ( i = 0; i < numColumns-1; i++ ) {
    839 		(*this)[numRows-1][i] = w[i];
    840 	}
    841 }
    842 
    843 /*
    844 ============
    845 idMatX::Update_IncrementSymmetric
    846 
    847   Updates the matrix to obtain the matrix:
    848 
    849   [ A  a ]
    850   [ a  b ]
    851 
    852   where: a = v[0,numRows-1], b = v[numRows]
    853 ============
    854 */
    855 void idMatX::Update_IncrementSymmetric( const idVecX &v ) {
    856 	int i;
    857 
    858 	assert( numRows == numColumns );
    859 	assert( v.GetSize() >= numRows+1 );
    860 
    861 	ChangeSize( numRows+1, numColumns+1, false );
    862 
    863 	for ( i = 0; i < numRows-1; i++ ) {
    864 		(*this)[i][numColumns-1] = v[i];
    865 	}
    866 	for ( i = 0; i < numColumns; i++ ) {
    867 		(*this)[numRows-1][i] = v[i];
    868 	}
    869 }
    870 
    871 /*
    872 ============
    873 idMatX::Update_Decrement
    874 
    875   Updates the matrix to obtain a matrix with row r and column r removed.
    876 ============
    877 */
    878 void idMatX::Update_Decrement( int r ) {
    879 	RemoveRowColumn( r );
    880 }
    881 
    882 /*
    883 ============
    884 idMatX::Inverse_GaussJordan
    885 
    886   in-place inversion using Gauss-Jordan elimination
    887 ============
    888 */
    889 bool idMatX::Inverse_GaussJordan() {
    890 	int i, j, k, r, c;
    891 	float d, max;
    892 
    893 	assert( numRows == numColumns );
    894 
    895 	int *columnIndex = (int *) _alloca16( numRows * sizeof( int ) );
    896 	int *rowIndex = (int *) _alloca16( numRows * sizeof( int ) );
    897 	bool *pivot = (bool *) _alloca16( numRows * sizeof( bool ) );
    898 
    899 	memset( pivot, 0, numRows * sizeof( bool ) );
    900 
    901 	// elimination with full pivoting
    902 	for ( i = 0; i < numRows; i++ ) {
    903 
    904 		// search the whole matrix except for pivoted rows for the maximum absolute value
    905 		max = 0.0f;
    906 		r = c = 0;
    907 		for ( j = 0; j < numRows; j++ ) {
    908 			if ( !pivot[j] ) {
    909 				for ( k = 0; k < numRows; k++ ) {
    910 					if ( !pivot[k] ) {
    911 						d = idMath::Fabs( (*this)[j][k] );
    912 						if ( d > max ) {
    913 							max = d;
    914 							r = j;
    915 							c = k;
    916 						}
    917 					}
    918 				}
    919 			}
    920 		}
    921 
    922 		if ( max == 0.0f ) {
    923 			// matrix is not invertible
    924 			return false;
    925 		}
    926 
    927 		pivot[c] = true;
    928 
    929 		// swap rows such that entry (c,c) has the pivot entry
    930 		if ( r != c ) {
    931 			SwapRows( r, c );
    932 		}
    933 
    934 		// keep track of the row permutation
    935 		rowIndex[i] = r;
    936 		columnIndex[i] = c;
    937 
    938 		// scale the row to make the pivot entry equal to 1
    939 		d = 1.0f / (*this)[c][c];
    940 		(*this)[c][c] = 1.0f;
    941 		for ( k = 0; k < numRows; k++ ) {
    942 			(*this)[c][k] *= d;
    943 		}
    944 
    945 		// zero out the pivot column entries in the other rows
    946 		for ( j = 0; j < numRows; j++ ) {
    947 			if ( j != c ) {
    948 				d = (*this)[j][c];
    949 				(*this)[j][c] = 0.0f;
    950 				for ( k = 0; k < numRows; k++ ) {
    951 					(*this)[j][k] -= (*this)[c][k] * d;
    952 				}
    953 			}
    954 		}
    955 	}
    956 
    957 	// reorder rows to store the inverse of the original matrix
    958 	for ( j = numRows - 1; j >= 0; j-- ) {
    959 		if ( rowIndex[j] != columnIndex[j] ) {
    960 			for ( k = 0; k < numRows; k++ ) {
    961 				d = (*this)[k][rowIndex[j]];
    962 				(*this)[k][rowIndex[j]] = (*this)[k][columnIndex[j]];
    963 				(*this)[k][columnIndex[j]] = d;
    964 			}
    965 		}
    966 	}
    967 
    968 	return true;
    969 }
    970 
    971 /*
    972 ============
    973 idMatX::Inverse_UpdateRankOne
    974 
    975   Updates the in-place inverse using the Sherman-Morrison formula to obtain the inverse for the matrix: A + alpha * v * w'
    976 ============
    977 */
    978 bool idMatX::Inverse_UpdateRankOne( const idVecX &v, const idVecX &w, float alpha ) {
    979 	int i, j;
    980 	float beta, s;
    981 	idVecX y, z;
    982 
    983 	assert( numRows == numColumns );
    984 	assert( v.GetSize() >= numColumns );
    985 	assert( w.GetSize() >= numRows );
    986 
    987 	y.SetData( numRows, VECX_ALLOCA( numRows ) );
    988 	z.SetData( numRows, VECX_ALLOCA( numRows ) );
    989 
    990 	Multiply( y, v );
    991 	TransposeMultiply( z, w );
    992 	beta = 1.0f + ( w * y );
    993 
    994 	if ( beta == 0.0f ) {
    995 		return false;
    996 	}
    997 
    998 	alpha /= beta;
    999 
   1000 	for ( i = 0; i < numRows; i++ ) {
   1001 		s = y[i] * alpha;
   1002 		for ( j = 0; j < numColumns; j++ ) {
   1003 			(*this)[i][j] -= s * z[j];
   1004 		}
   1005 	}
   1006 	return true;
   1007 }
   1008 
   1009 /*
   1010 ============
   1011 idMatX::Inverse_UpdateRowColumn
   1012 
   1013   Updates the in-place inverse to obtain the inverse for the matrix:
   1014 
   1015       [ 0  a  0 ]
   1016   A + [ d  b  e ]
   1017       [ 0  c  0 ]
   1018 
   1019   where: a = v[0,r-1], b = v[r], c = v[r+1,numRows-1], d = w[0,r-1], w[r] = 0.0f, e = w[r+1,numColumns-1]
   1020 ============
   1021 */
   1022 bool idMatX::Inverse_UpdateRowColumn( const idVecX &v, const idVecX &w, int r ) {
   1023 	idVecX s;
   1024 
   1025 	assert( numRows == numColumns );
   1026 	assert( v.GetSize() >= numColumns );
   1027 	assert( w.GetSize() >= numRows );
   1028 	assert( r >= 0 && r < numRows && r < numColumns );
   1029 	assert( w[r] == 0.0f );
   1030 
   1031 	s.SetData( Max( numRows, numColumns ), VECX_ALLOCA( Max( numRows, numColumns ) ) );
   1032 	s.Zero();
   1033 	s[r] = 1.0f;
   1034 
   1035 	if ( !Inverse_UpdateRankOne( v, s, 1.0f ) ) {
   1036 		return false;
   1037 	}
   1038 	if ( !Inverse_UpdateRankOne( s, w, 1.0f ) ) {
   1039 		return false;
   1040 	}
   1041 	return true;
   1042 }
   1043 
   1044 /*
   1045 ============
   1046 idMatX::Inverse_UpdateIncrement
   1047 
   1048   Updates the in-place inverse to obtain the inverse for the matrix:
   1049 
   1050   [ A  a ]
   1051   [ c  b ]
   1052 
   1053   where: a = v[0,numRows-1], b = v[numRows], c = w[0,numColumns-1], w[numColumns] = 0
   1054 ============
   1055 */
   1056 bool idMatX::Inverse_UpdateIncrement( const idVecX &v, const idVecX &w ) {
   1057 	idVecX v2;
   1058 
   1059 	assert( numRows == numColumns );
   1060 	assert( v.GetSize() >= numRows+1 );
   1061 	assert( w.GetSize() >= numColumns+1 );
   1062 
   1063 	ChangeSize( numRows+1, numColumns+1, true );
   1064 	(*this)[numRows-1][numRows-1] = 1.0f;
   1065 
   1066 	v2.SetData( numRows, VECX_ALLOCA( numRows ) );
   1067 	v2 = v;
   1068 	v2[numRows-1] -= 1.0f;
   1069 
   1070 	return Inverse_UpdateRowColumn( v2, w, numRows-1 );
   1071 }
   1072 
   1073 /*
   1074 ============
   1075 idMatX::Inverse_UpdateDecrement
   1076 
   1077   Updates the in-place inverse to obtain the inverse of the matrix with row r and column r removed.
   1078   v and w should store the column and row of the original matrix respectively.
   1079 ============
   1080 */
   1081 bool idMatX::Inverse_UpdateDecrement( const idVecX &v, const idVecX &w, int r ) {
   1082 	idVecX v1, w1;
   1083 
   1084 	assert( numRows == numColumns );
   1085 	assert( v.GetSize() >= numRows );
   1086 	assert( w.GetSize() >= numColumns );
   1087 	assert( r >= 0 && r < numRows && r < numColumns );
   1088 
   1089 	v1.SetData( numRows, VECX_ALLOCA( numRows ) );
   1090 	w1.SetData( numRows, VECX_ALLOCA( numRows ) );
   1091 
   1092 	// update the row and column to identity
   1093 	v1 = -v;
   1094 	w1 = -w;
   1095 	v1[r] += 1.0f;
   1096 	w1[r] = 0.0f;
   1097 
   1098 	if ( !Inverse_UpdateRowColumn( v1, w1, r ) ) {
   1099 		return false;
   1100 	}
   1101 
   1102 	// physically remove the row and column
   1103 	Update_Decrement( r );
   1104 
   1105 	return true;
   1106 }
   1107 
   1108 /*
   1109 ============
   1110 idMatX::Inverse_Solve
   1111 
   1112   Solve Ax = b with A inverted
   1113 ============
   1114 */
   1115 void idMatX::Inverse_Solve( idVecX &x, const idVecX &b ) const {
   1116 	Multiply( x, b );
   1117 }
   1118 
   1119 /*
   1120 ============
   1121 idMatX::LU_Factor
   1122 
   1123   in-place factorization: LU
   1124   L is a triangular matrix stored in the lower triangle.
   1125   L has ones on the diagonal that are not stored.
   1126   U is a triangular matrix stored in the upper triangle.
   1127   If index != NULL partial pivoting is used for numerical stability.
   1128   If index != NULL it must point to an array of numRow integers and is used to keep track of the row permutation.
   1129   If det != NULL the determinant of the matrix is calculated and stored.
   1130 ============
   1131 */
   1132 bool idMatX::LU_Factor( int *index, float *det ) {
   1133 	int i, j, k, newi, min;
   1134 	double s, t, d, w;
   1135 
   1136 	// if partial pivoting should be used
   1137 	if ( index ) {
   1138 		for ( i = 0; i < numRows; i++ ) {
   1139 			index[i] = i;
   1140 		}
   1141 	}
   1142 
   1143 	w = 1.0f;
   1144 	min = Min( numRows, numColumns );
   1145 	for ( i = 0; i < min; i++ ) {
   1146 
   1147 		newi = i;
   1148 		s = idMath::Fabs( (*this)[i][i] );
   1149 
   1150 		if ( index ) {
   1151 			// find the largest absolute pivot
   1152 			for ( j = i + 1; j < numRows; j++ ) {
   1153 				t = idMath::Fabs( (*this)[j][i] );
   1154 				if ( t > s ) {
   1155 					newi = j;
   1156 					s = t;
   1157 				}
   1158 			}
   1159 		}
   1160 
   1161 		if ( s == 0.0f ) {
   1162 			return false;
   1163 		}
   1164 
   1165 		if ( newi != i && index ) {
   1166 
   1167 			w = -w;
   1168 
   1169 			// swap index elements
   1170 			k = index[i];
   1171 			index[i] = index[newi];
   1172 			index[newi] = k;
   1173 
   1174 			// swap rows
   1175 			for ( j = 0; j < numColumns; j++ ) {
   1176 				t = (*this)[newi][j];
   1177 				(*this)[newi][j] = (*this)[i][j];
   1178 				(*this)[i][j] = t;
   1179 			}
   1180 		}
   1181 
   1182 		if ( i < numRows ) {
   1183 			d = 1.0f / (*this)[i][i];
   1184 			for ( j = i + 1; j < numRows; j++ ) {
   1185 				(*this)[j][i] *= d;
   1186 			}
   1187 		}
   1188 
   1189 		if ( i < min-1 ) {
   1190 			for ( j = i + 1; j < numRows; j++ ) {
   1191 				d = (*this)[j][i];
   1192 				for ( k = i + 1; k < numColumns; k++ ) {
   1193 					(*this)[j][k] -= d * (*this)[i][k];
   1194 				}
   1195 			}
   1196 		}
   1197 	}
   1198 
   1199 	if ( det ) {
   1200 		for ( i = 0; i < numRows; i++ ) {
   1201 			w *= (*this)[i][i];
   1202 		}
   1203 		*det = w;
   1204 	}
   1205 
   1206 	return true;
   1207 }   
   1208 
   1209 /*
   1210 ============
   1211 idMatX::LU_UpdateRankOne
   1212 
   1213   Updates the in-place LU factorization to obtain the factors for the matrix: LU + alpha * v * w'
   1214 ============
   1215 */
   1216 bool idMatX::LU_UpdateRankOne( const idVecX &v, const idVecX &w, float alpha, int *index ) {
   1217 	int i, j, max;
   1218 	float *y, *z;
   1219 	double diag, beta, p0, p1, d;
   1220 
   1221 	assert( v.GetSize() >= numColumns );
   1222 	assert( w.GetSize() >= numRows );
   1223 
   1224 	y = (float *) _alloca16( v.GetSize() * sizeof( float ) );
   1225 	z = (float *) _alloca16( w.GetSize() * sizeof( float ) );
   1226 
   1227 	if ( index != NULL ) {
   1228 		for ( i = 0; i < numRows; i++ ) {
   1229 			y[i] = alpha * v[index[i]];
   1230 		}
   1231 	} else {
   1232 		for ( i = 0; i < numRows; i++ ) {
   1233 			y[i] = alpha * v[i];
   1234 		}
   1235 	}
   1236 
   1237 	memcpy( z, w.ToFloatPtr(), w.GetSize() * sizeof( float ) );
   1238 
   1239 	max = Min( numRows, numColumns );
   1240 	for ( i = 0; i < max; i++ ) {
   1241 		diag = (*this)[i][i];
   1242 
   1243 		p0 = y[i];
   1244 		p1 = z[i];
   1245 		diag += p0 * p1;
   1246 
   1247 		if ( diag == 0.0f ) {
   1248 			return false;
   1249 		}
   1250 
   1251 		beta = p1 / diag;
   1252 
   1253 		(*this)[i][i] = diag;
   1254 
   1255 		for ( j = i+1; j < numColumns; j++ ) {
   1256 
   1257 			d = (*this)[i][j];
   1258 
   1259 			d += p0 * z[j];
   1260 			z[j] -= beta * d;
   1261 
   1262 			(*this)[i][j] = d;
   1263 		}
   1264 
   1265 		for ( j = i+1; j < numRows; j++ ) {
   1266 
   1267 			d = (*this)[j][i];
   1268 
   1269 			y[j] -= p0 * d;
   1270 			d += beta * y[j];
   1271 
   1272 			(*this)[j][i] = d;
   1273 		}
   1274 	}
   1275 	return true;
   1276 }
   1277 
   1278 /*
   1279 ============
   1280 idMatX::LU_UpdateRowColumn
   1281 
   1282   Updates the in-place LU factorization to obtain the factors for the matrix:
   1283 
   1284        [ 0  a  0 ]
   1285   LU + [ d  b  e ]
   1286        [ 0  c  0 ]
   1287 
   1288   where: a = v[0,r-1], b = v[r], c = v[r+1,numRows-1], d = w[0,r-1], w[r] = 0.0f, e = w[r+1,numColumns-1]
   1289 ============
   1290 */
   1291 bool idMatX::LU_UpdateRowColumn( const idVecX &v, const idVecX &w, int r, int *index ) {
   1292 #if 0
   1293 
   1294 	idVecX s;
   1295 
   1296 	assert( v.GetSize() >= numColumns );
   1297 	assert( w.GetSize() >= numRows );
   1298 	assert( r >= 0 && r < numRows && r < numColumns );
   1299 	assert( w[r] == 0.0f );
   1300 
   1301 	s.SetData( Max( numRows, numColumns ), VECX_ALLOCA( Max( numRows, numColumns ) ) );
   1302 	s.Zero();
   1303 	s[r] = 1.0f;
   1304 
   1305 	if ( !LU_UpdateRankOne( v, s, 1.0f, index ) ) {
   1306 		return false;
   1307 	}
   1308 	if ( !LU_UpdateRankOne( s, w, 1.0f, index ) ) {
   1309 		return false;
   1310 	}
   1311 	return true;
   1312 
   1313 #else
   1314 
   1315 	int i, j, min, max, rp;
   1316 	float *y0, *y1, *z0, *z1;
   1317 	double diag, beta0, beta1, p0, p1, q0, q1, d;
   1318 
   1319 	assert( v.GetSize() >= numColumns );
   1320 	assert( w.GetSize() >= numRows );
   1321 	assert( r >= 0 && r < numColumns && r < numRows );
   1322 	assert( w[r] == 0.0f );
   1323 
   1324 	y0 = (float *) _alloca16( v.GetSize() * sizeof( float ) );
   1325 	z0 = (float *) _alloca16( w.GetSize() * sizeof( float ) );
   1326 	y1 = (float *) _alloca16( v.GetSize() * sizeof( float ) );
   1327 	z1 = (float *) _alloca16( w.GetSize() * sizeof( float ) );
   1328 
   1329 	if ( index != NULL ) {
   1330 		for ( i = 0; i < numRows; i++ ) {
   1331 			y0[i] = v[index[i]];
   1332 		}
   1333 		rp = r;
   1334 		for ( i = 0; i < numRows; i++ ) {
   1335 			if ( index[i] == r ) {
   1336 				rp = i;
   1337 				break;
   1338 			}
   1339 		}
   1340 	} else {
   1341 		memcpy( y0, v.ToFloatPtr(), v.GetSize() * sizeof( float ) );
   1342 		rp = r;
   1343 	}
   1344 
   1345 	memset( y1, 0, v.GetSize() * sizeof( float ) );
   1346 	y1[rp] = 1.0f;
   1347 
   1348 	memset( z0, 0, w.GetSize() * sizeof( float ) );
   1349 	z0[r] = 1.0f;
   1350 
   1351 	memcpy( z1, w.ToFloatPtr(), w.GetSize() * sizeof( float ) );
   1352 
   1353 	// update the beginning of the to be updated row and column
   1354 	min = Min( r, rp );
   1355 	for ( i = 0; i < min; i++ ) {
   1356 		p0 = y0[i];
   1357 		beta1 = z1[i] / (*this)[i][i];
   1358 
   1359 		(*this)[i][r] += p0;
   1360 		for ( j = i+1; j < numColumns; j++ ) {
   1361 			z1[j] -= beta1 * (*this)[i][j];
   1362 		}
   1363 		for ( j = i+1; j < numRows; j++ ) {
   1364 			y0[j] -= p0 * (*this)[j][i];
   1365 		}
   1366 		(*this)[rp][i] += beta1;
   1367 	}
   1368 
   1369 	// update the lower right corner starting at r,r
   1370 	max = Min( numRows, numColumns );
   1371 	for ( i = min; i < max; i++ ) {
   1372 		diag = (*this)[i][i];
   1373 
   1374 		p0 = y0[i];
   1375 		p1 = z0[i];
   1376 		diag += p0 * p1;
   1377 
   1378 		if ( diag == 0.0f ) {
   1379 			return false;
   1380 		}
   1381 
   1382 		beta0 = p1 / diag;
   1383 
   1384 		q0 = y1[i];
   1385 		q1 = z1[i];
   1386 		diag += q0 * q1;
   1387 
   1388 		if ( diag == 0.0f ) {
   1389 			return false;
   1390 		}
   1391 
   1392 		beta1 = q1 / diag;
   1393 
   1394 		(*this)[i][i] = diag;
   1395 
   1396 		for ( j = i+1; j < numColumns; j++ ) {
   1397 
   1398 			d = (*this)[i][j];
   1399 
   1400 			d += p0 * z0[j];
   1401 			z0[j] -= beta0 * d;
   1402 
   1403 			d += q0 * z1[j];
   1404 			z1[j] -= beta1 * d;
   1405 
   1406 			(*this)[i][j] = d;
   1407 		}
   1408 
   1409 		for ( j = i+1; j < numRows; j++ ) {
   1410 
   1411 			d = (*this)[j][i];
   1412 
   1413 			y0[j] -= p0 * d;
   1414 			d += beta0 * y0[j];
   1415 
   1416 			y1[j] -= q0 * d;
   1417 			d += beta1 * y1[j];
   1418 
   1419 			(*this)[j][i] = d;
   1420 		}
   1421 	}
   1422 	return true;
   1423 
   1424 #endif
   1425 }
   1426 
   1427 /*
   1428 ============
   1429 idMatX::LU_UpdateIncrement
   1430 
   1431   Updates the in-place LU factorization to obtain the factors for the matrix:
   1432 
   1433   [ A  a ]
   1434   [ c  b ]
   1435 
   1436   where: a = v[0,numRows-1], b = v[numRows], c = w[0,numColumns-1], w[numColumns] = 0
   1437 ============
   1438 */
   1439 bool idMatX::LU_UpdateIncrement( const idVecX &v, const idVecX &w, int *index ) {
   1440 	int i, j;
   1441 	float sum;
   1442 
   1443 	assert( numRows == numColumns );
   1444 	assert( v.GetSize() >= numRows+1 );
   1445 	assert( w.GetSize() >= numColumns+1 );
   1446 
   1447 	ChangeSize( numRows+1, numColumns+1, true );
   1448 
   1449 	// add row to L
   1450 	for ( i = 0; i < numRows - 1; i++ ) {
   1451 		sum = w[i];
   1452 		for ( j = 0; j < i; j++ ) {
   1453 			sum -= (*this)[numRows - 1][j] * (*this)[j][i];
   1454 		}
   1455 		(*this)[numRows - 1 ][i] = sum / (*this)[i][i];
   1456 	}
   1457 
   1458 	// add row to the permutation index
   1459 	if ( index != NULL ) {
   1460 		index[numRows - 1] = numRows - 1;
   1461 	}
   1462 
   1463 	// add column to U
   1464 	for ( i = 0; i < numRows; i++ ) {
   1465 		if ( index != NULL ) {
   1466 			sum = v[index[i]];
   1467 		} else {
   1468 			sum = v[i];
   1469 		}
   1470 		for ( j = 0; j < i; j++ ) {
   1471 			sum -= (*this)[i][j] * (*this)[j][numRows - 1];
   1472 		}
   1473 		(*this)[i][numRows - 1] = sum;
   1474 	}
   1475 
   1476 	return true;
   1477 }
   1478 
   1479 /*
   1480 ============
   1481 idMatX::LU_UpdateDecrement
   1482 
   1483   Updates the in-place LU factorization to obtain the factors for the matrix with row r and column r removed.
   1484   v and w should store the column and row of the original matrix respectively.
   1485   If index != NULL then u should store row index[r] of the original matrix. If index == NULL then u = w.
   1486 ============
   1487 */
   1488 bool idMatX::LU_UpdateDecrement( const idVecX &v, const idVecX &w, const idVecX &u, int r, int *index ) {
   1489 	int i, p;
   1490 	idVecX v1, w1;
   1491 
   1492 	assert( numRows == numColumns );
   1493 	assert( v.GetSize() >= numColumns );
   1494 	assert( w.GetSize() >= numRows );
   1495 	assert( r >= 0 && r < numRows && r < numColumns );
   1496 
   1497 	v1.SetData( numRows, VECX_ALLOCA( numRows ) );
   1498 	w1.SetData( numRows, VECX_ALLOCA( numRows ) );
   1499 
   1500 	if ( index != NULL ) {
   1501 
   1502 		// find the pivot row
   1503 		for ( p = i = 0; i < numRows; i++ ) {
   1504 			if ( index[i] == r ) {
   1505 				p = i;
   1506 				break;
   1507 			}
   1508 		}
   1509 
   1510 		// update the row and column to identity
   1511 		v1 = -v;
   1512 		w1 = -u;
   1513 
   1514 		if ( p != r ) {
   1515 			SwapValues( v1[index[r]], v1[index[p]] );
   1516 			SwapValues( index[r], index[p] );
   1517 		}
   1518 
   1519 		v1[r] += 1.0f;
   1520 		w1[r] = 0.0f;
   1521 
   1522 		if ( !LU_UpdateRowColumn( v1, w1, r, index ) ) {
   1523 			return false;
   1524 		}
   1525 
   1526 		if ( p != r ) {
   1527 
   1528 			if ( idMath::Fabs( u[p] ) < 1e-4f ) {
   1529 				// NOTE: an additional row interchange is required for numerical stability
   1530 			}
   1531 
   1532 			// move row index[r] of the original matrix to row index[p] of the original matrix
   1533 			v1.Zero();
   1534 			v1[index[p]] = 1.0f;
   1535 			w1 = u - w;
   1536 
   1537 			if ( !LU_UpdateRankOne( v1, w1, 1.0f, index ) ) {
   1538 				return false;
   1539 			}
   1540 		}
   1541 
   1542 		// remove the row from the permutation index
   1543 		for ( i = r; i < numRows - 1; i++ ) {
   1544 			index[i] = index[i+1];
   1545 		}
   1546 		for ( i = 0; i < numRows - 1; i++ ) {
   1547 			if ( index[i] > r ) {
   1548 				index[i]--;
   1549 			}
   1550 		}
   1551 
   1552 	} else {
   1553 
   1554 		v1 = -v;
   1555 		w1 = -w;
   1556 		v1[r] += 1.0f;
   1557 		w1[r] = 0.0f;
   1558 
   1559 		if ( !LU_UpdateRowColumn( v1, w1, r, index ) ) {
   1560 			return false;
   1561 		}
   1562 	}
   1563 
   1564 	// physically remove the row and column
   1565 	Update_Decrement( r );
   1566 
   1567 	return true;
   1568 }
   1569 
   1570 /*
   1571 ============
   1572 idMatX::LU_Solve
   1573 
   1574   Solve Ax = b with A factored in-place as: LU
   1575 ============
   1576 */
   1577 void idMatX::LU_Solve( idVecX &x, const idVecX &b, const int *index ) const {
   1578 	int i, j;
   1579 	double sum;
   1580 
   1581 	assert( x.GetSize() == numColumns && b.GetSize() == numRows );
   1582 
   1583 	// solve L
   1584 	for ( i = 0; i < numRows; i++ ) {
   1585 		if ( index != NULL ) {
   1586 			sum = b[index[i]];
   1587 		} else {
   1588 			sum = b[i];
   1589 		}
   1590 		for ( j = 0; j < i; j++ ) {
   1591 			sum -= (*this)[i][j] * x[j];
   1592 		}
   1593 		x[i] = sum;
   1594 	}
   1595 
   1596 	// solve U
   1597 	for ( i = numRows - 1; i >= 0; i-- ) {
   1598 		sum = x[i];
   1599 		for ( j = i + 1; j < numRows; j++ ) {
   1600 			sum -= (*this)[i][j] * x[j];
   1601 		}
   1602 		x[i] = sum / (*this)[i][i];
   1603 	}
   1604 }
   1605 
   1606 /*
   1607 ============
   1608 idMatX::LU_Inverse
   1609 
   1610   Calculates the inverse of the matrix which is factored in-place as LU
   1611 ============
   1612 */
   1613 void idMatX::LU_Inverse( idMatX &inv, const int *index ) const {
   1614 	int i, j;
   1615 	idVecX x, b;
   1616 
   1617 	assert( numRows == numColumns );
   1618 
   1619 	x.SetData( numRows, VECX_ALLOCA( numRows ) );
   1620 	b.SetData( numRows, VECX_ALLOCA( numRows ) );
   1621 	b.Zero();
   1622 	inv.SetSize( numRows, numColumns );
   1623 
   1624 	for ( i = 0; i < numRows; i++ ) {
   1625 
   1626 		b[i] = 1.0f;
   1627 		LU_Solve( x, b, index );
   1628 		for ( j = 0; j < numRows; j++ ) {
   1629 			inv[j][i] = x[j];
   1630 		}
   1631 		b[i] = 0.0f;
   1632 	}
   1633 }
   1634 
   1635 /*
   1636 ============
   1637 idMatX::LU_UnpackFactors
   1638 
   1639   Unpacks the in-place LU factorization.
   1640 ============
   1641 */
   1642 void idMatX::LU_UnpackFactors( idMatX &L, idMatX &U ) const {
   1643 	int i, j;
   1644 
   1645 	L.Zero( numRows, numColumns );
   1646 	U.Zero( numRows, numColumns );
   1647 	for ( i = 0; i < numRows; i++ ) {
   1648 		for ( j = 0; j < i; j++ ) {
   1649 			L[i][j] = (*this)[i][j];
   1650 		}
   1651 		L[i][i] = 1.0f;
   1652 		for ( j = i; j < numColumns; j++ ) {
   1653 			U[i][j] = (*this)[i][j];
   1654 		}
   1655 	}
   1656 }
   1657 
   1658 /*
   1659 ============
   1660 idMatX::LU_MultiplyFactors
   1661 
   1662   Multiplies the factors of the in-place LU factorization to form the original matrix.
   1663 ============
   1664 */
   1665 void idMatX::LU_MultiplyFactors( idMatX &m, const int *index ) const {
   1666 	int r, rp, i, j;
   1667 	double sum;
   1668 
   1669 	m.SetSize( numRows, numColumns );
   1670 
   1671 	for ( r = 0; r < numRows; r++ ) {
   1672 
   1673 		if ( index != NULL ) {
   1674 			rp = index[r];
   1675 		} else {
   1676 			rp = r;
   1677 		}
   1678 
   1679 		// calculate row of matrix
   1680 		for ( i = 0; i < numColumns; i++ ) {
   1681 			if ( i >= r ) {
   1682 				sum = (*this)[r][i];
   1683 			} else {
   1684 				sum = 0.0f;
   1685 			}
   1686 			for ( j = 0; j <= i && j < r; j++ ) {
   1687 				sum += (*this)[r][j] * (*this)[j][i];
   1688 			}
   1689 			m[rp][i] = sum;
   1690 		}
   1691 	}
   1692 }
   1693 
   1694 /*
   1695 ============
   1696 idMatX::QR_Factor
   1697 
   1698   in-place factorization: QR
   1699   Q is an orthogonal matrix represented as a product of Householder matrices stored in the lower triangle and c.
   1700   R is a triangular matrix stored in the upper triangle except for the diagonal elements which are stored in d.
   1701   The initial matrix has to be square.
   1702 ============
   1703 */
   1704 bool idMatX::QR_Factor( idVecX &c, idVecX &d ) {
   1705 	int i, j, k;
   1706 	double scale, s, t, sum;
   1707 	bool singular = false;
   1708 
   1709 	assert( numRows == numColumns );
   1710 	assert( c.GetSize() >= numRows && d.GetSize() >= numRows );
   1711 
   1712 	for ( k = 0; k < numRows-1; k++ ) {
   1713 
   1714 		scale = 0.0f;
   1715 		for ( i = k; i < numRows; i++ ) {
   1716 			s = idMath::Fabs( (*this)[i][k] );
   1717 			if ( s > scale ) {
   1718 				scale = s;
   1719 			}
   1720 		}
   1721 		if ( scale == 0.0f ) {
   1722 			singular = true;
   1723 			c[k] = d[k] = 0.0f;
   1724 		} else {
   1725 
   1726 			s = 1.0f / scale;
   1727 			for ( i = k; i < numRows; i++ ) {
   1728 				(*this)[i][k] *= s;
   1729 			}
   1730 
   1731 			sum = 0.0f;
   1732 			for ( i = k; i < numRows; i++ ) {
   1733 				s = (*this)[i][k];
   1734 				sum += s * s;
   1735 			}
   1736 
   1737 			s = idMath::Sqrt( sum );
   1738 			if ( (*this)[k][k] < 0.0f ) {
   1739 				s = -s;
   1740 			}
   1741 			(*this)[k][k] += s;
   1742 			c[k] = s * (*this)[k][k];
   1743 			d[k] = -scale * s;
   1744 
   1745 			for ( j = k+1; j < numRows; j++ ) {
   1746 
   1747 				sum = 0.0f;
   1748 				for ( i = k; i < numRows; i++ ) {
   1749 					sum += (*this)[i][k] * (*this)[i][j];
   1750 				}
   1751 				t = sum / c[k];
   1752 				for ( i = k; i < numRows; i++ ) {
   1753 					(*this)[i][j] -= t * (*this)[i][k];
   1754 				}
   1755 			}
   1756 		}
   1757 	}
   1758 	d[numRows-1] = (*this)[ (numRows-1) ][ (numRows-1) ];
   1759 	if ( d[numRows-1] == 0.0f ) {
   1760 		singular = true;
   1761 	}
   1762 
   1763 	return !singular;
   1764 }
   1765 
   1766 /*
   1767 ============
   1768 idMatX::QR_Rotate
   1769 
   1770   Performs a Jacobi rotation on the rows i and i+1 of the unpacked QR factors.
   1771 ============
   1772 */
   1773 void idMatX::QR_Rotate( idMatX &R, int i, float a, float b ) {
   1774 	int j;
   1775 	float f, c, s, w, y;
   1776 
   1777 	if ( a == 0.0f ) {
   1778 		c = 0.0f;
   1779 		s = ( b >= 0.0f ) ? 1.0f : -1.0f;
   1780 	} else if ( idMath::Fabs( a ) > idMath::Fabs( b ) ) {
   1781 		f = b / a;
   1782 		c = idMath::Fabs( 1.0f / idMath::Sqrt( 1.0f + f * f ) );
   1783 		if ( a < 0.0f ) {
   1784 			c = -c;
   1785 		}
   1786 		s = f * c;
   1787 	} else {
   1788 		f = a / b;
   1789 		s = idMath::Fabs( 1.0f / idMath::Sqrt( 1.0f + f * f ) );
   1790 		if ( b < 0.0f ) {
   1791 			s = -s;
   1792 		}
   1793 		c = f * s;
   1794 	}
   1795 	for ( j = i; j < numRows; j++ ) {
   1796 		y = R[i][j];
   1797 		w = R[i+1][j];
   1798 		R[i][j] = c * y - s * w;
   1799 		R[i+1][j] = s * y + c * w;
   1800 	}
   1801 	for ( j = 0; j < numRows; j++ ) {
   1802 		y = (*this)[j][i];
   1803 		w = (*this)[j][i+1];
   1804 		(*this)[j][i] = c * y - s * w;
   1805 		(*this)[j][i+1] = s * y + c * w;
   1806 	}
   1807 }
   1808 
   1809 /*
   1810 ============
   1811 idMatX::QR_UpdateRankOne
   1812 
   1813   Updates the unpacked QR factorization to obtain the factors for the matrix: QR + alpha * v * w'
   1814 ============
   1815 */
   1816 bool idMatX::QR_UpdateRankOne( idMatX &R, const idVecX &v, const idVecX &w, float alpha ) {
   1817 	int i, k;
   1818 	float f;
   1819 	idVecX u;
   1820 
   1821 	assert( v.GetSize() >= numColumns );
   1822 	assert( w.GetSize() >= numRows );
   1823 
   1824 	u.SetData( v.GetSize(), VECX_ALLOCA( v.GetSize() ) );
   1825 	TransposeMultiply( u, v );
   1826 	u *= alpha;
   1827 
   1828 	for ( k = v.GetSize()-1; k > 0; k-- ) {
   1829 		if ( u[k] != 0.0f ) {
   1830 			break;
   1831 		}
   1832 	}
   1833 	for ( i = k-1; i >= 0; i-- ) {
   1834 		QR_Rotate( R, i, u[i], -u[i+1] );
   1835 		if ( u[i] == 0.0f ) {
   1836 			u[i] = idMath::Fabs( u[i+1] );
   1837 		} else if ( idMath::Fabs( u[i] ) > idMath::Fabs( u[i+1] ) ) {
   1838 			f = u[i+1] / u[i];
   1839 			u[i] = idMath::Fabs( u[i] ) * idMath::Sqrt( 1.0f + f * f );
   1840 		} else {
   1841 			f = u[i] / u[i+1];
   1842 			u[i] = idMath::Fabs( u[i+1] ) * idMath::Sqrt( 1.0f + f * f );
   1843 		}
   1844 	}
   1845 	for ( i = 0; i < v.GetSize(); i++ ) {
   1846 		R[0][i] += u[0] * w[i];
   1847 	}
   1848 	for ( i = 0; i < k; i++ ) {
   1849 		QR_Rotate( R, i, -R[i][i], R[i+1][i] );
   1850 	}
   1851 	return true;
   1852 }
   1853 
   1854 /*
   1855 ============
   1856 idMatX::QR_UpdateRowColumn
   1857 
   1858   Updates the unpacked QR factorization to obtain the factors for the matrix:
   1859 
   1860        [ 0  a  0 ]
   1861   QR + [ d  b  e ]
   1862        [ 0  c  0 ]
   1863 
   1864   where: a = v[0,r-1], b = v[r], c = v[r+1,numRows-1], d = w[0,r-1], w[r] = 0.0f, e = w[r+1,numColumns-1]
   1865 ============
   1866 */
   1867 bool idMatX::QR_UpdateRowColumn( idMatX &R, const idVecX &v, const idVecX &w, int r ) {
   1868 	idVecX s;
   1869 
   1870 	assert( v.GetSize() >= numColumns );
   1871 	assert( w.GetSize() >= numRows );
   1872 	assert( r >= 0 && r < numRows && r < numColumns );
   1873 	assert( w[r] == 0.0f );
   1874 
   1875 	s.SetData( Max( numRows, numColumns ), VECX_ALLOCA( Max( numRows, numColumns ) ) );
   1876 	s.Zero();
   1877 	s[r] = 1.0f;
   1878 
   1879 	if ( !QR_UpdateRankOne( R, v, s, 1.0f ) ) {
   1880 		return false;
   1881 	}
   1882 	if ( !QR_UpdateRankOne( R, s, w, 1.0f ) ) {
   1883 		return false;
   1884 	}
   1885 	return true;
   1886 }
   1887 
   1888 /*
   1889 ============
   1890 idMatX::QR_UpdateIncrement
   1891 
   1892   Updates the unpacked QR factorization to obtain the factors for the matrix:
   1893 
   1894   [ A  a ]
   1895   [ c  b ]
   1896 
   1897   where: a = v[0,numRows-1], b = v[numRows], c = w[0,numColumns-1], w[numColumns] = 0
   1898 ============
   1899 */
   1900 bool idMatX::QR_UpdateIncrement( idMatX &R, const idVecX &v, const idVecX &w ) {
   1901 	idVecX v2;
   1902 
   1903 	assert( numRows == numColumns );
   1904 	assert( v.GetSize() >= numRows+1 );
   1905 	assert( w.GetSize() >= numColumns+1 );
   1906 
   1907 	ChangeSize( numRows+1, numColumns+1, true );
   1908 	(*this)[numRows-1][numRows-1] = 1.0f;
   1909 
   1910 	R.ChangeSize( R.numRows+1, R.numColumns+1, true );
   1911 	R[R.numRows-1][R.numRows-1] = 1.0f;
   1912 
   1913 	v2.SetData( numRows, VECX_ALLOCA( numRows ) );
   1914 	v2 = v;
   1915 	v2[numRows-1] -= 1.0f;
   1916 
   1917 	return QR_UpdateRowColumn( R, v2, w, numRows-1 );
   1918 }
   1919 
   1920 /*
   1921 ============
   1922 idMatX::QR_UpdateDecrement
   1923 
   1924   Updates the unpacked QR factorization to obtain the factors for the matrix with row r and column r removed.
   1925   v and w should store the column and row of the original matrix respectively.
   1926 ============
   1927 */
   1928 bool idMatX::QR_UpdateDecrement( idMatX &R, const idVecX &v, const idVecX &w, int r ) {
   1929 	idVecX v1, w1;
   1930 
   1931 	assert( numRows == numColumns );
   1932 	assert( v.GetSize() >= numRows );
   1933 	assert( w.GetSize() >= numColumns );
   1934 	assert( r >= 0 && r < numRows && r < numColumns );
   1935 
   1936 	v1.SetData( numRows, VECX_ALLOCA( numRows ) );
   1937 	w1.SetData( numRows, VECX_ALLOCA( numRows ) );
   1938 
   1939 	// update the row and column to identity
   1940 	v1 = -v;
   1941 	w1 = -w;
   1942 	v1[r] += 1.0f;
   1943 	w1[r] = 0.0f;
   1944 
   1945 	if ( !QR_UpdateRowColumn( R, v1, w1, r ) ) {
   1946 		return false;
   1947 	}
   1948 
   1949 	// physically remove the row and column
   1950 	Update_Decrement( r );
   1951 	R.Update_Decrement( r );
   1952 
   1953 	return true;
   1954 }
   1955 
   1956 /*
   1957 ============
   1958 idMatX::QR_Solve
   1959 
   1960   Solve Ax = b with A factored in-place as: QR
   1961 ============
   1962 */
   1963 void idMatX::QR_Solve( idVecX &x, const idVecX &b, const idVecX &c, const idVecX &d ) const {
   1964 	int i, j;
   1965 	double sum, t;
   1966 
   1967 	assert( numRows == numColumns );
   1968 	assert( x.GetSize() >= numRows && b.GetSize() >= numRows );
   1969 	assert( c.GetSize() >= numRows && d.GetSize() >= numRows );
   1970 
   1971 	for ( i = 0; i < numRows; i++ ) {
   1972 		x[i] = b[i];
   1973 	}
   1974 
   1975 	// multiply b with transpose of Q
   1976 	for ( i = 0; i < numRows-1; i++ ) {
   1977 
   1978 		sum = 0.0f;
   1979 		for ( j = i; j < numRows; j++ ) {
   1980 			sum += (*this)[j][i] * x[j];
   1981 		}
   1982 		t = sum / c[i];
   1983 		for ( j = i; j < numRows; j++ ) {
   1984 			x[j] -= t * (*this)[j][i];
   1985 		}
   1986 	}
   1987 
   1988 	// backsubstitution with R
   1989 	for ( i = numRows-1; i >= 0; i-- ) {
   1990 
   1991 		sum = x[i];
   1992 		for ( j = i + 1; j < numRows; j++ ) {
   1993 			sum -= (*this)[i][j] * x[j];
   1994 		}
   1995 		x[i] = sum / d[i];
   1996 	}
   1997 }
   1998 
   1999 /*
   2000 ============
   2001 idMatX::QR_Solve
   2002 
   2003   Solve Ax = b with A factored as: QR
   2004 ============
   2005 */
   2006 void idMatX::QR_Solve( idVecX &x, const idVecX &b, const idMatX &R ) const {
   2007 	int i, j;
   2008 	double sum;
   2009 
   2010 	assert( numRows == numColumns );
   2011 
   2012 	// multiply b with transpose of Q
   2013 	TransposeMultiply( x, b );
   2014 
   2015 	// backsubstitution with R
   2016 	for ( i = numRows-1; i >= 0; i-- ) {
   2017 
   2018 		sum = x[i];
   2019 		for ( j = i + 1; j < numRows; j++ ) {
   2020 			sum -= R[i][j] * x[j];
   2021 		}
   2022 		x[i] = sum / R[i][i];
   2023 	}
   2024 }
   2025 
   2026 /*
   2027 ============
   2028 idMatX::QR_Inverse
   2029 
   2030   Calculates the inverse of the matrix which is factored in-place as: QR
   2031 ============
   2032 */
   2033 void idMatX::QR_Inverse( idMatX &inv, const idVecX &c, const idVecX &d ) const {
   2034 	int i, j;
   2035 	idVecX x, b;
   2036 
   2037 	assert( numRows == numColumns );
   2038 
   2039 	x.SetData( numRows, VECX_ALLOCA( numRows ) );
   2040 	b.SetData( numRows, VECX_ALLOCA( numRows ) );
   2041 	b.Zero();
   2042 	inv.SetSize( numRows, numColumns );
   2043 
   2044 	for ( i = 0; i < numRows; i++ ) {
   2045 
   2046 		b[i] = 1.0f;
   2047 		QR_Solve( x, b, c, d );
   2048 		for ( j = 0; j < numRows; j++ ) {
   2049 			inv[j][i] = x[j];
   2050 		}
   2051 		b[i] = 0.0f;
   2052 	}
   2053 }
   2054 
   2055 /*
   2056 ============
   2057 idMatX::QR_UnpackFactors
   2058 
   2059   Unpacks the in-place QR factorization.
   2060 ============
   2061 */
   2062 void idMatX::QR_UnpackFactors( idMatX &Q, idMatX &R, const idVecX &c, const idVecX &d ) const {
   2063 	int i, j, k;
   2064 	double sum;
   2065 
   2066 	Q.Identity( numRows, numColumns );
   2067 	for ( i = 0; i < numColumns-1; i++ ) {
   2068 		if ( c[i] == 0.0f ) {
   2069 			continue;
   2070 		}
   2071 		for ( j = 0; j < numRows; j++ ) {
   2072 			sum = 0.0f;
   2073 			for ( k = i; k < numColumns; k++ ) {
   2074 				sum += (*this)[k][i] * Q[j][k];
   2075 			}
   2076 			sum /= c[i];
   2077 			for ( k = i; k < numColumns; k++ ) {
   2078 				Q[j][k] -= sum * (*this)[k][i];
   2079 			}
   2080 		}
   2081 	}
   2082 
   2083 	R.Zero( numRows, numColumns );
   2084 	for ( i = 0; i < numRows; i++ ) {
   2085 		R[i][i] = d[i];
   2086 		for ( j = i+1; j < numColumns; j++ ) {
   2087 			R[i][j] = (*this)[i][j];
   2088 		}
   2089 	}
   2090 }
   2091 
   2092 /*
   2093 ============
   2094 idMatX::QR_MultiplyFactors
   2095 
   2096   Multiplies the factors of the in-place QR factorization to form the original matrix.
   2097 ============
   2098 */
   2099 void idMatX::QR_MultiplyFactors( idMatX &m, const idVecX &c, const idVecX &d ) const {
   2100 	int i, j, k;
   2101 	double sum;
   2102 	idMatX Q;
   2103 
   2104 	Q.Identity( numRows, numColumns );
   2105 	for ( i = 0; i < numColumns-1; i++ ) {
   2106 		if ( c[i] == 0.0f ) {
   2107 			continue;
   2108 		}
   2109 		for ( j = 0; j < numRows; j++ ) {
   2110 			sum = 0.0f;
   2111 			for ( k = i; k < numColumns; k++ ) {
   2112 				sum += (*this)[k][i] * Q[j][k];
   2113 			}
   2114 			sum /= c[i];
   2115 			for ( k = i; k < numColumns; k++ ) {
   2116 				Q[j][k] -= sum * (*this)[k][i];
   2117 			}
   2118 		}
   2119 	}
   2120 
   2121 	for ( i = 0; i < numRows; i++ ) {
   2122 		for ( j = 0; j < numColumns; j++ ) {
   2123 			sum = Q[i][j] * d[i];
   2124 			for ( k = 0; k < i; k++ ) {
   2125 				sum += Q[i][k] * (*this)[j][k];
   2126 			}
   2127 			m[i][j] = sum;
   2128 		}
   2129 	}
   2130 }
   2131 
   2132 /*
   2133 ============
   2134 idMatX::Pythag
   2135 
   2136   Computes (a^2 + b^2)^1/2 without underflow or overflow.
   2137 ============
   2138 */
   2139 float idMatX::Pythag( float a, float b ) const {
   2140 	double at, bt, ct;
   2141 
   2142 	at = idMath::Fabs( a );
   2143 	bt = idMath::Fabs( b );
   2144 	if ( at > bt ) {
   2145 		ct = bt / at;
   2146 		return at * idMath::Sqrt( 1.0f + ct * ct );
   2147 	} else {
   2148 		if ( bt ) {
   2149 			ct = at / bt;
   2150 			return bt * idMath::Sqrt( 1.0f + ct * ct );
   2151 		} else {
   2152 			return 0.0f;
   2153 		}
   2154 	}
   2155 }
   2156 
   2157 /*
   2158 ============
   2159 idMatX::SVD_BiDiag
   2160 ============
   2161 */
   2162 void idMatX::SVD_BiDiag( idVecX &w, idVecX &rv1, float &anorm ) {
   2163 	int i, j, k, l;
   2164 	double f, h, r, g, s, scale;
   2165 
   2166 	anorm = 0.0f;
   2167 	g = s = scale = 0.0f;
   2168 	for ( i = 0; i < numColumns; i++ ) {
   2169 		l = i + 1;
   2170 		rv1[i] = scale * g;
   2171 		g = s = scale = 0.0f;
   2172 		if ( i < numRows ) {
   2173 			for ( k = i; k < numRows; k++ ) {
   2174 				scale += idMath::Fabs( (*this)[k][i] );
   2175 			}
   2176 			if ( scale ) {
   2177 				for ( k = i; k < numRows; k++ ) {
   2178 					(*this)[k][i] /= scale;
   2179 					s += (*this)[k][i] * (*this)[k][i];
   2180 				}
   2181 				f = (*this)[i][i];
   2182 				g = idMath::Sqrt( s );
   2183 				if ( f >= 0.0f ) {
   2184 					g = -g;
   2185 				}
   2186 				h = f * g - s;
   2187 				(*this)[i][i] = f - g;
   2188 				if ( i != (numColumns-1) ) {
   2189 					for ( j = l; j < numColumns; j++ ) {
   2190 						for ( s = 0.0f, k = i; k < numRows; k++ ) {
   2191 							s += (*this)[k][i] * (*this)[k][j];
   2192 						}
   2193 						f = s / h;
   2194 						for ( k = i; k < numRows; k++ ) {
   2195 							(*this)[k][j] += f * (*this)[k][i];
   2196 						}
   2197 					}
   2198 				}
   2199 				for ( k = i; k < numRows; k++ ) {
   2200 					(*this)[k][i] *= scale;
   2201 				}
   2202 			}
   2203 		}
   2204 		w[i] = scale * g;
   2205 		g = s = scale = 0.0f;
   2206 		if ( i < numRows && i != (numColumns-1) ) {
   2207 			for ( k = l; k < numColumns; k++ ) {
   2208 				scale += idMath::Fabs( (*this)[i][k] );
   2209 			}
   2210 			if ( scale ) {
   2211 				for ( k = l; k < numColumns; k++ ) {
   2212 					(*this)[i][k] /= scale;
   2213 					s += (*this)[i][k] * (*this)[i][k];
   2214 				}
   2215 				f = (*this)[i][l];
   2216 				g = idMath::Sqrt( s );
   2217 				if ( f >= 0.0f ) {
   2218 					g = -g;
   2219 				}
   2220 				h = 1.0f / ( f * g - s );
   2221 				(*this)[i][l] = f - g;
   2222 				for ( k = l; k < numColumns; k++ ) {
   2223 					rv1[k] = (*this)[i][k] * h;
   2224 				}
   2225 				if ( i != (numRows-1) ) {
   2226 					for ( j = l; j < numRows; j++ ) {
   2227 						for ( s = 0.0f, k = l; k < numColumns; k++ ) {
   2228 							s += (*this)[j][k] * (*this)[i][k];
   2229 						}
   2230 						for ( k = l; k < numColumns; k++ ) {
   2231 							(*this)[j][k] += s * rv1[k];
   2232 						}
   2233 					}
   2234 				}
   2235 				for ( k = l; k < numColumns; k++ ) {
   2236 					(*this)[i][k] *= scale;
   2237 				}
   2238 			}
   2239 		}
   2240 		r = idMath::Fabs( w[i] ) + idMath::Fabs( rv1[i] );
   2241 		if ( r > anorm ) {
   2242 			anorm = r;
   2243 		}
   2244 	}
   2245 }
   2246 
   2247 /*
   2248 ============
   2249 idMatX::SVD_InitialWV
   2250 ============
   2251 */
   2252 void idMatX::SVD_InitialWV( idVecX &w, idMatX &V, idVecX &rv1 ) {
   2253 	int i, j, k, l;
   2254 	double f, g, s;
   2255 
   2256 	g = 0.0f;
   2257 	for ( i = (numColumns-1); i >= 0; i-- ) {
   2258 		l = i + 1;
   2259 		if ( i < ( numColumns - 1 ) ) {
   2260 			if ( g ) {
   2261 				for ( j = l; j < numColumns; j++ ) {
   2262 					V[j][i] = ((*this)[i][j] / (*this)[i][l]) / g;
   2263 				}
   2264 				// double division to reduce underflow
   2265 				for ( j = l; j < numColumns; j++ ) {
   2266 					for ( s = 0.0f, k = l; k < numColumns; k++ ) {
   2267 						s += (*this)[i][k] * V[k][j];
   2268 					}
   2269 					for ( k = l; k < numColumns; k++ ) {
   2270 						V[k][j] += s * V[k][i];
   2271 					}
   2272 				}
   2273 			}
   2274 			for ( j = l; j < numColumns; j++ ) {
   2275 				V[i][j] = V[j][i] = 0.0f;
   2276 			}
   2277 		}
   2278 		V[i][i] = 1.0f;
   2279 		g = rv1[i];
   2280 	}
   2281 	for ( i = numColumns - 1 ; i >= 0; i-- ) {
   2282 		l = i + 1;
   2283 		g = w[i];
   2284 		if ( i < (numColumns-1) ) {
   2285 			for ( j = l; j < numColumns; j++ ) {
   2286 				(*this)[i][j] = 0.0f;
   2287 			}
   2288 		}
   2289 		if ( g ) {
   2290 			g = 1.0f / g;
   2291 			if ( i != (numColumns-1) ) {
   2292 				for ( j = l; j < numColumns; j++ ) {
   2293 					for ( s = 0.0f, k = l; k < numRows; k++ ) {
   2294 						s += (*this)[k][i] * (*this)[k][j];
   2295 					}
   2296 					f = (s / (*this)[i][i]) * g;
   2297 					for ( k = i; k < numRows; k++ ) {
   2298 						(*this)[k][j] += f * (*this)[k][i];
   2299 					}
   2300 				}
   2301 			}
   2302 			for ( j = i; j < numRows; j++ ) {
   2303 				(*this)[j][i] *= g;
   2304 			}
   2305 		}
   2306 		else {
   2307 			for ( j = i; j < numRows; j++ ) {
   2308 				(*this)[j][i] = 0.0f;
   2309 			}
   2310 		}
   2311 		(*this)[i][i] += 1.0f;
   2312 	}
   2313 }
   2314 
   2315 /*
   2316 ============
   2317 idMatX::SVD_Factor
   2318 
   2319   in-place factorization: U * Diag(w) * V.Transpose()
   2320   known as the Singular Value Decomposition.
   2321   U is a column-orthogonal matrix which overwrites the original matrix.
   2322   w is a diagonal matrix with all elements >= 0 which are the singular values.
   2323   V is the transpose of an orthogonal matrix.
   2324 ============
   2325 */
   2326 bool idMatX::SVD_Factor( idVecX &w, idMatX &V ) {
   2327 	int flag, i, its, j, jj, k, l, nm;
   2328 	double c, f, h, s, x, y, z, r, g = 0.0f;
   2329 	float anorm = 0.0f;
   2330 	idVecX rv1;
   2331 
   2332 	if ( numRows < numColumns ) {
   2333 		return false;
   2334 	}
   2335 
   2336 	rv1.SetData( numColumns, VECX_ALLOCA( numColumns ) );
   2337 	rv1.Zero();
   2338 	w.Zero( numColumns );
   2339 	V.Zero( numColumns, numColumns );
   2340 
   2341 	SVD_BiDiag( w, rv1, anorm );
   2342 	SVD_InitialWV( w, V, rv1 );
   2343 
   2344 	for ( k = numColumns - 1; k >= 0; k-- ) {
   2345 		for ( its = 1; its <= 30; its++ ) {
   2346 			flag = 1;
   2347 			nm = 0;
   2348 			for ( l = k; l >= 0; l-- ) {
   2349 				nm = l - 1;
   2350 				if ( ( idMath::Fabs( rv1[l] ) + anorm ) == anorm /* idMath::Fabs( rv1[l] ) < idMath::FLT_EPSILON */ ) {
   2351 					flag = 0;
   2352 					break;
   2353 				}
   2354 				if ( ( idMath::Fabs( w[nm] ) + anorm ) == anorm /* idMath::Fabs( w[nm] ) < idMath::FLT_EPSILON */ ) {
   2355 					break;
   2356 				}
   2357 			}
   2358 			if ( flag ) {
   2359 				c = 0.0f;
   2360 				s = 1.0f;
   2361 				for ( i = l; i <= k; i++ ) {
   2362 					f = s * rv1[i];
   2363 
   2364 					if ( ( idMath::Fabs( f ) + anorm ) != anorm /* idMath::Fabs( f ) > idMath::FLT_EPSILON */ ) {
   2365 						g = w[i];
   2366 						h = Pythag( f, g );
   2367 						w[i] = h;
   2368 						h = 1.0f / h;
   2369 						c = g * h;
   2370 						s = -f * h;
   2371 						for ( j = 0; j < numRows; j++ ) {
   2372 							y = (*this)[j][nm];
   2373 							z = (*this)[j][i];
   2374 							(*this)[j][nm] = y * c + z * s;
   2375 							(*this)[j][i] = z * c - y * s;
   2376 						}
   2377 					}
   2378 				}
   2379 			}
   2380 			z = w[k];
   2381 			if ( l == k ) {
   2382 				if ( z < 0.0f ) {
   2383 					w[k] = -z;
   2384 					for ( j = 0; j < numColumns; j++ ) {
   2385 						V[j][k] = -V[j][k];
   2386 					}
   2387 				}
   2388 				break;
   2389 			}
   2390 			if ( its == 30 ) {
   2391 				return false;		// no convergence
   2392 			}
   2393 			x = w[l];
   2394 			nm = k - 1;
   2395 			y = w[nm];
   2396 			g = rv1[nm];
   2397 			h = rv1[k];
   2398 			f = ( ( y - z ) * ( y + z ) + ( g - h ) * ( g + h ) ) / ( 2.0f * h * y );
   2399 			g = Pythag( f, 1.0f );
   2400 			r = ( f >= 0.0f ? g : - g );
   2401 			f= ( ( x - z ) * ( x + z ) + h * ( ( y / ( f + r ) ) - h ) ) / x;
   2402 			c = s = 1.0f;
   2403 			for ( j = l; j <= nm; j++ ) {
   2404 				i = j + 1;
   2405 				g = rv1[i];
   2406 				y = w[i];
   2407 				h = s * g;
   2408 				g = c * g;
   2409 				z = Pythag( f, h );
   2410 				rv1[j] = z;
   2411 				c = f / z;
   2412 				s = h / z;
   2413 				f = x * c + g * s;
   2414 				g = g * c - x * s;
   2415 				h = y * s;
   2416 				y = y * c;
   2417 				for ( jj = 0; jj < numColumns; jj++ ) {
   2418 					x = V[jj][j];
   2419 					z = V[jj][i];
   2420 					V[jj][j] = x * c + z * s;
   2421 					V[jj][i] = z * c - x * s;
   2422 				}
   2423 				z = Pythag( f, h );
   2424 				w[j] = z;
   2425 				if ( z ) {
   2426 					z = 1.0f / z;
   2427 					c = f * z;
   2428 					s = h * z;
   2429 				}
   2430 				f = ( c * g ) + ( s * y );
   2431 				x = ( c * y ) - ( s * g );
   2432 				for ( jj = 0; jj < numRows; jj++ ) {
   2433 					y = (*this)[jj][j];
   2434 					z = (*this)[jj][i];
   2435 					(*this)[jj][j] = y * c + z * s;
   2436 					(*this)[jj][i] = z * c - y * s;
   2437 				}
   2438 			}
   2439 			rv1[l] = 0.0f;
   2440 			rv1[k] = f;
   2441 			w[k] = x;
   2442 		}
   2443 	}
   2444 	return true;
   2445 }
   2446 
   2447 /*
   2448 ============
   2449 idMatX::SVD_Solve
   2450 
   2451   Solve Ax = b with A factored as: U * Diag(w) * V.Transpose()
   2452 ============
   2453 */
   2454 void idMatX::SVD_Solve( idVecX &x, const idVecX &b, const idVecX &w, const idMatX &V ) const {
   2455 	int i, j;
   2456 	double sum;
   2457 	idVecX tmp;
   2458 
   2459 	assert( x.GetSize() >= numColumns );
   2460 	assert( b.GetSize() >= numColumns );
   2461 	assert( w.GetSize() == numColumns );
   2462 	assert( V.GetNumRows() == numColumns && V.GetNumColumns() == numColumns );
   2463 
   2464 	tmp.SetData( numColumns, VECX_ALLOCA( numColumns ) );
   2465 
   2466 	for ( i = 0; i < numColumns; i++ ) {
   2467 		sum = 0.0f;
   2468 		if ( w[i] >= idMath::FLT_EPSILON ) {
   2469 			for ( j = 0; j < numRows; j++ ) {
   2470 				sum += (*this)[j][i] * b[j];
   2471 			}
   2472 			sum /= w[i];
   2473 		}
   2474 		tmp[i] = sum;
   2475 	}
   2476 	for ( i = 0; i < numColumns; i++ ) {
   2477 		sum = 0.0f;
   2478 		for ( j = 0; j < numColumns; j++ ) {
   2479 			sum += V[i][j] * tmp[j];
   2480 		}
   2481 		x[i] = sum;
   2482 	}
   2483 }
   2484 
   2485 /*
   2486 ============
   2487 idMatX::SVD_Inverse
   2488 
   2489   Calculates the inverse of the matrix which is factored in-place as: U * Diag(w) * V.Transpose()
   2490 ============
   2491 */
   2492 void idMatX::SVD_Inverse( idMatX &inv, const idVecX &w, const idMatX &V ) const {
   2493 	int i, j, k;
   2494 	double wi, sum;
   2495 	idMatX V2;
   2496 
   2497 	assert( numRows == numColumns );
   2498 
   2499 	V2 = V;
   2500 
   2501 	// V * [diag(1/w[i])]
   2502 	for ( i = 0; i < numRows; i++ ) {
   2503 		wi = w[i];
   2504 		wi = ( wi < idMath::FLT_EPSILON ) ? 0.0f : 1.0f / wi;
   2505 		for ( j = 0; j < numColumns; j++ ) {
   2506 			V2[j][i] *= wi;
   2507 		}
   2508 	}
   2509 
   2510 	// V * [diag(1/w[i])] * Ut
   2511 	for ( i = 0; i < numRows; i++ ) {
   2512 		for ( j = 0; j < numColumns; j++ ) {
   2513 			sum = V2[i][0] * (*this)[j][0];
   2514 			for ( k = 1; k < numColumns; k++ ) {
   2515 				sum += V2[i][k] * (*this)[j][k];
   2516 			}
   2517 			inv[i][j] = sum;
   2518 		}
   2519 	}
   2520 }
   2521 
   2522 /*
   2523 ============
   2524 idMatX::SVD_MultiplyFactors
   2525 
   2526   Multiplies the factors of the in-place SVD factorization to form the original matrix.
   2527 ============
   2528 */
   2529 void idMatX::SVD_MultiplyFactors( idMatX &m, const idVecX &w, const idMatX &V ) const {
   2530 	int r, i, j;
   2531 	double sum;
   2532 
   2533 	m.SetSize( numRows, V.GetNumRows() );
   2534 
   2535 	for ( r = 0; r < numRows; r++ ) {
   2536 		// calculate row of matrix
   2537 		if ( w[r] >= idMath::FLT_EPSILON ) {
   2538 			for ( i = 0; i < V.GetNumRows(); i++ ) {
   2539 				sum = 0.0f;
   2540 				for ( j = 0; j < numColumns; j++ ) {
   2541 					sum += (*this)[r][j] * V[i][j];
   2542 				}
   2543 				m[r][i] = sum * w[r];
   2544 			}
   2545 		} else {
   2546 			for ( i = 0; i < V.GetNumRows(); i++ ) {
   2547 				m[r][i] = 0.0f;
   2548 			}
   2549 		}
   2550 	}
   2551 }
   2552 
   2553 /*
   2554 ============
   2555 idMatX::Cholesky_Factor
   2556 
   2557   in-place Cholesky factorization: LL'
   2558   L is a triangular matrix stored in the lower triangle.
   2559   The upper triangle is not cleared.
   2560   The initial matrix has to be symmetric positive definite.
   2561 ============
   2562 */
   2563 bool idMatX::Cholesky_Factor() {
   2564 	int i, j, k;
   2565 	float *invSqrt;
   2566 	double sum;
   2567 
   2568 	assert( numRows == numColumns );
   2569 
   2570 	invSqrt = (float *) _alloca16( numRows * sizeof( float ) );
   2571 
   2572 	for ( i = 0; i < numRows; i++ ) {
   2573 
   2574 		for ( j = 0; j < i; j++ ) {
   2575 
   2576 			sum = (*this)[i][j];
   2577 			for ( k = 0; k < j; k++ ) {
   2578 				sum -= (*this)[i][k] * (*this)[j][k];
   2579 			}
   2580 			(*this)[i][j] = sum * invSqrt[j];
   2581 		}
   2582 
   2583 		sum = (*this)[i][i];
   2584 		for ( k = 0; k < i; k++ ) {
   2585 			sum -= (*this)[i][k] * (*this)[i][k];
   2586 		}
   2587 
   2588 		if ( sum <= 0.0f ) {
   2589 			return false;
   2590 		}
   2591 
   2592 		invSqrt[i] = idMath::InvSqrt( sum );
   2593 		(*this)[i][i] = invSqrt[i] * sum;
   2594 	}
   2595 	return true;
   2596 }
   2597 
   2598 /*
   2599 ============
   2600 idMatX::Cholesky_UpdateRankOne
   2601 
   2602   Updates the in-place Cholesky factorization to obtain the factors for the matrix: LL' + alpha * v * v'
   2603   If offset > 0 only the lower right corner starting at (offset, offset) is updated.
   2604 ============
   2605 */
   2606 bool idMatX::Cholesky_UpdateRankOne( const idVecX &v, float alpha, int offset ) {
   2607 	int i, j;
   2608 	float *y;
   2609 	double diag, invDiag, diagSqr, newDiag, newDiagSqr, beta, p, d;
   2610 
   2611 	assert( numRows == numColumns );
   2612 	assert( v.GetSize() >= numRows );
   2613 	assert( offset >= 0 && offset < numRows );
   2614 
   2615 	y = (float *) _alloca16( v.GetSize() * sizeof( float ) );
   2616 	memcpy( y, v.ToFloatPtr(), v.GetSize() * sizeof( float ) );
   2617 
   2618 	for ( i = offset; i < numColumns; i++ ) {
   2619 		p = y[i];
   2620 		diag = (*this)[i][i];
   2621 		invDiag = 1.0f / diag;
   2622 		diagSqr = diag * diag;
   2623 		newDiagSqr = diagSqr + alpha * p * p;
   2624 
   2625 		if ( newDiagSqr <= 0.0f ) {
   2626 			return false;
   2627 		}
   2628 
   2629 		(*this)[i][i] = newDiag = idMath::Sqrt( newDiagSqr );
   2630 
   2631 		alpha /= newDiagSqr;
   2632 		beta = p * alpha;
   2633 		alpha *= diagSqr;
   2634 
   2635 		for ( j = i+1; j < numRows; j++ ) {
   2636 
   2637 			d = (*this)[j][i] * invDiag;
   2638 
   2639 			y[j] -= p * d;
   2640 			d += beta * y[j];
   2641 
   2642 			(*this)[j][i] = d * newDiag;
   2643 		}
   2644 	}
   2645 	return true;
   2646 }
   2647 
   2648 /*
   2649 ============
   2650 idMatX::Cholesky_UpdateRowColumn
   2651 
   2652   Updates the in-place Cholesky factorization to obtain the factors for the matrix:
   2653 
   2654         [ 0  a  0 ]
   2655   LL' + [ a  b  c ]
   2656         [ 0  c  0 ]
   2657 
   2658   where: a = v[0,r-1], b = v[r], c = v[r+1,numRows-1]
   2659 ============
   2660 */
   2661 bool idMatX::Cholesky_UpdateRowColumn( const idVecX &v, int r ) {
   2662 	int i, j;
   2663 	double sum;
   2664 	float *original, *y;
   2665 	idVecX addSub;
   2666 
   2667 	assert( numRows == numColumns );
   2668 	assert( v.GetSize() >= numRows );
   2669 	assert( r >= 0 && r < numRows );
   2670 
   2671 	addSub.SetData( numColumns, (float *) _alloca16( numColumns * sizeof( float ) ) );
   2672 
   2673 	if ( r == 0 ) {
   2674 
   2675 		if ( numColumns == 1 ) {
   2676 			double v0 = v[0];
   2677 			sum = (*this)[0][0];
   2678 			sum = sum * sum; 
   2679 			sum = sum + v0; 
   2680 			if ( sum <= 0.0f ) {
   2681 				return false;
   2682 			}
   2683 			(*this)[0][0] = idMath::Sqrt( sum );
   2684 			return true;
   2685 		}
   2686 		for ( i = 0; i < numColumns; i++ ) {
   2687 			addSub[i] = v[i];
   2688 		}
   2689 
   2690 	} else {
   2691 
   2692 		original = (float *) _alloca16( numColumns * sizeof( float ) );
   2693 		y = (float *) _alloca16( numColumns * sizeof( float ) );
   2694 
   2695 		// calculate original row/column of matrix
   2696 		for ( i = 0; i < numRows; i++ ) {
   2697 			sum = 0.0f;
   2698 			for ( j = 0; j <= i; j++ ) {
   2699 				sum += (*this)[r][j] * (*this)[i][j];
   2700 			}
   2701 			original[i] = sum;
   2702 		}
   2703 
   2704 		// solve for y in L * y = original + v
   2705 		for ( i = 0; i < r; i++ ) {
   2706 			sum = original[i] + v[i];
   2707 			for ( j = 0; j < i; j++ ) {
   2708 				sum -= (*this)[r][j] * (*this)[i][j];
   2709 			}
   2710 			(*this)[r][i] = sum / (*this)[i][i];
   2711 		}
   2712 
   2713 		// if the last row/column of the matrix is updated
   2714 		if ( r == numColumns - 1 ) {
   2715 			// only calculate new diagonal
   2716 			sum = original[r] + v[r];
   2717 			for ( j = 0; j < r; j++) {
   2718 				sum -= (*this)[r][j] * (*this)[r][j];
   2719 			}
   2720 			if ( sum <= 0.0f ) {
   2721 				return false;
   2722 			}
   2723 			(*this)[r][r] = idMath::Sqrt( sum );
   2724 			return true;
   2725 		}
   2726 
   2727 		// calculate the row/column to be added to the lower right sub matrix starting at (r, r)
   2728 		for ( i = r; i < numColumns; i++ ) {
   2729 			sum = 0.0f;
   2730 			for ( j = 0; j <= r; j++ ) {
   2731 				sum += (*this)[r][j] * (*this)[i][j];
   2732 			}
   2733 			addSub[i] = v[i] - ( sum - original[i] );
   2734 		}
   2735 	}
   2736 
   2737 	// add row/column to the lower right sub matrix starting at (r, r)
   2738 
   2739 #if 0
   2740 
   2741 	idVecX v1, v2;
   2742 	double d;
   2743 
   2744 	v1.SetData( numColumns, (float *) _alloca16( numColumns * sizeof( float ) ) );
   2745 	v2.SetData( numColumns, (float *) _alloca16( numColumns * sizeof( float ) ) );
   2746 
   2747 	d = idMath::SQRT_1OVER2;
   2748 	v1[r] = ( 0.5f * addSub[r] + 1.0f ) * d;
   2749 	v2[r] = ( 0.5f * addSub[r] - 1.0f ) * d;
   2750 	for ( i = r+1; i < numColumns; i++ ) {
   2751 		v1[i] = v2[i] = addSub[i] * d;
   2752 	}
   2753 
   2754 	// update
   2755 	if ( !Cholesky_UpdateRankOne( v1, 1.0f, r ) ) {
   2756 		return false;
   2757 	}
   2758 	// downdate
   2759 	if ( !Cholesky_UpdateRankOne( v2, -1.0f, r ) ) {
   2760 		return false;
   2761 	}
   2762 
   2763 #else
   2764 
   2765 	float *v1, *v2;
   2766 	double diag, invDiag, diagSqr, newDiag, newDiagSqr;
   2767 	double alpha1, alpha2, beta1, beta2, p1, p2, d;
   2768 
   2769 	v1 = (float *) _alloca16( numColumns * sizeof( float ) );
   2770 	v2 = (float *) _alloca16( numColumns * sizeof( float ) );
   2771 
   2772 	d = idMath::SQRT_1OVER2;
   2773 	v1[r] = ( 0.5f * addSub[r] + 1.0f ) * d;
   2774 	v2[r] = ( 0.5f * addSub[r] - 1.0f ) * d;
   2775 	for ( i = r+1; i < numColumns; i++ ) {
   2776 		v1[i] = v2[i] = addSub[i] * d;
   2777 	}
   2778 
   2779 	alpha1 = 1.0f;
   2780 	alpha2 = -1.0f;
   2781 
   2782 	// simultaneous update/downdate of the sub matrix starting at (r, r)
   2783 	for ( i = r; i < numColumns; i++ ) {
   2784 		p1 = v1[i];
   2785 		diag = (*this)[i][i];
   2786 		invDiag = 1.0f / diag;
   2787 		diagSqr = diag * diag;
   2788 		newDiagSqr = diagSqr + alpha1 * p1 * p1;
   2789 
   2790 		if ( newDiagSqr <= 0.0f ) {
   2791 			return false;
   2792 		}
   2793 
   2794 		alpha1 /= newDiagSqr;
   2795 		beta1 = p1 * alpha1;
   2796 		alpha1 *= diagSqr;
   2797 
   2798 		p2 = v2[i];
   2799 		diagSqr = newDiagSqr;
   2800 		newDiagSqr = diagSqr + alpha2 * p2 * p2;
   2801 
   2802 		if ( newDiagSqr <= 0.0f ) {
   2803 			return false;
   2804 		}
   2805 
   2806 		(*this)[i][i] = newDiag = idMath::Sqrt( newDiagSqr );
   2807 
   2808 		alpha2 /= newDiagSqr;
   2809 		beta2 = p2 * alpha2;
   2810 		alpha2 *= diagSqr;
   2811 
   2812 		for ( j = i+1; j < numRows; j++ ) {
   2813 
   2814 			d = (*this)[j][i] * invDiag;
   2815 
   2816 			v1[j] -= p1 * d;
   2817 			d += beta1 * v1[j];
   2818 
   2819 			v2[j] -= p2 * d;
   2820 			d += beta2 * v2[j];
   2821 
   2822 			(*this)[j][i] = d * newDiag;
   2823 		}
   2824 	}
   2825 
   2826 #endif
   2827 
   2828 	return true;
   2829 }
   2830 
   2831 /*
   2832 ============
   2833 idMatX::Cholesky_UpdateIncrement
   2834 
   2835   Updates the in-place Cholesky factorization to obtain the factors for the matrix:
   2836 
   2837   [ A  a ]
   2838   [ a  b ]
   2839 
   2840   where: a = v[0,numRows-1], b = v[numRows]
   2841 ============
   2842 */
   2843 bool idMatX::Cholesky_UpdateIncrement( const idVecX &v ) {
   2844 	int i, j;
   2845 	float *x;
   2846 	double sum;
   2847 
   2848 	assert( numRows == numColumns );
   2849 	assert( v.GetSize() >= numRows+1 );
   2850 
   2851 	ChangeSize( numRows+1, numColumns+1, false );
   2852 
   2853 	x = (float *) _alloca16( numRows * sizeof( float ) );
   2854 
   2855 	// solve for x in L * x = v
   2856 	for ( i = 0; i < numRows - 1; i++ ) {
   2857 		sum = v[i];
   2858 		for ( j = 0; j < i; j++ ) {
   2859 			sum -= (*this)[i][j] * x[j];
   2860 		}
   2861 		x[i] = sum / (*this)[i][i];
   2862 	}
   2863 
   2864 	// calculate new row of L and calculate the square of the diagonal entry
   2865 	sum = v[numRows - 1];
   2866 	for ( i = 0; i < numRows - 1; i++ ) {
   2867 		(*this)[numRows - 1][i] = x[i];
   2868 		sum -= x[i] * x[i];
   2869 	}
   2870 
   2871 	if ( sum <= 0.0f ) {
   2872 		return false;
   2873 	}
   2874 
   2875 	// store the diagonal entry
   2876 	(*this)[numRows - 1][numRows - 1] = idMath::Sqrt( sum );
   2877 
   2878 	return true;
   2879 }
   2880 
   2881 /*
   2882 ============
   2883 idMatX::Cholesky_UpdateDecrement
   2884 
   2885   Updates the in-place Cholesky factorization to obtain the factors for the matrix with row r and column r removed.
   2886   v should store the row of the original matrix.
   2887 ============
   2888 */
   2889 bool idMatX::Cholesky_UpdateDecrement( const idVecX &v, int r ) {
   2890 	idVecX v1;
   2891 
   2892 	assert( numRows == numColumns );
   2893 	assert( v.GetSize() >= numRows );
   2894 	assert( r >= 0 && r < numRows );
   2895 
   2896 	v1.SetData( numRows, VECX_ALLOCA( numRows ) );
   2897 
   2898 	// update the row and column to identity
   2899 	v1 = -v;
   2900 	v1[r] += 1.0f;
   2901 
   2902 	// NOTE:	msvc compiler bug: the this pointer stored in edi is expected to stay
   2903 	//			untouched when calling Cholesky_UpdateRowColumn in the if statement
   2904 #if 0
   2905 	if ( !Cholesky_UpdateRowColumn( v1, r ) ) {
   2906 #else
   2907 	bool ret = Cholesky_UpdateRowColumn( v1, r );
   2908 	if ( !ret ) {
   2909 #endif
   2910 		return false;
   2911 	}
   2912 
   2913 	// physically remove the row and column
   2914 	Update_Decrement( r );
   2915 
   2916 	return true;
   2917 }
   2918 
   2919 /*
   2920 ============
   2921 idMatX::Cholesky_Solve
   2922 
   2923   Solve Ax = b with A factored in-place as: LL'
   2924 ============
   2925 */
   2926 void idMatX::Cholesky_Solve( idVecX &x, const idVecX &b ) const {
   2927 	int i, j;
   2928 	double sum;
   2929 
   2930 	assert( numRows == numColumns );
   2931 	assert( x.GetSize() >= numRows && b.GetSize() >= numRows );
   2932 
   2933 	// solve L
   2934 	for ( i = 0; i < numRows; i++ ) {
   2935 		sum = b[i];
   2936 		for ( j = 0; j < i; j++ ) {
   2937 			sum -= (*this)[i][j] * x[j];
   2938 		}
   2939 		x[i] = sum / (*this)[i][i];
   2940 	}
   2941 
   2942 	// solve Lt
   2943 	for ( i = numRows - 1; i >= 0; i-- ) {
   2944 		sum = x[i];
   2945 		for ( j = i + 1; j < numRows; j++ ) {
   2946 			sum -= (*this)[j][i] * x[j];
   2947 		}
   2948 		x[i] = sum / (*this)[i][i];
   2949 	}
   2950 }
   2951 
   2952 /*
   2953 ============
   2954 idMatX::Cholesky_Inverse
   2955 
   2956   Calculates the inverse of the matrix which is factored in-place as: LL'
   2957 ============
   2958 */
   2959 void idMatX::Cholesky_Inverse( idMatX &inv ) const {
   2960 	int i, j;
   2961 	idVecX x, b;
   2962 
   2963 	assert( numRows == numColumns );
   2964 
   2965 	x.SetData( numRows, VECX_ALLOCA( numRows ) );
   2966 	b.SetData( numRows, VECX_ALLOCA( numRows ) );
   2967 	b.Zero();
   2968 	inv.SetSize( numRows, numColumns );
   2969 
   2970 	for ( i = 0; i < numRows; i++ ) {
   2971 
   2972 		b[i] = 1.0f;
   2973 		Cholesky_Solve( x, b );
   2974 		for ( j = 0; j < numRows; j++ ) {
   2975 			inv[j][i] = x[j];
   2976 		}
   2977 		b[i] = 0.0f;
   2978 	}
   2979 }
   2980 
   2981 /*
   2982 ============
   2983 idMatX::Cholesky_MultiplyFactors
   2984 
   2985   Multiplies the factors of the in-place Cholesky factorization to form the original matrix.
   2986 ============
   2987 */
   2988 void idMatX::Cholesky_MultiplyFactors( idMatX &m ) const {
   2989 	int r, i, j;
   2990 	double sum;
   2991 
   2992 	m.SetSize( numRows, numColumns );
   2993 
   2994 	for ( r = 0; r < numRows; r++ ) {
   2995 
   2996 		// calculate row of matrix
   2997 		for ( i = 0; i < numRows; i++ ) {
   2998 			sum = 0.0f;
   2999 			for ( j = 0; j <= i && j <= r; j++ ) {
   3000 				sum += (*this)[r][j] * (*this)[i][j];
   3001 			}
   3002 			m[r][i] = sum;
   3003 		}
   3004 	}
   3005 }
   3006 
   3007 /*
   3008 ============
   3009 idMatX::LDLT_Factor
   3010 
   3011   in-place factorization: LDL'
   3012   L is a triangular matrix stored in the lower triangle.
   3013   L has ones on the diagonal that are not stored.
   3014   D is a diagonal matrix stored on the diagonal.
   3015   The upper triangle is not cleared.
   3016   The initial matrix has to be symmetric.
   3017 ============
   3018 */
   3019 bool idMatX::LDLT_Factor() {
   3020 	int i, j, k;
   3021 	float *v;
   3022 	double d, sum;
   3023 
   3024 	assert( numRows == numColumns );
   3025 
   3026 	v = (float *) _alloca16( numRows * sizeof( float ) );
   3027 
   3028 	for ( i = 0; i < numRows; i++ ) {
   3029 
   3030 		sum = (*this)[i][i];
   3031 		for ( j = 0; j < i; j++ ) {
   3032 			d = (*this)[i][j];
   3033 		    v[j] = (*this)[j][j] * d;
   3034 		    sum -= v[j] * d;
   3035 		}
   3036 
   3037 		if ( sum == 0.0f ) {
   3038 			return false;
   3039 		}
   3040 
   3041 		(*this)[i][i] = sum;
   3042 		d = 1.0f / sum;
   3043 
   3044 		for ( j = i + 1; j < numRows; j++ ) {
   3045 		    sum = (*this)[j][i];
   3046 			for ( k = 0; k < i; k++ ) {
   3047 				sum -= (*this)[j][k] * v[k];
   3048 			}
   3049 		    (*this)[j][i] = sum * d;
   3050 		}
   3051 	}
   3052 
   3053 	return true;
   3054 }
   3055 
   3056 /*
   3057 ============
   3058 idMatX::LDLT_UpdateRankOne
   3059 
   3060   Updates the in-place LDL' factorization to obtain the factors for the matrix: LDL' + alpha * v * v'
   3061   If offset > 0 only the lower right corner starting at (offset, offset) is updated.
   3062 ============
   3063 */
   3064 bool idMatX::LDLT_UpdateRankOne( const idVecX &v, float alpha, int offset ) {
   3065 	int i, j;
   3066 	float *y;
   3067 	double diag, newDiag, beta, p, d;
   3068 
   3069 	assert( numRows == numColumns );
   3070 	assert( v.GetSize() >= numRows );
   3071 	assert( offset >= 0 && offset < numRows );
   3072 
   3073 	y = (float *) _alloca16( v.GetSize() * sizeof( float ) );
   3074 	memcpy( y, v.ToFloatPtr(), v.GetSize() * sizeof( float ) );
   3075 
   3076 	for ( i = offset; i < numColumns; i++ ) {
   3077 		p = y[i];
   3078 		diag = (*this)[i][i];
   3079 		(*this)[i][i] = newDiag = diag + alpha * p * p;
   3080 
   3081 		if ( newDiag == 0.0f ) {
   3082 			return false;
   3083 		}
   3084 
   3085 		alpha /= newDiag;
   3086 		beta = p * alpha;
   3087 		alpha *= diag;
   3088 
   3089 		for ( j = i+1; j < numRows; j++ ) {
   3090 
   3091 			d = (*this)[j][i];
   3092 
   3093 			y[j] -= p * d;
   3094 			d += beta * y[j];
   3095 
   3096 			(*this)[j][i] = d;
   3097 		}
   3098 	}
   3099 
   3100 	return true;
   3101 }
   3102 
   3103 /*
   3104 ============
   3105 idMatX::LDLT_UpdateRowColumn
   3106 
   3107   Updates the in-place LDL' factorization to obtain the factors for the matrix:
   3108 
   3109          [ 0  a  0 ]
   3110   LDL' + [ a  b  c ]
   3111          [ 0  c  0 ]
   3112 
   3113   where: a = v[0,r-1], b = v[r], c = v[r+1,numRows-1]
   3114 ============
   3115 */
   3116 bool idMatX::LDLT_UpdateRowColumn( const idVecX &v, int r ) {
   3117 	int i, j;
   3118 	double sum;
   3119 	float *original, *y;
   3120 	idVecX addSub;
   3121 
   3122 	assert( numRows == numColumns );
   3123 	assert( v.GetSize() >= numRows );
   3124 	assert( r >= 0 && r < numRows );
   3125 
   3126 	addSub.SetData( numColumns, (float *) _alloca16( numColumns * sizeof( float ) ) );
   3127 
   3128 	if ( r == 0 ) {
   3129 
   3130 		if ( numColumns == 1 ) {
   3131 			(*this)[0][0] += v[0];
   3132 			return true;
   3133 		}
   3134 		for ( i = 0; i < numColumns; i++ ) {
   3135 			addSub[i] = v[i];
   3136 		}
   3137 
   3138 	} else {
   3139 
   3140 		original = (float *) _alloca16( numColumns * sizeof( float ) );
   3141 		y = (float *) _alloca16( numColumns * sizeof( float ) );
   3142 
   3143 		// calculate original row/column of matrix
   3144 		for ( i = 0; i < r; i++ ) {
   3145 			y[i] = (*this)[r][i] * (*this)[i][i];
   3146 		}
   3147 		for ( i = 0; i < numColumns; i++ ) {
   3148 			if ( i < r ) {
   3149 				sum = (*this)[i][i] * (*this)[r][i];
   3150 			} else if ( i == r ) {
   3151 				sum = (*this)[r][r];
   3152 			} else {
   3153 				sum = (*this)[r][r] * (*this)[i][r];
   3154 			}
   3155 			for ( j = 0; j < i && j < r; j++ ) {
   3156 				sum += (*this)[i][j] * y[j];
   3157 			}
   3158 			original[i] = sum;
   3159 		}
   3160 
   3161 		// solve for y in L * y = original + v
   3162 		for ( i = 0; i < r; i++ ) {
   3163 			sum = original[i] + v[i];
   3164 			for ( j = 0; j < i; j++ ) {
   3165 				sum -= (*this)[i][j] * y[j];
   3166 			}
   3167 			y[i] = sum;
   3168 		}
   3169 
   3170 		// calculate new row of L
   3171 		for ( i = 0; i < r; i++ ) {
   3172 			(*this)[r][i] = y[i] / (*this)[i][i];
   3173 		}
   3174 
   3175 		// if the last row/column of the matrix is updated
   3176 		if ( r == numColumns - 1 ) {
   3177 			// only calculate new diagonal
   3178 			sum = original[r] + v[r];
   3179 			for ( j = 0; j < r; j++ ) {
   3180 				sum -= (*this)[r][j] * y[j];
   3181 			}
   3182 			if ( sum == 0.0f ) {
   3183 				return false;
   3184 			}
   3185 			(*this)[r][r] = sum;
   3186 			return true;
   3187 		}
   3188 
   3189 		// calculate the row/column to be added to the lower right sub matrix starting at (r, r)
   3190 		for ( i = 0; i < r; i++ ) {
   3191 			y[i] = (*this)[r][i] * (*this)[i][i];
   3192 		}
   3193 		for ( i = r; i < numColumns; i++ ) {
   3194 			if ( i == r ) {
   3195 				sum = (*this)[r][r];
   3196 			} else {
   3197 				sum = (*this)[r][r] * (*this)[i][r];
   3198 			}
   3199 			for ( j = 0; j < r; j++ ) {
   3200 				sum += (*this)[i][j] * y[j];
   3201 			}
   3202 			addSub[i] = v[i] - ( sum - original[i] );
   3203 		}
   3204 	}
   3205 
   3206 	// add row/column to the lower right sub matrix starting at (r, r)
   3207 
   3208 #if 0
   3209 
   3210 	idVecX v1, v2;
   3211 	double d;
   3212 
   3213 	v1.SetData( numColumns, (float *) _alloca16( numColumns * sizeof( float ) ) );
   3214 	v2.SetData( numColumns, (float *) _alloca16( numColumns * sizeof( float ) ) );
   3215 
   3216 	d = idMath::SQRT_1OVER2;
   3217 	v1[r] = ( 0.5f * addSub[r] + 1.0f ) * d;
   3218 	v2[r] = ( 0.5f * addSub[r] - 1.0f ) * d;
   3219 	for ( i = r+1; i < numColumns; i++ ) {
   3220 		v1[i] = v2[i] = addSub[i] * d;
   3221 	}
   3222 
   3223 	// update
   3224 	if ( !LDLT_UpdateRankOne( v1, 1.0f, r ) ) {
   3225 		return false;
   3226 	}
   3227 	// downdate
   3228 	if ( !LDLT_UpdateRankOne( v2, -1.0f, r ) ) {
   3229 		return false;
   3230 	}
   3231 
   3232 #else
   3233 
   3234 	float *v1, *v2;
   3235 	double d, diag, newDiag, p1, p2, alpha1, alpha2, beta1, beta2;
   3236 
   3237 	v1 = (float *) _alloca16( numColumns * sizeof( float ) );
   3238 	v2 = (float *) _alloca16( numColumns * sizeof( float ) );
   3239 
   3240 	d = idMath::SQRT_1OVER2;
   3241 	v1[r] = ( 0.5f * addSub[r] + 1.0f ) * d;
   3242 	v2[r] = ( 0.5f * addSub[r] - 1.0f ) * d;
   3243 	for ( i = r+1; i < numColumns; i++ ) {
   3244 		v1[i] = v2[i] = addSub[i] * d;
   3245 	}
   3246 
   3247 	alpha1 = 1.0f;
   3248 	alpha2 = -1.0f;
   3249 
   3250 	// simultaneous update/downdate of the sub matrix starting at (r, r)
   3251 	for ( i = r; i < numColumns; i++ ) {
   3252 
   3253 		diag = (*this)[i][i];
   3254 		p1 = v1[i];
   3255 		newDiag = diag + alpha1 * p1 * p1;
   3256 
   3257 		if ( newDiag == 0.0f ) {
   3258 			return false;
   3259 		}
   3260 
   3261 		alpha1 /= newDiag;
   3262 		beta1 = p1 * alpha1;
   3263 		alpha1 *= diag;
   3264 
   3265 		diag = newDiag;
   3266 		p2 = v2[i];
   3267 		newDiag = diag + alpha2 * p2 * p2;
   3268 
   3269 		if ( newDiag == 0.0f ) {
   3270 			return false;
   3271 		}
   3272 
   3273 		alpha2 /= newDiag;
   3274 		beta2 = p2 * alpha2;
   3275 		alpha2 *= diag;
   3276 
   3277 		(*this)[i][i] = newDiag;
   3278 
   3279 		for ( j = i+1; j < numRows; j++ ) {
   3280 
   3281 			d = (*this)[j][i];
   3282 
   3283 			v1[j] -= p1 * d;
   3284 			d += beta1 * v1[j];
   3285 
   3286 			v2[j] -= p2 * d;
   3287 			d += beta2 * v2[j];
   3288 
   3289 			(*this)[j][i] = d;
   3290 		}
   3291 	}
   3292 
   3293 #endif
   3294 
   3295 	return true;
   3296 }
   3297 
   3298 /*
   3299 ============
   3300 idMatX::LDLT_UpdateIncrement
   3301 
   3302   Updates the in-place LDL' factorization to obtain the factors for the matrix:
   3303 
   3304   [ A  a ]
   3305   [ a  b ]
   3306 
   3307   where: a = v[0,numRows-1], b = v[numRows]
   3308 ============
   3309 */
   3310 bool idMatX::LDLT_UpdateIncrement( const idVecX &v ) {
   3311 	int i, j;
   3312 	float *x;
   3313 	double sum, d;
   3314 
   3315 	assert( numRows == numColumns );
   3316 	assert( v.GetSize() >= numRows+1 );
   3317 
   3318 	ChangeSize( numRows+1, numColumns+1, false );
   3319 
   3320 	x = (float *) _alloca16( numRows * sizeof( float ) );
   3321 
   3322 	// solve for x in L * x = v
   3323 	for ( i = 0; i < numRows - 1; i++ ) {
   3324 		sum = v[i];
   3325 		for ( j = 0; j < i; j++ ) {
   3326 			sum -= (*this)[i][j] * x[j];
   3327 		}
   3328 		x[i] = sum;
   3329 	}
   3330 
   3331 	// calculate new row of L and calculate the diagonal entry
   3332 	sum = v[numRows - 1];
   3333 	for ( i = 0; i < numRows - 1; i++ ) {
   3334 		(*this)[numRows - 1][i] = d = x[i] / (*this)[i][i];
   3335 		sum -= d * x[i];
   3336 	}
   3337 
   3338 	if ( sum == 0.0f ) {
   3339 		return false;
   3340 	}
   3341 
   3342 	// store the diagonal entry
   3343 	(*this)[numRows - 1][numRows - 1] = sum;
   3344 
   3345 	return true;
   3346 }
   3347 
   3348 /*
   3349 ============
   3350 idMatX::LDLT_UpdateDecrement
   3351 
   3352   Updates the in-place LDL' factorization to obtain the factors for the matrix with row r and column r removed.
   3353   v should store the row of the original matrix.
   3354 ============
   3355 */
   3356 bool idMatX::LDLT_UpdateDecrement( const idVecX &v, int r ) {
   3357 	idVecX v1;
   3358 
   3359 	assert( numRows == numColumns );
   3360 	assert( v.GetSize() >= numRows );
   3361 	assert( r >= 0 && r < numRows );
   3362 
   3363 	v1.SetData( numRows, VECX_ALLOCA( numRows ) );
   3364 
   3365 	// update the row and column to identity
   3366 	v1 = -v;
   3367 	v1[r] += 1.0f;
   3368 
   3369 	// NOTE:	msvc compiler bug: the this pointer stored in edi is expected to stay
   3370 	//			untouched when calling LDLT_UpdateRowColumn in the if statement
   3371 #if 0
   3372 	if ( !LDLT_UpdateRowColumn( v1, r ) ) {
   3373 #else
   3374 	bool ret = LDLT_UpdateRowColumn( v1, r );
   3375 	if ( !ret ) {
   3376 #endif
   3377 		return false;
   3378 	}
   3379 
   3380 	// physically remove the row and column
   3381 	Update_Decrement( r );
   3382 
   3383 	return true;
   3384 }
   3385 
   3386 /*
   3387 ============
   3388 idMatX::LDLT_Solve
   3389 
   3390   Solve Ax = b with A factored in-place as: LDL'
   3391 ============
   3392 */
   3393 void idMatX::LDLT_Solve( idVecX &x, const idVecX &b ) const {
   3394 	int i, j;
   3395 	double sum;
   3396 
   3397 	assert( numRows == numColumns );
   3398 	assert( x.GetSize() >= numRows && b.GetSize() >= numRows );
   3399 
   3400 	// solve L
   3401 	for ( i = 0; i < numRows; i++ ) {
   3402 		sum = b[i];
   3403 		for ( j = 0; j < i; j++ ) {
   3404 			sum -= (*this)[i][j] * x[j];
   3405 		}
   3406 		x[i] = sum;
   3407 	}
   3408 
   3409 	// solve D
   3410 	for ( i = 0; i < numRows; i++ ) {
   3411 		x[i] /= (*this)[i][i];
   3412 	}
   3413 
   3414 	// solve Lt
   3415 	for ( i = numRows - 2; i >= 0; i-- ) {
   3416 		sum = x[i];
   3417 		for ( j = i + 1; j < numRows; j++ ) {
   3418 			sum -= (*this)[j][i] * x[j];
   3419 		}
   3420 		x[i] = sum;
   3421 	}
   3422 }
   3423 
   3424 /*
   3425 ============
   3426 idMatX::LDLT_Inverse
   3427 
   3428   Calculates the inverse of the matrix which is factored in-place as: LDL'
   3429 ============
   3430 */
   3431 void idMatX::LDLT_Inverse( idMatX &inv ) const {
   3432 	int i, j;
   3433 	idVecX x, b;
   3434 
   3435 	assert( numRows == numColumns );
   3436 
   3437 	x.SetData( numRows, VECX_ALLOCA( numRows ) );
   3438 	b.SetData( numRows, VECX_ALLOCA( numRows ) );
   3439 	b.Zero();
   3440 	inv.SetSize( numRows, numColumns );
   3441 
   3442 	for ( i = 0; i < numRows; i++ ) {
   3443 
   3444 		b[i] = 1.0f;
   3445 		LDLT_Solve( x, b );
   3446 		for ( j = 0; j < numRows; j++ ) {
   3447 			inv[j][i] = x[j];
   3448 		}
   3449 		b[i] = 0.0f;
   3450 	}
   3451 }
   3452 
   3453 /*
   3454 ============
   3455 idMatX::LDLT_UnpackFactors
   3456 
   3457   Unpacks the in-place LDL' factorization.
   3458 ============
   3459 */
   3460 void idMatX::LDLT_UnpackFactors( idMatX &L, idMatX &D ) const {
   3461 	int i, j;
   3462 
   3463 	L.Zero( numRows, numColumns );
   3464 	D.Zero( numRows, numColumns );
   3465 	for ( i = 0; i < numRows; i++ ) {
   3466 		for ( j = 0; j < i; j++ ) {
   3467 			L[i][j] = (*this)[i][j];
   3468 		}
   3469 		L[i][i] = 1.0f;
   3470 		D[i][i] = (*this)[i][i];
   3471 	}
   3472 }
   3473 
   3474 /*
   3475 ============
   3476 idMatX::LDLT_MultiplyFactors
   3477 
   3478   Multiplies the factors of the in-place LDL' factorization to form the original matrix.
   3479 ============
   3480 */
   3481 void idMatX::LDLT_MultiplyFactors( idMatX &m ) const {
   3482 	int r, i, j;
   3483 	float *v;
   3484 	double sum;
   3485 
   3486 	v = (float *) _alloca16( numRows * sizeof( float ) );
   3487 	m.SetSize( numRows, numColumns );
   3488 
   3489 	for ( r = 0; r < numRows; r++ ) {
   3490 
   3491 		// calculate row of matrix
   3492 		for ( i = 0; i < r; i++ ) {
   3493 			v[i] = (*this)[r][i] * (*this)[i][i];
   3494 		}
   3495 		for ( i = 0; i < numColumns; i++ ) {
   3496 			if ( i < r ) {
   3497 				sum = (*this)[i][i] * (*this)[r][i];
   3498 			} else if ( i == r ) {
   3499 				sum = (*this)[r][r];
   3500 			} else {
   3501 				sum = (*this)[r][r] * (*this)[i][r];
   3502 			}
   3503 			for ( j = 0; j < i && j < r; j++ ) {
   3504 				sum += (*this)[i][j] * v[j];
   3505 			}
   3506 			m[r][i] = sum;
   3507 		}
   3508 	}
   3509 }
   3510 
   3511 /*
   3512 ============
   3513 idMatX::TriDiagonal_ClearTriangles
   3514 ============
   3515 */
   3516 void idMatX::TriDiagonal_ClearTriangles() {
   3517 	int i, j;
   3518 
   3519 	assert( numRows == numColumns );
   3520 	for ( i = 0; i < numRows-2; i++ ) {
   3521 		for ( j = i+2; j < numColumns; j++ ) {
   3522 			(*this)[i][j] = 0.0f;
   3523 			(*this)[j][i] = 0.0f;
   3524 		}
   3525 	}
   3526 }
   3527 
   3528 /*
   3529 ============
   3530 idMatX::TriDiagonal_Solve
   3531 
   3532   Solve Ax = b with A being tridiagonal.
   3533 ============
   3534 */
   3535 bool idMatX::TriDiagonal_Solve( idVecX &x, const idVecX &b ) const {
   3536 	int i;
   3537 	float d;
   3538 	idVecX tmp;
   3539 
   3540 	assert( numRows == numColumns );
   3541 	assert( x.GetSize() >= numRows && b.GetSize() >= numRows );
   3542 
   3543 	tmp.SetData( numRows, VECX_ALLOCA( numRows ) );
   3544 
   3545 	d = (*this)[0][0];
   3546 	if ( d == 0.0f ) {
   3547 		return false;
   3548 	}
   3549 	d = 1.0f / d;
   3550 	x[0] = b[0] * d;
   3551 	for ( i = 1; i < numRows; i++ ) {
   3552 		tmp[i] = (*this)[i-1][i] * d;
   3553 		d = (*this)[i][i] - (*this)[i][i-1] * tmp[i];
   3554 		if ( d == 0.0f ) {
   3555 			return false;
   3556 		}
   3557 		d = 1.0f / d;
   3558 		x[i] = ( b[i] - (*this)[i][i-1] * x[i-1] ) * d;
   3559 	}
   3560 	for ( i = numRows - 2; i >= 0; i-- ) {
   3561 		x[i] -= tmp[i+1] * x[i+1];
   3562 	}
   3563 	return true;
   3564 }
   3565 
   3566 /*
   3567 ============
   3568 idMatX::TriDiagonal_Inverse
   3569 
   3570   Calculates the inverse of a tri-diagonal matrix.
   3571 ============
   3572 */
   3573 void idMatX::TriDiagonal_Inverse( idMatX &inv ) const {
   3574 	int i, j;
   3575 	idVecX x, b;
   3576 
   3577 	assert( numRows == numColumns );
   3578 
   3579 	x.SetData( numRows, VECX_ALLOCA( numRows ) );
   3580 	b.SetData( numRows, VECX_ALLOCA( numRows ) );
   3581 	b.Zero();
   3582 	inv.SetSize( numRows, numColumns );
   3583 
   3584 	for ( i = 0; i < numRows; i++ ) {
   3585 
   3586 		b[i] = 1.0f;
   3587 		TriDiagonal_Solve( x, b );
   3588 		for ( j = 0; j < numRows; j++ ) {
   3589 			inv[j][i] = x[j];
   3590 		}
   3591 		b[i] = 0.0f;
   3592 	}
   3593 }
   3594 
   3595 /*
   3596 ============
   3597 idMatX::HouseholderReduction
   3598 
   3599   Householder reduction to symmetric tri-diagonal form.
   3600   The original matrix is replaced by an orthogonal matrix effecting the accumulated householder transformations.
   3601   The diagonal elements of the diagonal matrix are stored in diag.
   3602   The off-diagonal elements of the diagonal matrix are stored in subd.
   3603   The initial matrix has to be symmetric.
   3604 ============
   3605 */
   3606 void idMatX::HouseholderReduction( idVecX &diag, idVecX &subd ) {
   3607 	int i0, i1, i2, i3;
   3608 	float h, f, g, invH, halfFdivH, scale, invScale, sum;
   3609 
   3610 	assert( numRows == numColumns );
   3611 
   3612 	diag.SetSize( numRows );
   3613 	subd.SetSize( numRows );
   3614 
   3615 	for ( i0 = numRows-1, i3 = numRows-2; i0 >= 1; i0--, i3-- ) {
   3616 		h = 0.0f;
   3617 		scale = 0.0f;
   3618 
   3619 		if ( i3 > 0 ) {
   3620 			for ( i2 = 0; i2 <= i3; i2++ ) {
   3621 				scale += idMath::Fabs( (*this)[i0][i2] );
   3622 			}
   3623 			if ( scale == 0 ) {
   3624 				subd[i0] = (*this)[i0][i3];
   3625 			} else {
   3626 				invScale = 1.0f / scale;
   3627 				for (i2 = 0; i2 <= i3; i2++)
   3628 				{
   3629 					(*this)[i0][i2] *= invScale;
   3630 					h += (*this)[i0][i2] * (*this)[i0][i2];
   3631 				}
   3632 				f = (*this)[i0][i3];
   3633 				g = idMath::Sqrt( h );
   3634 				if ( f > 0.0f ) {
   3635 					g = -g;
   3636 				}
   3637 				subd[i0] = scale * g;
   3638 				h -= f * g;
   3639 				(*this)[i0][i3] = f - g;
   3640 				f = 0.0f;
   3641 				invH = 1.0f / h;
   3642 				for (i1 = 0; i1 <= i3; i1++) {
   3643 					(*this)[i1][i0] = (*this)[i0][i1] * invH;
   3644 					g = 0.0f;
   3645 					for (i2 = 0; i2 <= i1; i2++) {
   3646 						g += (*this)[i1][i2] * (*this)[i0][i2];
   3647 					}
   3648 					for (i2 = i1+1; i2 <= i3; i2++) {
   3649 						g += (*this)[i2][i1] * (*this)[i0][i2];
   3650 					}
   3651 					subd[i1] = g * invH;
   3652 					f += subd[i1] * (*this)[i0][i1];
   3653 				}
   3654 				halfFdivH = 0.5f * f * invH;
   3655 				for ( i1 = 0; i1 <= i3; i1++ ) {
   3656 					f = (*this)[i0][i1];
   3657 					g = subd[i1] - halfFdivH * f;
   3658 					subd[i1] = g;
   3659 					for ( i2 = 0; i2 <= i1; i2++ ) {
   3660 						(*this)[i1][i2] -= f * subd[i2] + g * (*this)[i0][i2];
   3661 					}
   3662 				}
   3663             }
   3664 		} else {
   3665 			subd[i0] = (*this)[i0][i3];
   3666 		}
   3667 
   3668 		diag[i0] = h;
   3669 	}
   3670 
   3671 	diag[0] = 0.0f;
   3672 	subd[0] = 0.0f;
   3673 	for ( i0 = 0, i3 = -1; i0 <= numRows-1; i0++, i3++ ) {
   3674 		if ( diag[i0] ) {
   3675 			for ( i1 = 0; i1 <= i3; i1++ ) {
   3676 				sum = 0.0f;
   3677 				for (i2 = 0; i2 <= i3; i2++) {
   3678 					sum += (*this)[i0][i2] * (*this)[i2][i1];
   3679 				}
   3680 				for ( i2 = 0; i2 <= i3; i2++ ) {
   3681 					(*this)[i2][i1] -= sum * (*this)[i2][i0];
   3682 				}
   3683 			}
   3684 		}
   3685 		diag[i0] = (*this)[i0][i0];
   3686 		(*this)[i0][i0] = 1.0f;
   3687 		for ( i1 = 0; i1 <= i3; i1++ ) {
   3688 			(*this)[i1][i0] = 0.0f;
   3689 			(*this)[i0][i1] = 0.0f;
   3690 		}
   3691 	}
   3692 
   3693 	// re-order
   3694 	for ( i0 = 1, i3 = 0; i0 < numRows; i0++, i3++ ) {
   3695 		subd[i3] = subd[i0];
   3696 	}
   3697 	subd[numRows-1] = 0.0f;
   3698 }
   3699 
   3700 /*
   3701 ============
   3702 idMatX::QL
   3703 
   3704   QL algorithm with implicit shifts to determine the eigenvalues and eigenvectors of a symmetric tri-diagonal matrix.
   3705   diag contains the diagonal elements of the symmetric tri-diagonal matrix on input and is overwritten with the eigenvalues.
   3706   subd contains the off-diagonal elements of the symmetric tri-diagonal matrix and is destroyed.
   3707   This matrix has to be either the identity matrix to determine the eigenvectors for a symmetric tri-diagonal matrix,
   3708   or the matrix returned by the Householder reduction to determine the eigenvalues for the original symmetric matrix.
   3709 ============
   3710 */
   3711 bool idMatX::QL( idVecX &diag, idVecX &subd ) {
   3712     const int maxIter = 32;
   3713 	int i0, i1, i2, i3;
   3714 	float a, b, f, g, r, p, s, c;
   3715 
   3716 	assert( numRows == numColumns );
   3717 
   3718 	for ( i0 = 0; i0 < numRows; i0++ ) {
   3719 		for ( i1 = 0; i1 < maxIter; i1++ ) {
   3720 			for ( i2 = i0; i2 <= numRows - 2; i2++ ) {
   3721 				a = idMath::Fabs( diag[i2] ) + idMath::Fabs( diag[i2+1] );
   3722 				if ( idMath::Fabs( subd[i2] ) + a == a ) {
   3723 					break;
   3724 				}
   3725 			}
   3726 			if ( i2 == i0 ) {
   3727 				break;
   3728 			}
   3729 
   3730 			g = ( diag[i0+1] - diag[i0] ) / ( 2.0f * subd[i0] );
   3731 			r = idMath::Sqrt( g * g + 1.0f );
   3732 			if ( g < 0.0f ) {
   3733 				g = diag[i2] - diag[i0] + subd[i0] / ( g - r );
   3734 			} else {
   3735 				g = diag[i2] - diag[i0] + subd[i0] / ( g + r );
   3736 			}
   3737 			s = 1.0f;
   3738 			c = 1.0f;
   3739 			p = 0.0f;
   3740 			for ( i3 = i2 - 1; i3 >= i0; i3-- ) {
   3741 				f = s * subd[i3];
   3742 				b = c * subd[i3];
   3743 				if ( idMath::Fabs( f ) >= idMath::Fabs( g ) ) {
   3744 					c = g / f;
   3745 					r = idMath::Sqrt( c * c + 1.0f );
   3746 					subd[i3+1] = f * r;
   3747 					s = 1.0f / r;
   3748 					c *= s;
   3749 				} else {
   3750 					s = f / g;
   3751 					r = idMath::Sqrt( s * s + 1.0f );
   3752 					subd[i3+1] = g * r;
   3753 					c = 1.0f / r;
   3754 					s *= c;
   3755 				}
   3756 				g = diag[i3+1] - p;
   3757 				r = ( diag[i3] - g ) * s + 2.0f * b * c;
   3758 				p = s * r;
   3759 				diag[i3+1] = g + p;
   3760 				g = c * r - b;
   3761 
   3762 				for ( int i4 = 0; i4 < numRows; i4++ ) {
   3763 					f = (*this)[i4][i3+1];
   3764 					(*this)[i4][i3+1] = s * (*this)[i4][i3] + c * f;
   3765 					(*this)[i4][i3] = c * (*this)[i4][i3] - s * f;
   3766 				}
   3767 			}
   3768 			diag[i0] -= p;
   3769 			subd[i0] = g;
   3770 			subd[i2] = 0.0f;
   3771 		}
   3772 		if ( i1 == maxIter ) {
   3773 			return false;
   3774 		}
   3775 	}
   3776 	return true;
   3777 }
   3778 
   3779 /*
   3780 ============
   3781 idMatX::Eigen_SolveSymmetricTriDiagonal
   3782 
   3783   Determine eigen values and eigen vectors for a symmetric tri-diagonal matrix.
   3784   The eigen values are stored in 'eigenValues'.
   3785   Column i of the original matrix will store the eigen vector corresponding to the eigenValues[i].
   3786   The initial matrix has to be symmetric tri-diagonal.
   3787 ============
   3788 */
   3789 bool idMatX::Eigen_SolveSymmetricTriDiagonal( idVecX &eigenValues ) {
   3790 	int i;
   3791 	idVecX subd;
   3792 
   3793 	assert( numRows == numColumns );
   3794 
   3795 	subd.SetData( numRows, VECX_ALLOCA( numRows ) );
   3796 	eigenValues.SetSize( numRows );
   3797 
   3798 	for ( i = 0; i < numRows-1; i++ ) {
   3799 		eigenValues[i] = (*this)[i][i];
   3800 		subd[i] = (*this)[i+1][i];
   3801 	}
   3802 	eigenValues[numRows-1] = (*this)[numRows-1][numRows-1];
   3803 
   3804 	Identity();
   3805 
   3806 	return QL( eigenValues, subd );
   3807 }
   3808 
   3809 /*
   3810 ============
   3811 idMatX::Eigen_SolveSymmetric
   3812 
   3813   Determine eigen values and eigen vectors for a symmetric matrix.
   3814   The eigen values are stored in 'eigenValues'.
   3815   Column i of the original matrix will store the eigen vector corresponding to the eigenValues[i].
   3816   The initial matrix has to be symmetric.
   3817 ============
   3818 */
   3819 bool idMatX::Eigen_SolveSymmetric( idVecX &eigenValues ) {
   3820 	idVecX subd;
   3821 
   3822 	assert( numRows == numColumns );
   3823 
   3824 	subd.SetData( numRows, VECX_ALLOCA( numRows ) );
   3825 	eigenValues.SetSize( numRows );
   3826 
   3827 	HouseholderReduction( eigenValues, subd );
   3828 	return QL( eigenValues, subd );
   3829 }
   3830 
   3831 /*
   3832 ============
   3833 idMatX::HessenbergReduction
   3834 
   3835   Reduction to Hessenberg form.
   3836 ============
   3837 */
   3838 void idMatX::HessenbergReduction( idMatX &H ) {
   3839 	int i, j, m;
   3840 	int low = 0;
   3841 	int high = numRows - 1;
   3842 	float scale, f, g, h;
   3843 	idVecX v;
   3844 
   3845 	v.SetData( numRows, VECX_ALLOCA( numRows ) );
   3846 
   3847 	for ( m = low + 1; m <= high - 1; m++ ) {
   3848 
   3849 		scale = 0.0f;
   3850 		for ( i = m; i <= high; i++ ) {
   3851 			scale = scale + idMath::Fabs( H[i][m-1] );
   3852 		}
   3853 		if ( scale != 0.0f ) {
   3854 
   3855 			// compute Householder transformation.
   3856 			h = 0.0f;
   3857 			for ( i = high; i >= m; i-- ) {
   3858 				v[i] = H[i][m-1] / scale;
   3859 				h += v[i] * v[i];
   3860 			}
   3861 			g = idMath::Sqrt( h );
   3862 			if ( v[m] > 0.0f ) {
   3863 				g = -g;
   3864 			}
   3865 			h = h - v[m] * g;
   3866 			v[m] = v[m] - g;
   3867 
   3868 			// apply Householder similarity transformation
   3869 			// H = (I-u*u'/h)*H*(I-u*u')/h)
   3870 			for ( j = m; j < numRows; j++) {
   3871 				f = 0.0f;
   3872 				for ( i = high; i >= m; i-- ) {
   3873 					f += v[i] * H[i][j];
   3874 				}
   3875 				f = f / h;
   3876 				for ( i = m; i <= high; i++ ) {
   3877 					H[i][j] -= f * v[i];
   3878 				}
   3879 			}
   3880 
   3881 			for ( i = 0; i <= high; i++ ) {
   3882 				f = 0.0f;
   3883 				for ( j = high; j >= m; j-- ) {
   3884 					f += v[j] * H[i][j];
   3885 				}
   3886 				f = f / h;
   3887 				for ( j = m; j <= high; j++ ) {
   3888 					H[i][j] -= f * v[j];
   3889 				}
   3890 			}
   3891 			v[m] = scale * v[m];
   3892 			H[m][m-1] = scale * g;
   3893 		}
   3894 	}
   3895 
   3896 	// accumulate transformations
   3897 	Identity();
   3898 	for ( int m = high - 1; m >= low + 1; m-- ) {
   3899 		if ( H[m][m-1] != 0.0f ) {
   3900 			for ( i = m + 1; i <= high; i++ ) {
   3901 				v[i] = H[i][m-1];
   3902 			}
   3903 			for ( j = m; j <= high; j++ ) {
   3904 				g = 0.0f;
   3905 				for ( i = m; i <= high; i++ ) {
   3906 					g += v[i] * (*this)[i][j];
   3907 				}
   3908 				// float division to avoid possible underflow
   3909 				g = ( g / v[m] ) / H[m][m-1];
   3910 				for ( i = m; i <= high; i++ ) {
   3911 					(*this)[i][j] += g * v[i];
   3912 				}
   3913 			}
   3914 		}
   3915 	}
   3916 }
   3917 
   3918 /*
   3919 ============
   3920 idMatX::ComplexDivision
   3921 
   3922   Complex scalar division.
   3923 ============
   3924 */
   3925 void idMatX::ComplexDivision( float xr, float xi, float yr, float yi, float &cdivr, float &cdivi ) {
   3926 	float r, d;
   3927 	if ( idMath::Fabs( yr ) > idMath::Fabs( yi ) ) {
   3928 		r = yi / yr;
   3929 		d = yr + r * yi;
   3930 		cdivr = ( xr + r * xi ) / d;
   3931 		cdivi = ( xi - r * xr ) / d;
   3932 	} else {
   3933 		r = yr / yi;
   3934 		d = yi + r * yr;
   3935 		cdivr = ( r * xr + xi ) / d;
   3936 		cdivi = ( r * xi - xr ) / d;
   3937 	}
   3938 }
   3939 
   3940 /*
   3941 ============
   3942 idMatX::HessenbergToRealSchur
   3943 
   3944   Reduction from Hessenberg to real Schur form.
   3945 ============
   3946 */
   3947 bool idMatX::HessenbergToRealSchur( idMatX &H, idVecX &realEigenValues, idVecX &imaginaryEigenValues ) {
   3948 	int i, j, k;
   3949 	int n = numRows - 1;
   3950 	int low = 0;
   3951 	int high = numRows - 1;
   3952 	float eps = 2e-16f, exshift = 0.0f;
   3953 	float p = 0.0f, q = 0.0f, r = 0.0f, s = 0.0f, z = 0.0f, t, w, x, y;
   3954 
   3955 	// store roots isolated by balanc and compute matrix norm
   3956 	float norm = 0.0f;
   3957 	for ( i = 0; i < numRows; i++ ) {
   3958 		if ( i < low || i > high ) {
   3959 			realEigenValues[i] = H[i][i];
   3960 			imaginaryEigenValues[i] = 0.0f;
   3961 		}
   3962 		for ( j = Max( i - 1, 0 ); j < numRows; j++ ) {
   3963 			norm = norm + idMath::Fabs( H[i][j] );
   3964 		}
   3965 	}
   3966 
   3967 	int iter = 0;
   3968 	while( n >= low ) {
   3969 
   3970 		// look for single small sub-diagonal element
   3971 		int l = n;
   3972 		while ( l > low ) {
   3973 			s = idMath::Fabs( H[l-1][l-1] ) + idMath::Fabs( H[l][l] );
   3974 			if ( s == 0.0f ) {
   3975 				s = norm;
   3976 			}
   3977 			if ( idMath::Fabs( H[l][l-1] ) < eps * s ) {
   3978 				break;
   3979 			}
   3980 			l--;
   3981 		}
   3982 	   
   3983 		// check for convergence
   3984 		if ( l == n ) {			// one root found
   3985 			H[n][n] = H[n][n] + exshift;
   3986 			realEigenValues[n] = H[n][n];
   3987 			imaginaryEigenValues[n] = 0.0f;
   3988 			n--;
   3989 			iter = 0;
   3990 		} else if ( l == n-1 ) {	// two roots found
   3991 			w = H[n][n-1] * H[n-1][n];
   3992 			p = ( H[n-1][n-1] - H[n][n] ) / 2.0f;
   3993 			q = p * p + w;
   3994 			z = idMath::Sqrt( idMath::Fabs( q ) );
   3995 			H[n][n] = H[n][n] + exshift;
   3996 			H[n-1][n-1] = H[n-1][n-1] + exshift;
   3997 			x = H[n][n];
   3998 
   3999 			if ( q >= 0.0f ) {		// real pair
   4000 				if ( p >= 0.0f ) {
   4001 					z = p + z;
   4002 				} else {
   4003 					z = p - z;
   4004 				}
   4005 				realEigenValues[n-1] = x + z;
   4006 				realEigenValues[n] = realEigenValues[n-1];
   4007 				if ( z != 0.0f ) {
   4008 					realEigenValues[n] = x - w / z;
   4009 				}
   4010 				imaginaryEigenValues[n-1] = 0.0f;
   4011 				imaginaryEigenValues[n] = 0.0f;
   4012 				x = H[n][n-1];
   4013 				s = idMath::Fabs( x ) + idMath::Fabs( z );
   4014 				p = x / s;
   4015 				q = z / s;
   4016 				r = idMath::Sqrt( p * p + q * q );
   4017 				p = p / r;
   4018 				q = q / r;
   4019 
   4020 				// modify row
   4021 				for ( j = n-1; j < numRows; j++ ) {
   4022 					z = H[n-1][j];
   4023 					H[n-1][j] = q * z + p * H[n][j];
   4024 					H[n][j] = q * H[n][j] - p * z;
   4025 				}
   4026 
   4027 				// modify column
   4028 				for ( i = 0; i <= n; i++ ) {
   4029 					z = H[i][n-1];
   4030 					H[i][n-1] = q * z + p * H[i][n];
   4031 					H[i][n] = q * H[i][n] - p * z;
   4032 				}
   4033 
   4034 				// accumulate transformations
   4035 				for ( i = low; i <= high; i++ ) {
   4036 					z = (*this)[i][n-1];
   4037 					(*this)[i][n-1] = q * z + p * (*this)[i][n];
   4038 					(*this)[i][n] = q * (*this)[i][n] - p * z;
   4039 				}
   4040 			} else {		// complex pair
   4041 				realEigenValues[n-1] = x + p;
   4042 				realEigenValues[n] = x + p;
   4043 				imaginaryEigenValues[n-1] = z;
   4044 				imaginaryEigenValues[n] = -z;
   4045 			}
   4046 			n = n - 2;
   4047 			iter = 0;
   4048 
   4049 		} else {	// no convergence yet
   4050 
   4051 			// form shift
   4052 			x = H[n][n];
   4053 			y = 0.0f;
   4054 			w = 0.0f;
   4055 			if ( l < n ) {
   4056 				y = H[n-1][n-1];
   4057 				w = H[n][n-1] * H[n-1][n];
   4058 			}
   4059 
   4060 			// Wilkinson's original ad hoc shift
   4061 			if ( iter == 10 ) {
   4062 				exshift += x;
   4063 				for ( i = low; i <= n; i++ ) {
   4064 					H[i][i] -= x;
   4065 				}
   4066 				s = idMath::Fabs( H[n][n-1] ) + idMath::Fabs( H[n-1][n-2] );
   4067 				x = y = 0.75f * s;
   4068 				w = -0.4375f * s * s;
   4069 			}
   4070 
   4071 			// new ad hoc shift
   4072 			if ( iter == 30 ) {
   4073 				s = ( y - x ) / 2.0f;
   4074 				s = s * s + w;
   4075 				if ( s > 0 ) {
   4076 					s = idMath::Sqrt( s );
   4077 					if ( y < x ) {
   4078 						s = -s;
   4079 					}
   4080 					s = x - w / ( ( y - x ) / 2.0f + s );
   4081 					for ( i = low; i <= n; i++ ) {
   4082 						H[i][i] -= s;
   4083 					}
   4084 					exshift += s;
   4085 					x = y = w = 0.964f;
   4086 				}
   4087 			}
   4088 
   4089 			iter = iter + 1;
   4090 
   4091 			// look for two consecutive small sub-diagonal elements
   4092 			int m;
   4093 			for( m = n-2; m >= l; m-- ) {
   4094 				z = H[m][m];
   4095 				r = x - z;
   4096 				s = y - z;
   4097 				p = ( r * s - w ) / H[m+1][m] + H[m][m+1];
   4098 				q = H[m+1][m+1] - z - r - s;
   4099 				r = H[m+2][m+1];
   4100 				s = idMath::Fabs( p ) + idMath::Fabs( q ) + idMath::Fabs( r );
   4101 				p = p / s;
   4102 				q = q / s;
   4103 				r = r / s;
   4104 				if ( m == l ) {
   4105 					break;
   4106 				}
   4107 				if ( idMath::Fabs( H[m][m-1] ) * ( idMath::Fabs( q ) + idMath::Fabs( r ) ) <
   4108 						eps * ( idMath::Fabs( p ) * ( idMath::Fabs( H[m-1][m-1] ) + idMath::Fabs( z ) + idMath::Fabs( H[m+1][m+1] ) ) ) ) {
   4109 					break;
   4110 				}
   4111 			}
   4112 
   4113 			for ( i = m+2; i <= n; i++ ) {
   4114 				H[i][i-2] = 0.0f;
   4115 				if ( i > m+2 ) {
   4116 					H[i][i-3] = 0.0f;
   4117 				}
   4118 			}
   4119 
   4120 			// double QR step involving rows l:n and columns m:n
   4121 			for ( k = m; k <= n-1; k++ ) {
   4122 				bool notlast = ( k != n-1 );
   4123 				if ( k != m ) {
   4124 					p = H[k][k-1];
   4125 					q = H[k+1][k-1];
   4126 					r = ( notlast ? H[k+2][k-1] : 0.0f );
   4127 					x = idMath::Fabs( p ) + idMath::Fabs( q ) + idMath::Fabs( r );
   4128 					if ( x != 0.0f ) {
   4129 						p = p / x;
   4130 						q = q / x;
   4131 						r = r / x;
   4132 					}
   4133 				}
   4134 				if ( x == 0.0f ) {
   4135 					break;
   4136 				}
   4137 				s = idMath::Sqrt( p * p + q * q + r * r );
   4138 				if ( p < 0.0f ) {
   4139 					s = -s;
   4140 				}
   4141 				if ( s != 0.0f ) {
   4142 					if ( k != m ) {
   4143 						H[k][k-1] = -s * x;
   4144 					} else if ( l != m ) {
   4145 						H[k][k-1] = -H[k][k-1];
   4146 					}
   4147 					p = p + s;
   4148 					x = p / s;
   4149 					y = q / s;
   4150 					z = r / s;
   4151 					q = q / p;
   4152 					r = r / p;
   4153 
   4154 					// modify row
   4155 					for ( j = k; j < numRows; j++ ) {
   4156 						p = H[k][j] + q * H[k+1][j];
   4157 						if ( notlast ) {
   4158 							p = p + r * H[k+2][j];
   4159 							H[k+2][j] = H[k+2][j] - p * z;
   4160 						}
   4161 						H[k][j] = H[k][j] - p * x;
   4162 						H[k+1][j] = H[k+1][j] - p * y;
   4163 					}
   4164 
   4165 					// modify column
   4166 					for ( i = 0; i <= Min( n, k + 3 ); i++ ) {
   4167 						p = x * H[i][k] + y * H[i][k+1];
   4168 						if ( notlast ) {
   4169 							p = p + z * H[i][k+2];
   4170 							H[i][k+2] = H[i][k+2] - p * r;
   4171 						}
   4172 						H[i][k] = H[i][k] - p;
   4173 						H[i][k+1] = H[i][k+1] - p * q;
   4174 					}
   4175 
   4176 					// accumulate transformations
   4177 					for ( i = low; i <= high; i++ ) {
   4178 						p = x * (*this)[i][k] + y * (*this)[i][k+1];
   4179 						if ( notlast ) {
   4180 							p = p + z * (*this)[i][k+2];
   4181 							(*this)[i][k+2] = (*this)[i][k+2] - p * r;
   4182 						}
   4183 						(*this)[i][k] = (*this)[i][k] - p;
   4184 						(*this)[i][k+1] = (*this)[i][k+1] - p * q;
   4185 					}
   4186 				}
   4187 			}
   4188 		}
   4189 	}
   4190 	
   4191 	// backsubstitute to find vectors of upper triangular form
   4192 	if ( norm == 0.0f ) {
   4193 		return false;
   4194 	}
   4195 
   4196 	for ( n = numRows-1; n >= 0; n-- ) {
   4197 		p = realEigenValues[n];
   4198 		q = imaginaryEigenValues[n];
   4199 
   4200 		if ( q == 0.0f ) {		// real vector
   4201 			int l = n;
   4202 			H[n][n] = 1.0f;
   4203 			for ( i = n-1; i >= 0; i-- ) {
   4204 				w = H[i][i] - p;
   4205 				r = 0.0f;
   4206 				for ( j = l; j <= n; j++ ) {
   4207 					r = r + H[i][j] * H[j][n];
   4208 				}
   4209 				if ( imaginaryEigenValues[i] < 0.0f ) {
   4210 					z = w;
   4211 					s = r;
   4212 				} else {
   4213 					l = i;
   4214 					if ( imaginaryEigenValues[i] == 0.0f ) {
   4215 						if ( w != 0.0f ) {
   4216 							H[i][n] = -r / w;
   4217 						} else {
   4218 							H[i][n] = -r / ( eps * norm );
   4219 						}
   4220 					} else {		// solve real equations
   4221 						x = H[i][i+1];
   4222 						y = H[i+1][i];
   4223 						q = ( realEigenValues[i] - p ) * ( realEigenValues[i] - p ) + imaginaryEigenValues[i] * imaginaryEigenValues[i];
   4224 						t = ( x * s - z * r ) / q;
   4225 						H[i][n] = t;
   4226 						if ( idMath::Fabs(x) > idMath::Fabs( z ) ) {
   4227 							H[i+1][n] = ( -r - w * t ) / x;
   4228 						} else {
   4229 							H[i+1][n] = ( -s - y * t ) / z;
   4230 						}
   4231 					}
   4232 
   4233 					// overflow control
   4234 					t = idMath::Fabs(H[i][n]);
   4235 					if ( ( eps * t ) * t > 1 ) {
   4236 						for ( j = i; j <= n; j++ ) {
   4237 							H[j][n] = H[j][n] / t;
   4238 						}
   4239 					}
   4240 				}
   4241 			}
   4242 		} else if ( q < 0.0f ) {	// complex vector
   4243 			int l = n-1;
   4244 
   4245 			// last vector component imaginary so matrix is triangular
   4246 			if ( idMath::Fabs( H[n][n-1] ) > idMath::Fabs( H[n-1][n] ) ) {
   4247 				H[n-1][n-1] = q / H[n][n-1];
   4248 				H[n-1][n] = -( H[n][n] - p ) / H[n][n-1];
   4249 			} else {
   4250 				ComplexDivision( 0.0f, -H[n-1][n], H[n-1][n-1]-p, q, H[n-1][n-1], H[n-1][n] );
   4251 			}
   4252 			H[n][n-1] = 0.0f;
   4253 			H[n][n] = 1.0f;
   4254 			for ( i = n-2; i >= 0; i-- ) {
   4255 				float ra, sa, vr, vi;
   4256 				ra = 0.0f;
   4257 				sa = 0.0f;
   4258 				for ( j = l; j <= n; j++ ) {
   4259 					ra = ra + H[i][j] * H[j][n-1];
   4260 					sa = sa + H[i][j] * H[j][n];
   4261 				}
   4262 				w = H[i][i] - p;
   4263 
   4264 				if ( imaginaryEigenValues[i] < 0.0f ) {
   4265 					z = w;
   4266 					r = ra;
   4267 					s = sa;
   4268 				} else {
   4269 					l = i;
   4270 					if ( imaginaryEigenValues[i] == 0.0f ) {
   4271 						ComplexDivision( -ra, -sa, w, q, H[i][n-1], H[i][n] );
   4272 					} else {
   4273 						// solve complex equations
   4274 						x = H[i][i+1];
   4275 						y = H[i+1][i];
   4276 						vr = ( realEigenValues[i] - p ) * ( realEigenValues[i] - p ) + imaginaryEigenValues[i] * imaginaryEigenValues[i] - q * q;
   4277 						vi = ( realEigenValues[i] - p ) * 2.0f * q;
   4278 						if ( vr == 0.0f && vi == 0.0f ) {
   4279 							vr = eps * norm * ( idMath::Fabs( w ) + idMath::Fabs( q ) + idMath::Fabs( x ) + idMath::Fabs( y ) + idMath::Fabs( z ) );
   4280 						}
   4281 						ComplexDivision( x * r - z * ra + q * sa, x * s - z * sa - q * ra, vr, vi, H[i][n-1], H[i][n] );
   4282 						if ( idMath::Fabs( x ) > ( idMath::Fabs( z ) + idMath::Fabs( q ) ) ) {
   4283 							H[i+1][n-1] = ( -ra - w * H[i][n-1] + q * H[i][n] ) / x;
   4284 							H[i+1][n] = ( -sa - w * H[i][n] - q * H[i][n-1] ) / x;
   4285 						} else {
   4286 							ComplexDivision( -r - y * H[i][n-1], -s - y * H[i][n], z, q, H[i+1][n-1], H[i+1][n] );
   4287 						}
   4288 					}
   4289 
   4290 					// overflow control
   4291 					t = Max( idMath::Fabs( H[i][n-1] ), idMath::Fabs( H[i][n] ) );
   4292 					if ( ( eps * t ) * t > 1 ) {
   4293 						for ( j = i; j <= n; j++ ) {
   4294 							H[j][n-1] = H[j][n-1] / t;
   4295 							H[j][n] = H[j][n] / t;
   4296 						}
   4297 					}
   4298 				}
   4299 			}
   4300 		}
   4301 	}
   4302 
   4303 	// vectors of isolated roots
   4304 	for ( i = 0; i < numRows; i++ ) {
   4305 		if ( i < low || i > high ) {
   4306 			for ( j = i; j < numRows; j++ ) {
   4307 				(*this)[i][j] = H[i][j];
   4308 			}
   4309 		}
   4310 	}
   4311 
   4312 	// back transformation to get eigenvectors of original matrix
   4313 	for ( j = numRows - 1; j >= low; j-- ) {
   4314 		for ( i = low; i <= high; i++ ) {
   4315 			z = 0.0f;
   4316 			for ( k = low; k <= Min( j, high ); k++ ) {
   4317 				z = z + (*this)[i][k] * H[k][j];
   4318 			}
   4319 			(*this)[i][j] = z;
   4320 		}
   4321 	}
   4322 
   4323 	return true;
   4324 }
   4325 
   4326 /*
   4327 ============
   4328 idMatX::Eigen_Solve
   4329 
   4330   Determine eigen values and eigen vectors for a square matrix.
   4331   The eigen values are stored in 'realEigenValues' and 'imaginaryEigenValues'.
   4332   Column i of the original matrix will store the eigen vector corresponding to the realEigenValues[i] and imaginaryEigenValues[i].
   4333 ============
   4334 */
   4335 bool idMatX::Eigen_Solve( idVecX &realEigenValues, idVecX &imaginaryEigenValues ) {
   4336     idMatX H;
   4337 
   4338 	assert( numRows == numColumns );
   4339 
   4340 	realEigenValues.SetSize( numRows );
   4341 	imaginaryEigenValues.SetSize( numRows );
   4342 
   4343 	H = *this;
   4344 
   4345     // reduce to Hessenberg form
   4346     HessenbergReduction( H );
   4347 
   4348     // reduce Hessenberg to real Schur form
   4349     return HessenbergToRealSchur( H, realEigenValues, imaginaryEigenValues );
   4350 }
   4351 
   4352 /*
   4353 ============
   4354 idMatX::Eigen_SortIncreasing
   4355 ============
   4356 */
   4357 void idMatX::Eigen_SortIncreasing( idVecX &eigenValues ) {
   4358 	for ( int i = 0, j = 0; i <= numRows - 2; i++ ) {
   4359 		j = i;
   4360 		float min = eigenValues[j];
   4361 		for ( int k = i + 1; k < numRows; k++ ) {
   4362 			if ( eigenValues[k] < min ) {
   4363 				j = k;
   4364 				min = eigenValues[j];
   4365 			}
   4366 		}
   4367 		if ( j != i ) {
   4368 			eigenValues.SwapElements( i, j );
   4369 			SwapColumns( i, j );
   4370 		}
   4371 	}
   4372 }
   4373 
   4374 /*
   4375 ============
   4376 idMatX::Eigen_SortDecreasing
   4377 ============
   4378 */
   4379 void idMatX::Eigen_SortDecreasing( idVecX &eigenValues ) {
   4380 	for ( int i = 0, j = 0; i <= numRows - 2; i++ ) {
   4381 		j = i;
   4382 		float max = eigenValues[j];
   4383 		for ( int k = i + 1; k < numRows; k++ ) {
   4384 			if ( eigenValues[k] > max ) {
   4385 				j = k;
   4386 				max = eigenValues[j];
   4387 			}
   4388 		}
   4389 		if ( j != i ) {
   4390 			eigenValues.SwapElements( i, j );
   4391 			SwapColumns( i, j );
   4392 		}
   4393 	}
   4394 }
   4395 
   4396 /*
   4397 ============
   4398 idMatX::DeterminantGeneric
   4399 ============
   4400 */
   4401 float idMatX::DeterminantGeneric() const {
   4402 	int *index;
   4403 	float det;
   4404 	idMatX tmp;
   4405 
   4406 	index = (int *) _alloca16( numRows * sizeof( int ) );
   4407 	tmp.SetData( numRows, numColumns, MATX_ALLOCA( numRows * numColumns ) );
   4408 	tmp = *this;
   4409 
   4410 	if ( !tmp.LU_Factor( index, &det ) ) {
   4411 		return 0.0f;
   4412 	}
   4413 
   4414 	return det;
   4415 }
   4416 
   4417 /*
   4418 ============
   4419 idMatX::InverseSelfGeneric
   4420 ============
   4421 */
   4422 bool idMatX::InverseSelfGeneric() {
   4423 	int i, j, *index;
   4424 	idMatX tmp;
   4425 	idVecX x, b;
   4426 
   4427 	index = (int *) _alloca16( numRows * sizeof( int ) );
   4428 	tmp.SetData( numRows, numColumns, MATX_ALLOCA( numRows * numColumns ) );
   4429 	tmp = *this;
   4430 
   4431 	if ( !tmp.LU_Factor( index ) ) {
   4432 		return false;
   4433 	}
   4434 
   4435 	x.SetData( numRows, VECX_ALLOCA( numRows ) );
   4436 	b.SetData( numRows, VECX_ALLOCA( numRows ) );
   4437 	b.Zero();
   4438 
   4439 	for ( i = 0; i < numRows; i++ ) {
   4440 
   4441 		b[i] = 1.0f;
   4442 		tmp.LU_Solve( x, b, index );
   4443 		for ( j = 0; j < numRows; j++ ) {
   4444 			(*this)[j][i] = x[j];
   4445 		}
   4446 		b[i] = 0.0f;
   4447 	}
   4448 	return true;
   4449 }
   4450 
   4451 /*
   4452 ============
   4453 idMatX::Test
   4454 ============
   4455 */
   4456 void idMatX::Test() {
   4457 	idMatX original, m1, m2, m3, q1, q2, r1, r2;
   4458 	idVecX v, w, u, c, d;
   4459 	int offset, size, *index1, *index2;
   4460 
   4461 	size = 6;
   4462 	original.Random( size, size, 0 );
   4463 	original = original * original.Transpose();
   4464 
   4465 	index1 = (int *) _alloca16( ( size + 1 ) * sizeof( index1[0] ) );
   4466 	index2 = (int *) _alloca16( ( size + 1 ) * sizeof( index2[0] ) );
   4467 
   4468 	/*
   4469 		idMatX::LowerTriangularInverse
   4470 	*/
   4471 
   4472 	m1 = original;
   4473 	m1.ClearUpperTriangle();
   4474 	m2 = m1;
   4475 
   4476 	m2.InverseSelf();
   4477 	m1.LowerTriangularInverse();
   4478 
   4479 	if ( !m1.Compare( m2, 1e-4f ) ) {
   4480 		idLib::common->Warning( "idMatX::LowerTriangularInverse failed" );
   4481 	}
   4482 
   4483 	/*
   4484 		idMatX::UpperTriangularInverse
   4485 	*/
   4486 
   4487 	m1 = original;
   4488 	m1.ClearLowerTriangle();
   4489 	m2 = m1;
   4490 
   4491 	m2.InverseSelf();
   4492 	m1.UpperTriangularInverse();
   4493 
   4494 	if ( !m1.Compare( m2, 1e-4f ) ) {
   4495 		idLib::common->Warning( "idMatX::UpperTriangularInverse failed" );
   4496 	}
   4497 
   4498 	/*
   4499 		idMatX::Inverse_GaussJordan
   4500 	*/
   4501 
   4502 	m1 = original;
   4503 
   4504 	m1.Inverse_GaussJordan();
   4505 	m1 *= original;
   4506 
   4507 	if ( !m1.IsIdentity( 1e-4f ) ) {
   4508 		idLib::common->Warning( "idMatX::Inverse_GaussJordan failed" );
   4509 	}
   4510 
   4511 	/*
   4512 		idMatX::Inverse_UpdateRankOne
   4513 	*/
   4514 
   4515 	m1 = original;
   4516 	m2 = original;
   4517 
   4518 	w.Random( size, 1 );
   4519 	v.Random( size, 2 );
   4520 
   4521 	// invert m1
   4522 	m1.Inverse_GaussJordan();
   4523 
   4524 	// modify and invert m2 
   4525 	m2.Update_RankOne( v, w, 1.0f );
   4526 	if ( !m2.Inverse_GaussJordan() ) {
   4527 		assert( 0 );
   4528 	}
   4529 
   4530 	// update inverse of m1
   4531 	m1.Inverse_UpdateRankOne( v, w, 1.0f );
   4532 
   4533 	if ( !m1.Compare( m2, 1e-4f ) ) {
   4534 		idLib::common->Warning( "idMatX::Inverse_UpdateRankOne failed" );
   4535 	}
   4536 
   4537 	/*
   4538 		idMatX::Inverse_UpdateRowColumn
   4539 	*/
   4540 
   4541 	for ( offset = 0; offset < size; offset++ ) {
   4542 		m1 = original;
   4543 		m2 = original;
   4544 
   4545 		v.Random( size, 1 );
   4546 		w.Random( size, 2 );
   4547 		w[offset] = 0.0f;
   4548 
   4549 		// invert m1
   4550 		m1.Inverse_GaussJordan();
   4551 
   4552 		// modify and invert m2
   4553 		m2.Update_RowColumn( v, w, offset );
   4554 		if ( !m2.Inverse_GaussJordan() ) {
   4555 			assert( 0 );
   4556 		}
   4557 
   4558 		// update inverse of m1
   4559 		m1.Inverse_UpdateRowColumn( v, w, offset );
   4560 
   4561 		if ( !m1.Compare( m2, 1e-3f ) ) {
   4562 			idLib::common->Warning( "idMatX::Inverse_UpdateRowColumn failed" );
   4563 		}
   4564 	}
   4565 
   4566 	/*
   4567 		idMatX::Inverse_UpdateIncrement
   4568 	*/
   4569 
   4570 	m1 = original;
   4571 	m2 = original;
   4572 
   4573 	v.Random( size + 1, 1 );
   4574 	w.Random( size + 1, 2 );
   4575 	w[size] = 0.0f;
   4576 
   4577 	// invert m1
   4578 	m1.Inverse_GaussJordan();
   4579 
   4580 	// modify and invert m2 
   4581 	m2.Update_Increment( v, w );
   4582 	if ( !m2.Inverse_GaussJordan() ) {
   4583 		assert( 0 );
   4584 	}
   4585 
   4586 	// update inverse of m1
   4587 	m1.Inverse_UpdateIncrement( v, w );
   4588 
   4589 	if ( !m1.Compare( m2, 1e-4f ) ) {
   4590 		idLib::common->Warning( "idMatX::Inverse_UpdateIncrement failed" );
   4591 	}
   4592 
   4593 	/*
   4594 		idMatX::Inverse_UpdateDecrement
   4595 	*/
   4596 
   4597 	for ( offset = 0; offset < size; offset++ ) {
   4598 		m1 = original;
   4599 		m2 = original;
   4600 
   4601 		v.SetSize( 6 );
   4602 		w.SetSize( 6 );
   4603 		for ( int i = 0; i < size; i++ ) {
   4604 			v[i] = original[i][offset];
   4605 			w[i] = original[offset][i];
   4606 		}
   4607 
   4608 		// invert m1
   4609 		m1.Inverse_GaussJordan();
   4610 
   4611 		// modify and invert m2
   4612 		m2.Update_Decrement( offset );
   4613 		if ( !m2.Inverse_GaussJordan() ) {
   4614 			assert( 0 );
   4615 		}
   4616 
   4617 		// update inverse of m1
   4618 		m1.Inverse_UpdateDecrement( v, w, offset );
   4619 
   4620 		if ( !m1.Compare( m2, 1e-3f ) ) {
   4621 			idLib::common->Warning( "idMatX::Inverse_UpdateDecrement failed" );
   4622 		}
   4623 	}
   4624 
   4625 	/*
   4626 		idMatX::LU_Factor
   4627 	*/
   4628 
   4629 	m1 = original;
   4630 
   4631 	m1.LU_Factor( NULL );	// no pivoting
   4632 	m1.LU_UnpackFactors( m2, m3 );
   4633 	m1 = m2 * m3;
   4634 
   4635 	if ( !original.Compare( m1, 1e-4f ) ) {
   4636 		idLib::common->Warning( "idMatX::LU_Factor failed" );
   4637 	}
   4638 
   4639 	/*
   4640 		idMatX::LU_UpdateRankOne
   4641 	*/
   4642 
   4643 	m1 = original;
   4644 	m2 = original;
   4645 
   4646 	w.Random( size, 1 );
   4647 	v.Random( size, 2 );
   4648 
   4649 	// factor m1
   4650 	m1.LU_Factor( index1 );
   4651 
   4652 	// modify and factor m2 
   4653 	m2.Update_RankOne( v, w, 1.0f );
   4654 	if ( !m2.LU_Factor( index2 ) ) {
   4655 		assert( 0 );
   4656 	}
   4657 	m2.LU_MultiplyFactors( m3, index2 );
   4658 	m2 = m3;
   4659 
   4660 	// update factored m1
   4661 	m1.LU_UpdateRankOne( v, w, 1.0f, index1 );
   4662 	m1.LU_MultiplyFactors( m3, index1 );
   4663 	m1 = m3;
   4664 
   4665 	if ( !m1.Compare( m2, 1e-4f ) ) {
   4666 		idLib::common->Warning( "idMatX::LU_UpdateRankOne failed" );
   4667 	}
   4668 
   4669 	/*
   4670 		idMatX::LU_UpdateRowColumn
   4671 	*/
   4672 
   4673 	for ( offset = 0; offset < size; offset++ ) {
   4674 		m1 = original;
   4675 		m2 = original;
   4676 
   4677 		v.Random( size, 1 );
   4678 		w.Random( size, 2 );
   4679 		w[offset] = 0.0f;
   4680 
   4681 		// factor m1
   4682 		m1.LU_Factor( index1 );
   4683 
   4684 		// modify and factor m2
   4685 		m2.Update_RowColumn( v, w, offset );
   4686 		if ( !m2.LU_Factor( index2 ) ) {
   4687 			assert( 0 );
   4688 		}
   4689 		m2.LU_MultiplyFactors( m3, index2 );
   4690 		m2 = m3;
   4691 
   4692 		// update m1
   4693 		m1.LU_UpdateRowColumn( v, w, offset, index1  );
   4694 		m1.LU_MultiplyFactors( m3, index1 );
   4695 		m1 = m3;
   4696 
   4697 		if ( !m1.Compare( m2, 1e-3f ) ) {
   4698 			idLib::common->Warning( "idMatX::LU_UpdateRowColumn failed" );
   4699 		}
   4700 	}
   4701 
   4702 	/*
   4703 		idMatX::LU_UpdateIncrement
   4704 	*/
   4705 
   4706 	m1 = original;
   4707 	m2 = original;
   4708 
   4709 	v.Random( size + 1, 1 );
   4710 	w.Random( size + 1, 2 );
   4711 	w[size] = 0.0f;
   4712 
   4713 	// factor m1
   4714 	m1.LU_Factor( index1 );
   4715 
   4716 	// modify and factor m2 
   4717 	m2.Update_Increment( v, w );
   4718 	if ( !m2.LU_Factor( index2 ) ) {
   4719 		assert( 0 );
   4720 	}
   4721 	m2.LU_MultiplyFactors( m3, index2 );
   4722 	m2 = m3;
   4723 
   4724 	// update factored m1
   4725 	m1.LU_UpdateIncrement( v, w, index1 );
   4726 	m1.LU_MultiplyFactors( m3, index1 );
   4727 	m1 = m3;
   4728 
   4729 	if ( !m1.Compare( m2, 1e-4f ) ) {
   4730 		idLib::common->Warning( "idMatX::LU_UpdateIncrement failed" );
   4731 	}
   4732 
   4733 	/*
   4734 		idMatX::LU_UpdateDecrement
   4735 	*/
   4736 
   4737 	for ( offset = 0; offset < size; offset++ ) {
   4738 		m1 = original;
   4739 		m2 = original;
   4740 
   4741 		v.SetSize( 6 );
   4742 		w.SetSize( 6 );
   4743 		for ( int i = 0; i < size; i++ ) {
   4744 			v[i] = original[i][offset];
   4745 			w[i] = original[offset][i];
   4746 		}
   4747 
   4748 		// factor m1
   4749 		m1.LU_Factor( index1 );
   4750 
   4751 		// modify and factor m2
   4752 		m2.Update_Decrement( offset );
   4753 		if ( !m2.LU_Factor( index2 ) ) {
   4754 			assert( 0 );
   4755 		}
   4756 		m2.LU_MultiplyFactors( m3, index2 );
   4757 		m2 = m3;
   4758 
   4759 		u.SetSize( 6 );
   4760 		for ( int i = 0; i < size; i++ ) {
   4761 			u[i] = original[index1[offset]][i];
   4762 		}
   4763 
   4764 		// update factors of m1
   4765 		m1.LU_UpdateDecrement( v, w, u, offset, index1 );
   4766 		m1.LU_MultiplyFactors( m3, index1 );
   4767 		m1 = m3;
   4768 
   4769 		if ( !m1.Compare( m2, 1e-3f ) ) {
   4770 			idLib::common->Warning( "idMatX::LU_UpdateDecrement failed" );
   4771 		}
   4772 	}
   4773 
   4774 	/*
   4775 		idMatX::LU_Inverse
   4776 	*/
   4777 
   4778 	m2 = original;
   4779 
   4780 	m2.LU_Factor( NULL );
   4781 	m2.LU_Inverse( m1, NULL );
   4782 	m1 *= original;
   4783 
   4784 	if ( !m1.IsIdentity( 1e-4f ) ) {
   4785 		idLib::common->Warning( "idMatX::LU_Inverse failed" );
   4786 	}
   4787 
   4788 	/*
   4789 		idMatX::QR_Factor
   4790 	*/
   4791 
   4792 	c.SetSize( size );
   4793 	d.SetSize( size );
   4794 
   4795 	m1 = original;
   4796 
   4797 	m1.QR_Factor( c, d );
   4798 	m1.QR_UnpackFactors( q1, r1, c, d );
   4799 	m1 = q1 * r1;
   4800 
   4801 	if ( !original.Compare( m1, 1e-4f ) ) {
   4802 		idLib::common->Warning( "idMatX::QR_Factor failed" );
   4803 	}
   4804 
   4805 	/*
   4806 		idMatX::QR_UpdateRankOne
   4807 	*/
   4808 
   4809 	c.SetSize( size );
   4810 	d.SetSize( size );
   4811 
   4812 	m1 = original;
   4813 	m2 = original;
   4814 
   4815 	w.Random( size, 0 );
   4816 	v = w;
   4817 
   4818 	// factor m1
   4819 	m1.QR_Factor( c, d );
   4820 	m1.QR_UnpackFactors( q1, r1, c, d );
   4821 
   4822 	// modify and factor m2 
   4823 	m2.Update_RankOne( v, w, 1.0f );
   4824 	if ( !m2.QR_Factor( c, d ) ) {
   4825 		assert( 0 );
   4826 	}
   4827 	m2.QR_UnpackFactors( q2, r2, c, d );
   4828 	m2 = q2 * r2;
   4829 
   4830 	// update factored m1
   4831 	q1.QR_UpdateRankOne( r1, v, w, 1.0f );
   4832 	m1 = q1 * r1;
   4833 
   4834 	if ( !m1.Compare( m2, 1e-4f ) ) {
   4835 		idLib::common->Warning( "idMatX::QR_UpdateRankOne failed" );
   4836 	}
   4837 
   4838 	/*
   4839 		idMatX::QR_UpdateRowColumn
   4840 	*/
   4841 
   4842 	for ( offset = 0; offset < size; offset++ ) {
   4843 		c.SetSize( size );
   4844 		d.SetSize( size );
   4845 
   4846 		m1 = original;
   4847 		m2 = original;
   4848 
   4849 		v.Random( size, 1 );
   4850 		w.Random( size, 2 );
   4851 		w[offset] = 0.0f;
   4852 
   4853 		// factor m1
   4854 		m1.QR_Factor( c, d );
   4855 		m1.QR_UnpackFactors( q1, r1, c, d );
   4856 
   4857 		// modify and factor m2
   4858 		m2.Update_RowColumn( v, w, offset );
   4859 		if ( !m2.QR_Factor( c, d ) ) {
   4860 			assert( 0 );
   4861 		}
   4862 		m2.QR_UnpackFactors( q2, r2, c, d );
   4863 		m2 = q2 * r2;
   4864 
   4865 		// update m1
   4866 		q1.QR_UpdateRowColumn( r1, v, w, offset );
   4867 		m1 = q1 * r1;
   4868 
   4869 		if ( !m1.Compare( m2, 1e-3f ) ) {
   4870 			idLib::common->Warning( "idMatX::QR_UpdateRowColumn failed" );
   4871 		}
   4872 	}
   4873 
   4874 	/*
   4875 		idMatX::QR_UpdateIncrement
   4876 	*/
   4877 
   4878 	c.SetSize( size+1 );
   4879 	d.SetSize( size+1 );
   4880 
   4881 	m1 = original;
   4882 	m2 = original;
   4883 
   4884 	v.Random( size + 1, 1 );
   4885 	w.Random( size + 1, 2 );
   4886 	w[size] = 0.0f;
   4887 
   4888 	// factor m1
   4889 	m1.QR_Factor( c, d );
   4890 	m1.QR_UnpackFactors( q1, r1, c, d );
   4891 
   4892 	// modify and factor m2 
   4893 	m2.Update_Increment( v, w );
   4894 	if ( !m2.QR_Factor( c, d ) ) {
   4895 		assert( 0 );
   4896 	}
   4897 	m2.QR_UnpackFactors( q2, r2, c, d );
   4898 	m2 = q2 * r2;
   4899 
   4900 	// update factored m1
   4901 	q1.QR_UpdateIncrement( r1, v, w );
   4902 	m1 = q1 * r1;
   4903 
   4904 	if ( !m1.Compare( m2, 1e-4f ) ) {
   4905 		idLib::common->Warning( "idMatX::QR_UpdateIncrement failed" );
   4906 	}
   4907 
   4908 	/*
   4909 		idMatX::QR_UpdateDecrement
   4910 	*/
   4911 
   4912 	for ( offset = 0; offset < size; offset++ ) {
   4913 		c.SetSize( size+1 );
   4914 		d.SetSize( size+1 );
   4915 
   4916 		m1 = original;
   4917 		m2 = original;
   4918 
   4919 		v.SetSize( 6 );
   4920 		w.SetSize( 6 );
   4921 		for ( int i = 0; i < size; i++ ) {
   4922 			v[i] = original[i][offset];
   4923 			w[i] = original[offset][i];
   4924 		}
   4925 
   4926 		// factor m1
   4927 		m1.QR_Factor( c, d );
   4928 		m1.QR_UnpackFactors( q1, r1, c, d );
   4929 
   4930 		// modify and factor m2
   4931 		m2.Update_Decrement( offset );
   4932 		if ( !m2.QR_Factor( c, d ) ) {
   4933 			assert( 0 );
   4934 		}
   4935 		m2.QR_UnpackFactors( q2, r2, c, d );
   4936 		m2 = q2 * r2;
   4937 
   4938 		// update factors of m1
   4939 		q1.QR_UpdateDecrement( r1, v, w, offset );
   4940 		m1 = q1 * r1;
   4941 
   4942 		if ( !m1.Compare( m2, 1e-3f ) ) {
   4943 			idLib::common->Warning( "idMatX::QR_UpdateDecrement failed" );
   4944 		}
   4945 	}
   4946 
   4947 	/*
   4948 		idMatX::QR_Inverse
   4949 	*/
   4950 
   4951 	m2 = original;
   4952 
   4953 	m2.QR_Factor( c, d );
   4954 	m2.QR_Inverse( m1, c, d );
   4955 	m1 *= original;
   4956 
   4957 	if ( !m1.IsIdentity( 1e-4f ) ) {
   4958 		idLib::common->Warning( "idMatX::QR_Inverse failed" );
   4959 	}
   4960 
   4961 	/*
   4962 		idMatX::SVD_Factor
   4963 	*/
   4964 
   4965 	m1 = original;
   4966 	m3.Zero( size, size );
   4967 	w.Zero( size );
   4968 
   4969 	m1.SVD_Factor( w, m3 );
   4970 	m2.Diag( w );
   4971 	m3.TransposeSelf();
   4972 	m1 = m1 * m2 * m3;
   4973 
   4974 	if ( !original.Compare( m1, 1e-4f ) ) {
   4975 		idLib::common->Warning( "idMatX::SVD_Factor failed" );
   4976 	}
   4977 
   4978 	/*
   4979 		idMatX::SVD_Inverse
   4980 	*/
   4981 
   4982 	m2 = original;
   4983 
   4984 	m2.SVD_Factor( w, m3 );
   4985 	m2.SVD_Inverse( m1, w, m3 );
   4986 	m1 *= original;
   4987 
   4988 	if ( !m1.IsIdentity( 1e-4f ) ) {
   4989 		idLib::common->Warning( "idMatX::SVD_Inverse failed" );
   4990 	}
   4991 
   4992 	/*
   4993 		idMatX::Cholesky_Factor
   4994 	*/
   4995 
   4996 	m1 = original;
   4997 
   4998 	m1.Cholesky_Factor();
   4999 	m1.Cholesky_MultiplyFactors( m2 );
   5000 
   5001 	if ( !original.Compare( m2, 1e-4f ) ) {
   5002 		idLib::common->Warning( "idMatX::Cholesky_Factor failed" );
   5003 	}
   5004 
   5005 	/*
   5006 		idMatX::Cholesky_UpdateRankOne
   5007 	*/
   5008 
   5009 	m1 = original;
   5010 	m2 = original;
   5011 
   5012 	w.Random( size, 0 );
   5013 
   5014 	// factor m1
   5015 	m1.Cholesky_Factor();
   5016 	m1.ClearUpperTriangle();
   5017 
   5018 	// modify and factor m2 
   5019 	m2.Update_RankOneSymmetric( w, 1.0f );
   5020 	if ( !m2.Cholesky_Factor() ) {
   5021 		assert( 0 );
   5022 	}
   5023 	m2.ClearUpperTriangle();
   5024 
   5025 	// update factored m1
   5026 	m1.Cholesky_UpdateRankOne( w, 1.0f, 0 );
   5027 
   5028 	if ( !m1.Compare( m2, 1e-4f ) ) {
   5029 		idLib::common->Warning( "idMatX::Cholesky_UpdateRankOne failed" );
   5030 	}
   5031 
   5032 	/*
   5033 		idMatX::Cholesky_UpdateRowColumn
   5034 	*/
   5035 
   5036 	for ( offset = 0; offset < size; offset++ ) {
   5037 		m1 = original;
   5038 		m2 = original;
   5039 
   5040 		// factor m1
   5041 		m1.Cholesky_Factor();
   5042 		m1.ClearUpperTriangle();
   5043 
   5044 		int pdtable[] = { 1, 0, 1, 0, 0, 0 };
   5045 		w.Random( size, pdtable[offset] );
   5046 		w *= 0.1f;
   5047 
   5048 		// modify and factor m2
   5049 		m2.Update_RowColumnSymmetric( w, offset );
   5050 		if ( !m2.Cholesky_Factor() ) {
   5051 			assert( 0 );
   5052 		}
   5053 		m2.ClearUpperTriangle();
   5054 
   5055 		// update m1
   5056 		m1.Cholesky_UpdateRowColumn( w, offset );
   5057 
   5058 		if ( !m1.Compare( m2, 1e-3f ) ) {
   5059 			idLib::common->Warning( "idMatX::Cholesky_UpdateRowColumn failed" );
   5060 		}
   5061 	}
   5062 
   5063 	/*
   5064 		idMatX::Cholesky_UpdateIncrement
   5065 	*/
   5066 
   5067 	m1.Random( size + 1, size + 1, 0 );
   5068 	m3 = m1 * m1.Transpose();
   5069 
   5070 	m1.SquareSubMatrix( m3, size );
   5071 	m2 = m1;
   5072 
   5073 	w.SetSize( size + 1 );
   5074 	for ( int i = 0; i < size + 1; i++ ) {
   5075 		w[i] = m3[size][i];
   5076 	}
   5077 
   5078 	// factor m1
   5079 	m1.Cholesky_Factor();
   5080 
   5081 	// modify and factor m2 
   5082 	m2.Update_IncrementSymmetric( w );
   5083 	if ( !m2.Cholesky_Factor() ) {
   5084 		assert( 0 );
   5085 	}
   5086 
   5087 	// update factored m1
   5088 	m1.Cholesky_UpdateIncrement( w );
   5089 
   5090 	m1.ClearUpperTriangle();
   5091 	m2.ClearUpperTriangle();
   5092 
   5093 	if ( !m1.Compare( m2, 1e-4f ) ) {
   5094 		idLib::common->Warning( "idMatX::Cholesky_UpdateIncrement failed" );
   5095 	}
   5096 
   5097 	/*
   5098 		idMatX::Cholesky_UpdateDecrement
   5099 	*/
   5100 
   5101 	for ( offset = 0; offset < size; offset += size - 1 ) {
   5102 		m1 = original;
   5103 		m2 = original;
   5104 
   5105 		v.SetSize( 6 );
   5106 		for ( int i = 0; i < size; i++ ) {
   5107 			v[i] = original[i][offset];
   5108 		}
   5109 
   5110 		// factor m1
   5111 		m1.Cholesky_Factor();
   5112 
   5113 		// modify and factor m2
   5114 		m2.Update_Decrement( offset );
   5115 		if ( !m2.Cholesky_Factor() ) {
   5116 			assert( 0 );
   5117 		}
   5118 
   5119 		// update factors of m1
   5120 		m1.Cholesky_UpdateDecrement( v, offset );
   5121 
   5122 		if ( !m1.Compare( m2, 1e-3f ) ) {
   5123 			idLib::common->Warning( "idMatX::Cholesky_UpdateDecrement failed" );
   5124 		}
   5125 	}
   5126 
   5127 	/*
   5128 		idMatX::Cholesky_Inverse
   5129 	*/
   5130 
   5131 	m2 = original;
   5132 
   5133 	m2.Cholesky_Factor();
   5134 	m2.Cholesky_Inverse( m1 );
   5135 	m1 *= original;
   5136 
   5137 	if ( !m1.IsIdentity( 1e-4f ) ) {
   5138 		idLib::common->Warning( "idMatX::Cholesky_Inverse failed" );
   5139 	}
   5140 
   5141 	/*
   5142 		idMatX::LDLT_Factor
   5143 	*/
   5144 
   5145 	m1 = original;
   5146 
   5147 	m1.LDLT_Factor();
   5148 	m1.LDLT_MultiplyFactors( m2 );
   5149 
   5150 	if ( !original.Compare( m2, 1e-4f ) ) {
   5151 		idLib::common->Warning( "idMatX::LDLT_Factor failed" );
   5152 	}
   5153 
   5154 	m1.LDLT_UnpackFactors( m2, m3 );
   5155 	m2 = m2 * m3 * m2.Transpose();
   5156 
   5157 	if ( !original.Compare( m2, 1e-4f ) ) {
   5158 		idLib::common->Warning( "idMatX::LDLT_Factor failed" );
   5159 	}
   5160 
   5161 	/*
   5162 		idMatX::LDLT_UpdateRankOne
   5163 	*/
   5164 
   5165 	m1 = original;
   5166 	m2 = original;
   5167 
   5168 	w.Random( size, 0 );
   5169 
   5170 	// factor m1
   5171 	m1.LDLT_Factor();
   5172 	m1.ClearUpperTriangle();
   5173 
   5174 	// modify and factor m2 
   5175 	m2.Update_RankOneSymmetric( w, 1.0f );
   5176 	if ( !m2.LDLT_Factor() ) {
   5177 		assert( 0 );
   5178 	}
   5179 	m2.ClearUpperTriangle();
   5180 
   5181 	// update factored m1
   5182 	m1.LDLT_UpdateRankOne( w, 1.0f, 0 );
   5183 
   5184 	if ( !m1.Compare( m2, 1e-4f ) ) {
   5185 		idLib::common->Warning( "idMatX::LDLT_UpdateRankOne failed" );
   5186 	}
   5187 
   5188 	/*
   5189 		idMatX::LDLT_UpdateRowColumn
   5190 	*/
   5191 
   5192 	for ( offset = 0; offset < size; offset++ ) {
   5193 		m1 = original;
   5194 		m2 = original;
   5195 
   5196 		w.Random( size, 0 );
   5197 
   5198 		// factor m1
   5199 		m1.LDLT_Factor();
   5200 		m1.ClearUpperTriangle();
   5201 
   5202 		// modify and factor m2
   5203 		m2.Update_RowColumnSymmetric( w, offset );
   5204 		if ( !m2.LDLT_Factor() ) {
   5205 			assert( 0 );
   5206 		}
   5207 		m2.ClearUpperTriangle();
   5208 
   5209 		// update m1
   5210 		m1.LDLT_UpdateRowColumn( w, offset );
   5211 
   5212 		if ( !m1.Compare( m2, 1e-3f ) ) {
   5213 			idLib::common->Warning( "idMatX::LDLT_UpdateRowColumn failed" );
   5214 		}
   5215 	}
   5216 
   5217 	/*
   5218 		idMatX::LDLT_UpdateIncrement
   5219 	*/
   5220 
   5221 	m1.Random( size + 1, size + 1, 0 );
   5222 	m3 = m1 * m1.Transpose();
   5223 
   5224 	m1.SquareSubMatrix( m3, size );
   5225 	m2 = m1;
   5226 
   5227 	w.SetSize( size + 1 );
   5228 	for ( int i = 0; i < size + 1; i++ ) {
   5229 		w[i] = m3[size][i];
   5230 	}
   5231 
   5232 	// factor m1
   5233 	m1.LDLT_Factor();
   5234 
   5235 	// modify and factor m2 
   5236 	m2.Update_IncrementSymmetric( w );
   5237 	if ( !m2.LDLT_Factor() ) {
   5238 		assert( 0 );
   5239 	}
   5240 
   5241 	// update factored m1
   5242 	m1.LDLT_UpdateIncrement( w );
   5243 
   5244 	m1.ClearUpperTriangle();
   5245 	m2.ClearUpperTriangle();
   5246 
   5247 	if ( !m1.Compare( m2, 1e-4f ) ) {
   5248 		idLib::common->Warning( "idMatX::LDLT_UpdateIncrement failed" );
   5249 	}
   5250 
   5251 	/*
   5252 		idMatX::LDLT_UpdateDecrement
   5253 	*/
   5254 
   5255 	for ( offset = 0; offset < size; offset++ ) {
   5256 		m1 = original;
   5257 		m2 = original;
   5258 
   5259 		v.SetSize( 6 );
   5260 		for ( int i = 0; i < size; i++ ) {
   5261 			v[i] = original[i][offset];
   5262 		}
   5263 
   5264 		// factor m1
   5265 		m1.LDLT_Factor();
   5266 
   5267 		// modify and factor m2
   5268 		m2.Update_Decrement( offset );
   5269 		if ( !m2.LDLT_Factor() ) {
   5270 			assert( 0 );
   5271 		}
   5272 
   5273 		// update factors of m1
   5274 		m1.LDLT_UpdateDecrement( v, offset );
   5275 
   5276 		if ( !m1.Compare( m2, 1e-3f ) ) {
   5277 			idLib::common->Warning( "idMatX::LDLT_UpdateDecrement failed" );
   5278 		}
   5279 	}
   5280 
   5281 	/*
   5282 		idMatX::LDLT_Inverse
   5283 	*/
   5284 
   5285 	m2 = original;
   5286 
   5287 	m2.LDLT_Factor();
   5288 	m2.LDLT_Inverse( m1 );
   5289 	m1 *= original;
   5290 
   5291 	if ( !m1.IsIdentity( 1e-4f ) ) {
   5292 		idLib::common->Warning( "idMatX::LDLT_Inverse failed" );
   5293 	}
   5294 
   5295 	/*
   5296 		idMatX::Eigen_SolveSymmetricTriDiagonal
   5297 	*/
   5298 
   5299 	m3 = original;
   5300 	m3.TriDiagonal_ClearTriangles();
   5301 	m1 = m3;
   5302 
   5303 	v.SetSize( size );
   5304 
   5305 	m1.Eigen_SolveSymmetricTriDiagonal( v );
   5306 
   5307 	m3.TransposeMultiply( m2, m1 );
   5308 
   5309 	for ( int i = 0; i < size; i++ ) {
   5310 		for ( int j = 0; j < size; j++ ) {
   5311 			m1[i][j] *= v[j];
   5312 		}
   5313 	}
   5314 
   5315 	if ( !m1.Compare( m2, 1e-4f ) ) {
   5316 		idLib::common->Warning( "idMatX::Eigen_SolveSymmetricTriDiagonal failed" );
   5317 	}
   5318 
   5319 	/*
   5320 		idMatX::Eigen_SolveSymmetric
   5321 	*/
   5322 
   5323 	m3 = original;
   5324 	m1 = m3;
   5325 
   5326 	v.SetSize( size );
   5327 
   5328 	m1.Eigen_SolveSymmetric( v );
   5329 
   5330 	m3.TransposeMultiply( m2, m1 );
   5331 
   5332 	for ( int i = 0; i < size; i++ ) {
   5333 		for ( int j = 0; j < size; j++ ) {
   5334 			m1[i][j] *= v[j];
   5335 		}
   5336 	}
   5337 
   5338 	if ( !m1.Compare( m2, 1e-4f ) ) {
   5339 		idLib::common->Warning( "idMatX::Eigen_SolveSymmetric failed" );
   5340 	}
   5341 
   5342 	/*
   5343 		idMatX::Eigen_Solve
   5344 	*/
   5345 
   5346 	m3 = original;
   5347 	m1 = m3;
   5348 
   5349 	v.SetSize( size );
   5350 	w.SetSize( size );
   5351 
   5352 	m1.Eigen_Solve( v, w );
   5353 
   5354 	m3.TransposeMultiply( m2, m1 );
   5355 
   5356 	for ( int i = 0; i < size; i++ ) {
   5357 		for ( int j = 0; j < size; j++ ) {
   5358 			m1[i][j] *= v[j];
   5359 		}
   5360 	}
   5361 
   5362 	if ( !m1.Compare( m2, 1e-4f ) ) {
   5363 		idLib::common->Warning( "idMatX::Eigen_Solve failed" );
   5364 	}
   5365 }