/// <summary> /// Obtém o valor da aplicação sucessiva da operação soma ao mesmo valor tendo em conta que esta é associativa. /// </summary> /// <typeparam name="T">O tipo do valor.</typeparam> /// <typeparam name="Deg">O tipo que representa o número de vezes a adicionar.</typeparam> /// <typeparam name="D">A classe que define a soma.</typeparam> /// <param name="val">O valor.</param> /// <param name="pow">O expoente.</param> /// <param name="monoid">A classe que define a soma sobre o valor.</param> /// <param name="degreeIntegerNumber">O objecto responsável pelas operaçóes sobre o grau.</param> /// <returns>A potência do valor.</returns> /// <exception cref="MathematicsException"> /// Se o monóide ou o objecto responsável pelas operações sobre inteiros forem nulos ou o expoente /// for negativo. /// </exception> public static T AddPower <T, Deg, D>( T val, Deg pow, D monoid, IIntegerNumber <Deg> degreeIntegerNumber) where D : IMonoid <T> { if (monoid == null) { throw new MathematicsException("Parameter multiplier can't be null."); } else if (degreeIntegerNumber == null) { throw new MathematicsException("Parameter degreeIntegerNumber can't be null."); } else if (degreeIntegerNumber.Compare(pow, degreeIntegerNumber.AdditiveUnity) < 0) { throw new MathematicsException("Can't computer the powers with negative expoents."); } else { var result = monoid.AdditiveUnity; var innerPow = pow; var innerVal = val; var n = degreeIntegerNumber.MapFrom(2); if (degreeIntegerNumber.Compare(innerPow, degreeIntegerNumber.AdditiveUnity) > 0) { var degreeQuotientAndRemainder = degreeIntegerNumber.GetQuotientAndRemainder( innerPow, n); if (degreeIntegerNumber.IsMultiplicativeUnity(degreeQuotientAndRemainder.Remainder)) { result = monoid.Add(result, innerVal); } innerPow = degreeIntegerNumber.Multiply(innerPow, n); while (degreeIntegerNumber.Compare(innerPow, degreeIntegerNumber.AdditiveUnity) > 0) { innerVal = monoid.Add(innerVal, innerVal); degreeQuotientAndRemainder = degreeIntegerNumber.GetQuotientAndRemainder( innerPow, n); if (degreeIntegerNumber.IsMultiplicativeUnity(degreeQuotientAndRemainder.Remainder)) { result = monoid.Add(result, innerVal); } innerPow = degreeIntegerNumber.Multiply(innerPow, n); } } return(result); } }