/// <summary> /// Divide um número complexo corrente por outro. /// </summary> /// <param name="right">O número a ser dividido.</param> /// <param name="field">O corpo responsável pelas operações.</param> /// <returns>O resultado da divisão.</returns> /// <exception cref="ArgumentNullException">Se algum dos argumentos for nulo.</exception> /// <exception cref="DivideByZeroException">Se ocorrer uma divisão por zero.</exception> public ComplexNumber <ObjectType> Divide(ComplexNumber <ObjectType> right, IField <ObjectType> field) { if (field == null) { throw new ArgumentNullException("field"); } else if (right == null) { throw new ArgumentNullException("right"); } else if (right.IsZero(field)) { throw new DivideByZeroException("Can't divide by the zero complex number."); } else { var quadReal = field.Multiply(right.realPart, right.realPart); var quadImaginary = field.Multiply(right.imaginaryPart, right.imaginaryPart); var denom = field.Add(quadReal, quadImaginary); var resReal = field.Multiply(this.realPart, right.realPart); resReal = field.Add( resReal, field.Multiply(this.imaginaryPart, right.imaginaryPart)); resReal = field.Multiply( resReal, field.MultiplicativeInverse(denom)); var resImg = field.Multiply(this.realPart, right.imaginaryPart); resImg = field.AdditiveInverse(resImg); resImg = field.Add( resImg, field.Multiply(this.imaginaryPart, right.realPart)); resImg = field.Multiply( resImg, field.MultiplicativeInverse(denom)); var result = new ComplexNumber <ObjectType>(); result.realPart = resReal; result.imaginaryPart = resImg; return(result); } }
/// <summary> /// Obtém uma base ortogonalizada a partir da base actual. /// </summary> /// <param name="coefficientsField">O corpo responsável pelas operações sobre os coeficientes.</param> /// <param name="vectorSpace">O espaço responsável pela multiplicação de um escalar com um vector.</param> /// <param name="scalarProduct">O produto escalar.</param> /// <returns>A base ortogonalizada.</returns> /// <exception cref="ArgumentNullException">Se algum dos argumentos for nulo.</exception> public VectorSpaceGenerator <CoeffType> GetOrthogonalizedBase( IField <CoeffType> coefficientsField, IVectorSpace <CoeffType, IMathVector <CoeffType> > vectorSpace, IScalarProductSpace <IMathVector <CoeffType>, CoeffType> scalarProduct) { if (coefficientsField == null) { throw new ArgumentNullException("coefficientsField"); } else if (vectorSpace == null) { throw new ArgumentNullException("vectorSpace"); } else if (scalarProduct == null) { throw new ArgumentNullException("scalarProduct"); } else { var result = new List <IMathVector <CoeffType> >(); // Mantém a lista de resultados intermédios var intermediaryResults = new List <CoeffType>(); if (this.basisVectors.Count > 0) { var basisCount = this.basisVectors.Count; var i = -1; var control = 0; while (control < basisCount) { var currentVector = this.basisVectors[control]; if (!currentVector.IsNull(coefficientsField)) { i = control; control = basisCount; } else { ++control; } } if (i != -1) { --basisCount; var currentVector = this.basisVectors[i]; result.Add(currentVector); if (i < basisCount) { var denom = scalarProduct.Multiply(currentVector, currentVector); intermediaryResults.Add(denom); ++i; for (; i < basisCount; ++i) { currentVector = this.basisVectors[i]; for (int j = 0; j < result.Count; ++j) { denom = intermediaryResults[j]; if (!coefficientsField.IsAdditiveUnity(denom)) { var orthoVector = result[j]; var num = scalarProduct.Multiply(currentVector, orthoVector); if (!coefficientsField.IsAdditiveUnity(num)) { var scalar = coefficientsField.Multiply( num, coefficientsField.MultiplicativeInverse(denom)); scalar = coefficientsField.AdditiveInverse(scalar); if (!coefficientsField.IsMultiplicativeUnity(scalar)) { orthoVector = vectorSpace.MultiplyScalar(scalar, orthoVector); currentVector = vectorSpace.Add(currentVector, orthoVector); } } } } // Já foi calculado o vector ortogonal denom = scalarProduct.Multiply(currentVector, currentVector); if (coefficientsField.IsAdditiveUnity(denom)) { if (!currentVector.IsNull(coefficientsField)) { intermediaryResults.Add(denom); result.Add(currentVector); } } else { intermediaryResults.Add(denom); result.Add(currentVector); } } // Na útlima iteração não é necessário calcular o produto escalar currentVector = this.basisVectors[i]; for (int j = 0; j < result.Count; ++j) { denom = intermediaryResults[j]; if (!coefficientsField.IsAdditiveUnity(denom)) { var orthoVector = result[j]; var num = scalarProduct.Multiply(currentVector, orthoVector); if (!coefficientsField.IsAdditiveUnity(num)) { var scalar = coefficientsField.Multiply( num, coefficientsField.MultiplicativeInverse(denom)); scalar = coefficientsField.AdditiveInverse(scalar); if (!coefficientsField.IsMultiplicativeUnity(scalar)) { orthoVector = vectorSpace.MultiplyScalar(scalar, orthoVector); currentVector = vectorSpace.Add(currentVector, orthoVector); } } } } // Já foi calculado o vector ortogonal if (!currentVector.IsNull(coefficientsField)) { result.Add(currentVector); } } } } return(new VectorSpaceGenerator <CoeffType>( this.vectorSpaceDimension, result)); } }
/// <summary> /// Determina a inversa da matriz correspondente à decomposição especificada. /// </summary> /// <param name="decompositionResult">A decomposição.</param> /// <param name="matrixFactory">A fábrica responsável pela criação da matriz resultante.</param> /// <param name="field">O corpo responsável pelas operações sobre os objectos.</param> /// <returns>A inversa da matriz associada à decomposição.</returns> /// <exception cref="ArgumentNullException">Se algums dos argumentos for nulo.</exception> public IMathMatrix <CoeffType> Run( TriangDiagSymmMatrixDecompResult <CoeffType> decompositionResult, ISquareMatrixFactory <CoeffType> matrixFactory, IField <CoeffType> field) { if (field == null) { throw new ArgumentNullException("field"); } else if (matrixFactory == null) { throw new ArgumentNullException("matrixFactory"); } else if (decompositionResult == null) { throw new ArgumentNullException("decompositionResult"); } else { var dimension = decompositionResult.UpperTriangularMatrix.GetLength(0); for (var i = 0; i < dimension; ++i) { var d = decompositionResult.DiagonalMatrix[i, i]; if (field.IsAdditiveUnity(d)) { throw new MathematicsException("The provided decomposition has no inverse."); } } var result = matrixFactory.CreateMatrix(dimension); for (int j = dimension - 1; j >= 0; --j) { // Elemento na diagonal. var i = j; var diagonalValue = field.MultiplicativeInverse( decompositionResult.DiagonalMatrix[i, j]); var k = i + 1; for (; k < dimension; ++k) { var product = field.Multiply( decompositionResult.UpperTriangularMatrix[i, k], result[i, k]); diagonalValue = field.Add( diagonalValue, field.AdditiveInverse(product)); } result[i, j] = diagonalValue; --i; while (i >= 0) { k = i + 1; var upperValue = field.Multiply( decompositionResult.UpperTriangularMatrix[i, k], result[k, j]); upperValue = field.AdditiveInverse(upperValue); ++k; for (; k <= j; ++k) { var product = field.Multiply( decompositionResult.UpperTriangularMatrix[i, k], result[k, j]); upperValue = field.Add( upperValue, field.AdditiveInverse(product)); } // Como a matriz é simétrica, inverte a orientação. for (; k < dimension; ++k) { var product = field.Multiply( decompositionResult.UpperTriangularMatrix[i, k], result[j, k]); upperValue = field.Add( upperValue, field.AdditiveInverse(product)); } result[i, j] = upperValue; --i; } } this.SetLowerTerms(result); return(result); } }