// (FLOAT) function computes inverse of a symmetric 4x4 matrix A
void f4x4matrixAeqInvSymA(float **A)
{
	// global arrays used: ftmpA4x1, ftmpA4x4

	// local variables
	int32 i, j, k;		// loop counters
	float fdet;			// matrix determinant

	// set tmpA4x1 to the eigenvalues and tmpA4x4 to the eigenvectors of A
	// function eigencompute does not use any additional global arrays
	eigencompute(A, 4, ftmpA4x1, ftmpA4x4);

	// check if the matrix A is singular by computing its determinant from the product of its eigenvalues
	fdet = 1.0F;
	for (i = 0; i < 4; i++)
		fdet *= ftmpA4x1[i][0];

	// compute the inverse if the determinant is non-zero
	if (fdet != 0.0F)
	{
		// take the reciprocal of the eigenvalues
		for (i = 0; i < 4; i++)
			ftmpA4x1[i][0] = 1.0F / ftmpA4x1[i][0];

		// set A to be eigenvectors . diag(1.0F / eigenvalues) . eigenvectors^T
		for (i = 0; i < 4; i++) // loop over rows i
		{
			for (j = 0; j < 4; j++) // loop over columns j
			{
				A[i][j] = 0.0F;
				for (k = 0; k < 4; k++)
				{
					A[i][j] += ftmpA4x4[i][k] * ftmpA4x1[k][0] * ftmpA4x4[j][k];
				}
			}
		}
	}
	else
	{
		// the matrix A is singular so return the identity matrix
		fmatrixAeqI(A, 4);
	}

	return;
}
void ResetMagCalibrationFunc(void)
{
	int32 j, k, l;   // loop counters  

	// initialise the calibration hard and soft iron estimate to null 
	fmatrixAeqI(finvW, 3);
	fVx = fVy = fVz = 0.;
	fB = 0.0F;
	fFitErrorpc = 1000.0F; 
	validmagcal = 0;

	// set the loop counter to 0 to denote first pass 
	loopcounter = 0;

	// set magnetic buffer index to invalid value -1 to denote invalid
	MagBufferCount = 0;
	for (j = 0; j < MAGBUFFSIZE; j++)
		for (k = 0; k < MAGBUFFSIZE; k++)
			for (l = 0; l < MAGBUFFSIZE; l++)
				iMagBuff[j][k][l].index = -1;

	return;
}
Exemple #3
0
// function uses Gauss-Jordan elimination to compute the inverse of matrix A in situ
// on exit, A is replaced with its inverse
void fmatrixAeqInvA(float *A[], int8 iColInd[], int8 iRowInd[], int8 iPivot[], int8 isize, int8 *pierror)
{
	float largest;					// largest element used for pivoting
	float scaling;					// scaling factor in pivoting
	float recippiv;					// reciprocal of pivot element
	float ftmp;						// temporary variable used in swaps
	int8 i, j, k, l, m;				// index counters
	int8 iPivotRow, iPivotCol;		// row and column of pivot element

	// to avoid compiler warnings
	iPivotRow = iPivotCol = 0;
	
	// default to successful inversion
	*pierror = false;
	
	// initialize the pivot array to 0
	for (j = 0; j < isize; j++)
	{
		iPivot[j] = 0;
	}

	// main loop i over the dimensions of the square matrix A
	for (i = 0; i < isize; i++)
	{
		// zero the largest element found for pivoting
		largest = 0.0F;
		// loop over candidate rows j
		for (j = 0; j < isize; j++)
		{
			// check if row j has been previously pivoted
			if (iPivot[j] != 1)
			{
				// loop over candidate columns k
				for (k = 0; k < isize; k++)
				{
					// check if column k has previously been pivoted
					if (iPivot[k] == 0)
					{
						// check if the pivot element is the largest found so far
						if (fabsf(A[j][k]) >= largest)
						{
							// and store this location as the current best candidate for pivoting
							iPivotRow = j;
							iPivotCol = k;
							largest = (float) fabsf(A[iPivotRow][iPivotCol]);
						}
					}
					else if (iPivot[k] > 1)
					{
						// zero determinant situation: exit with identity matrix and set error flag
						fmatrixAeqI(A, isize);
						*pierror = true;
						return;
					}
				}
			}
		}
		// increment the entry in iPivot to denote it has been selected for pivoting
		iPivot[iPivotCol]++;

		// check the pivot rows iPivotRow and iPivotCol are not the same before swapping
		if (iPivotRow != iPivotCol)
		{
			// loop over columns l
			for (l = 0; l < isize; l++)
			{
				// and swap all elements of rows iPivotRow and iPivotCol
				ftmp = A[iPivotRow][l];
				A[iPivotRow][l] = A[iPivotCol][l];
				A[iPivotCol][l] = ftmp;
			}
		}

		// record that on the i-th iteration rows iPivotRow and iPivotCol were swapped
		iRowInd[i] = iPivotRow;
		iColInd[i] = iPivotCol;

		// check for zero on-diagonal element (singular matrix) and return with identity matrix if detected
		if (A[iPivotCol][iPivotCol] == 0.0F)
		{
			// zero determinant situation: exit with identity matrix and set error flag
			fmatrixAeqI(A, isize);
			*pierror = true;
			return;
		}

		// calculate the reciprocal of the pivot element knowing it's non-zero
		recippiv = 1.0F / A[iPivotCol][iPivotCol];
		// by definition, the diagonal element normalizes to 1
		A[iPivotCol][iPivotCol] = 1.0F;
		// multiply all of row iPivotCol by the reciprocal of the pivot element including the diagonal element
		// the diagonal element A[iPivotCol][iPivotCol] now has value equal to the reciprocal of its previous value
		for (l = 0; l < isize; l++)
		{
			if (A[iPivotCol][l] != 0.0F)
				A[iPivotCol][l] *= recippiv;
		}
		// loop over all rows m of A
		for (m = 0; m < isize; m++)
		{
			if (m != iPivotCol)
			{
				// scaling factor for this row m is in column iPivotCol
				scaling = A[m][iPivotCol];
				// zero this element
				A[m][iPivotCol] = 0.0F;
				// loop over all columns l of A and perform elimination
				for (l = 0; l < isize; l++)
				{
					if ((A[iPivotCol][l] != 0.0F) && (scaling != 0.0F))
						A[m][l] -= A[iPivotCol][l] * scaling;
				}
			}
		}
	} // end of loop i over the matrix dimensions

	// finally, loop in inverse order to apply the missing column swaps
	for (l = isize - 1; l >= 0; l--)
	{
		// set i and j to the two columns to be swapped
		i = iRowInd[l];
		j = iColInd[l];

		// check that the two columns i and j to be swapped are not the same
		if (i != j)
		{
			// loop over all rows k to swap columns i and j of A
			for (k = 0; k < isize; k++)
			{
				ftmp = A[k][i];
				A[k][i] = A[k][j];
				A[k][j] = ftmp;
			}
		}
	}

	return;
}