/// <summary> /// Subtrai dois polinómios. /// </summary> /// <param name="left">O primeiro polinómio.</param> /// <param name="right">O segundo polinómio.</param> /// <returns>O polinómio resultante.</returns> protected virtual ParsePolynomialItem <T> Subtract(ParsePolynomialItem <T> left, ParsePolynomialItem <T> right) { var result = new ParsePolynomialItem <T>(); if (left.ValueType == EParsePolynomialValueType.COEFFICIENT) { if (right.ValueType == EParsePolynomialValueType.COEFFICIENT) { result.Coeff = this.ring.Add(left.Coeff, this.ring.AdditiveInverse(right.Coeff)); } else if (right.ValueType == EParsePolynomialValueType.INTEGER) { var rightConversion = this.conversion.InverseConversion(right.Degree); result.Coeff = this.ring.Add(left.Coeff, this.ring.AdditiveInverse(rightConversion)); } else if (right.ValueType == EParsePolynomialValueType.POLYNOMIAL) { result.Polynomial = right.Polynomial.Subtract(left.Coeff, this.ring); } } else if (left.ValueType == EParsePolynomialValueType.INTEGER) { if (right.ValueType == EParsePolynomialValueType.COEFFICIENT) { var leftConverted = this.conversion.InverseConversion(left.Degree); result.Coeff = this.ring.Add(leftConverted, this.ring.AdditiveInverse(right.Coeff)); } else if (right.ValueType == EParsePolynomialValueType.INTEGER) { result.Degree = this.integerRing.Add(left.Degree, this.integerRing.AdditiveInverse(right.Degree)); } else if (right.ValueType == EParsePolynomialValueType.POLYNOMIAL) { var leftConverted = this.conversion.InverseConversion(left.Degree); result.Polynomial.Subtract(leftConverted, this.ring); } } else if (left.ValueType == EParsePolynomialValueType.POLYNOMIAL) { if (right.ValueType == EParsePolynomialValueType.COEFFICIENT) { result.Polynomial = left.Polynomial.Subtract(right.Coeff, this.ring); } else if (right.ValueType == EParsePolynomialValueType.INTEGER) { var rightConverted = this.conversion.InverseConversion(right.Degree); result.Polynomial.Subtract(rightConverted, this.ring); } else if (right.ValueType == EParsePolynomialValueType.POLYNOMIAL) { result.Polynomial = left.Polynomial.Subtract(right.Polynomial, this.ring); } } return(result); }
/// <summary> /// Obtém o simétrico de um polinómio. /// </summary> /// <param name="pol">O polinómio.</param> /// <returns>O polinómio resultante.</returns> protected virtual ParsePolynomialItem <T> Symmetric(ParsePolynomialItem <T> pol) { var result = new ParsePolynomialItem <T>(); if (pol.ValueType == EParsePolynomialValueType.COEFFICIENT) { result.Coeff = this.ring.AdditiveInverse(pol.Coeff); } else if (pol.ValueType == EParsePolynomialValueType.INTEGER) { result.Degree = this.integerRing.AdditiveInverse(pol.Degree); } else if (pol.ValueType == EParsePolynomialValueType.POLYNOMIAL) { result.Polynomial = pol.Polynomial.GetSymmetric(this.ring); } return(result); }
/// <summary> /// Realiza a leitura. /// </summary> /// <remarks> /// Se a leitura não for bem-sucedida, os erros de leitura serão registados no diário /// e será retornado o objecto por defeito. /// </remarks> /// <param name="symbolListToParse">O vector de símbolos a ser lido.</param> /// <param name="errorLogs">O objecto que irá manter o registo do diário da leitura.</param> /// <returns>O valor lido.</returns> public ParsePolynomialItem <CoeffType> Parse( ISymbol <string, string>[] symbolListToParse, ILogStatus <string, EParseErrorLevel> errorLogs) { var pol = default(ParsePolynomialItem <CoeffType>); var innerError = new LogStatus <string, EParseErrorLevel>(); var parsedCoeff = this.coeffParser.Parse(symbolListToParse, innerError); if (innerError.HasLogs(EParseErrorLevel.ERROR)) { if (symbolListToParse.Length == 1) { var stringValue = symbolListToParse[0].SymbolValue; if (string.IsNullOrWhiteSpace(stringValue)) { errorLogs.AddLog( "Variable name can't be empty.", EParseErrorLevel.ERROR); } else if (char.IsLetter(stringValue[0])) { pol = new ParsePolynomialItem <CoeffType>(); pol.Polynomial = new Polynomial <CoeffType>(this.coeffRing.MultiplicativeUnity, stringValue, this.coeffRing); } else { var degreeError = new LogStatus <string, EParseErrorLevel>(); var integerValue = this.integerParser.Parse(symbolListToParse, degreeError); if (!degreeError.HasLogs(EParseErrorLevel.ERROR)) { pol = new ParsePolynomialItem <CoeffType>(); pol.Degree = integerValue; } this.CopyErrors(degreeError, errorLogs); } } else { var degreeError = new LogStatus <string, EParseErrorLevel>(); var integerValue = this.integerParser.Parse(symbolListToParse, degreeError); if (!degreeError.HasLogs(EParseErrorLevel.ERROR)) { pol = new ParsePolynomialItem <CoeffType>(); pol.Degree = integerValue; } this.CopyErrors(degreeError, errorLogs); } } else { pol = new ParsePolynomialItem <CoeffType>(); pol.Coeff = parsedCoeff; // Poderão existir avisos this.CopyErrors(innerError, errorLogs); } return(pol); }
/// <summary> /// Determina a potência do polinómio. /// </summary> /// <param name="left">O polinómio.</param> /// <param name="right">O expoente.</param> /// <returns>O resultado da potência.</returns> /// <exception cref="MathematicsException">Se a operação falhar por vários motivos.</exception> protected virtual ParsePolynomialItem <T> Power(ParsePolynomialItem <T> left, ParsePolynomialItem <T> right) { var result = new ParsePolynomialItem <T>(); if (left.ValueType == EParsePolynomialValueType.COEFFICIENT) { if (right.ValueType == EParsePolynomialValueType.COEFFICIENT) { var degree = this.conversion.DirectConversion(right.Coeff); result.Coeff = MathFunctions.Power(left.Coeff, degree, this.ring); } else if (right.ValueType == EParsePolynomialValueType.INTEGER) { result.Coeff = MathFunctions.Power(left.Coeff, right.Degree, this.ring); } else if (right.ValueType == EParsePolynomialValueType.POLYNOMIAL) { if (right.Polynomial.IsValue) { var exponent = this.conversion.DirectConversion(right.Polynomial.GetAsValue(this.ring)); result.Coeff = MathFunctions.Power(left.Coeff, exponent, this.ring); } else { throw new MathematicsException("Polynomial exponents aren't allowed."); } } } else if (left.ValueType == EParsePolynomialValueType.INTEGER) { if (right.ValueType == EParsePolynomialValueType.COEFFICIENT) { var rightConversion = this.conversion.DirectConversion(right.Coeff); result.Degree = MathFunctions.Power(left.Degree, rightConversion, this.integerRing); } else if (right.ValueType == EParsePolynomialValueType.INTEGER) { result.Degree = MathFunctions.Power(left.Degree, right.Degree, this.integerRing); } else if (right.ValueType == EParsePolynomialValueType.POLYNOMIAL) { if (right.Polynomial.IsValue) { var exponent = this.conversion.DirectConversion(right.Polynomial.GetAsValue(this.ring)); result.Degree = MathFunctions.Power(left.Degree, exponent, this.integerRing); } else { throw new MathematicsException("Polynomial exponents aren't allowed."); } } } else if (left.ValueType == EParsePolynomialValueType.POLYNOMIAL) { if (right.ValueType == EParsePolynomialValueType.COEFFICIENT) { var exponent = this.conversion.DirectConversion(right.Coeff); result.Polynomial = left.Polynomial.Power(exponent, this.ring); } else if (right.ValueType == EParsePolynomialValueType.INTEGER) { result.Polynomial = left.Polynomial.Power(right.Degree, this.ring); } else if (right.ValueType == EParsePolynomialValueType.POLYNOMIAL) { if (right.Polynomial.IsValue) { var exponent = this.conversion.DirectConversion(right.Polynomial.GetAsValue(this.ring)); result.Polynomial = left.Polynomial.Power(exponent, this.ring); } else { throw new MathematicsException("Polynomial exponents aren't allowed."); } } } return(result); }
/// <summary> /// Divide dois polinómios. /// </summary> /// <param name="left">O primeiro polinómio.</param> /// <param name="right">O segundo polinómio.</param> /// <returns>O polinómio resultante.</returns> /// <exception cref="MathematicsException"> /// Se a operação falhar por vários motivos. /// </exception> protected virtual ParsePolynomialItem <T> Divide(ParsePolynomialItem <T> left, ParsePolynomialItem <T> right) { var result = new ParsePolynomialItem <T>(); if (left.ValueType == EParsePolynomialValueType.COEFFICIENT) { if (right.ValueType == EParsePolynomialValueType.COEFFICIENT) { var field = this.ring as IField <T>; if (field == null) { throw new MathematicsException("The provided ring isn't a field."); } else { result.Coeff = field.Multiply(left.Coeff, field.MultiplicativeInverse(right.Coeff)); } } else if (right.ValueType == EParsePolynomialValueType.INTEGER) { var field = this.ring as IField <T>; if (field == null) { throw new MathematicsException("The provided ring isn't a field."); } else { var rightConversion = this.conversion.InverseConversion(right.Degree); result.Coeff = this.ring.Multiply(left.Coeff, field.MultiplicativeInverse(rightConversion)); } } else if (right.ValueType == EParsePolynomialValueType.POLYNOMIAL) { if (right.Polynomial.IsValue) { var rightCoeff = right.Polynomial.GetAsValue(this.ring); if (this.ring.IsAdditiveUnity(rightCoeff)) { throw new MathematicsException("Division by an additive unity."); } else { var field = this.ring as IField <T>; if (field == null) { throw new MathematicsException("The provided ring isn't a field."); } else { result.Polynomial.Multiply(field.MultiplicativeInverse(left.Coeff), this.ring); } } } else { throw new MathematicsException("Can't divide by a polynomial."); } } } else if (left.ValueType == EParsePolynomialValueType.INTEGER) { if (right.ValueType == EParsePolynomialValueType.COEFFICIENT) { var field = this.ring as IField <T>; if (field == null) { throw new MathematicsException("The provided ring isn't a field."); } else { var leftConverted = this.conversion.InverseConversion(left.Degree); result.Coeff = this.ring.Multiply(leftConverted, field.MultiplicativeInverse(right.Coeff)); } } else if (right.ValueType == EParsePolynomialValueType.INTEGER) { if (left.Degree % right.Degree == 0) { result.Degree = left.Degree / right.Degree; } else { throw new MathematicsException("Fractional powers aren't allowed."); } } else if (right.ValueType == EParsePolynomialValueType.POLYNOMIAL) { if (right.Polynomial.IsValue) { var field = this.ring as IField <T>; if (field == null) { throw new MathematicsException("The provided ring isn't a field."); } else { var rightValue = right.Polynomial.GetAsValue(this.ring); var leftConverted = this.conversion.InverseConversion(left.Degree); result.Coeff = this.ring.Multiply(leftConverted, field.MultiplicativeInverse(rightValue)); } } else { throw new MathematicsException("Can't divide by a polynomial."); } } } else if (left.ValueType == EParsePolynomialValueType.POLYNOMIAL) { if (right.ValueType == EParsePolynomialValueType.COEFFICIENT) { var field = this.ring as IField <T>; if (field == null) { throw new MathematicsException("The provided ring isn't a field."); } else { result.Polynomial = left.Polynomial.Multiply( field.MultiplicativeInverse(right.Coeff), this.ring); } } else if (right.ValueType == EParsePolynomialValueType.INTEGER) { var field = this.ring as IField <T>; if (field == null) { throw new MathematicsException("The provided ring isn't a field."); } else { var rightConverted = this.conversion.InverseConversion(right.Degree); result.Polynomial.Multiply(field.MultiplicativeInverse(rightConverted), this.ring); } } else if (right.ValueType == EParsePolynomialValueType.POLYNOMIAL) { if (right.Polynomial.IsValue) { var rightValue = right.Polynomial.GetAsValue(this.ring); var field = this.ring as IField <T>; if (field == null) { throw new MathematicsException("The provided ring isn't a field."); } else { result.Polynomial = left.Polynomial.Multiply( field.MultiplicativeInverse(rightValue), this.ring); } } else { throw new MathematicsException("Can't divide by a polynomial."); } } } return(result); }