/// POWER INTEGER /// /// <summary> /// Performs the quick mathematical power operation. /// Works only for integer exponent values. /// /// WARNING! The power value here should be an integer number, /// that is, the calculator method 'integerPower(power)' should /// return the same value as power. Otherwise, the result /// would be unpredictable AND INCORRECT. /// </summary> /// <param name="number">The number to raise to the power.</param> /// <param name="power">The INTEGER exponent of the power.</param> /// <returns>The number raised to the integer power.</returns> public static T PowerInteger_Generic(T number, T power) { power = calc.intPart(power); if (power == Numeric <T, C> .Zero) { return(calc.fromInt(1)); } else if (power < Numeric <T, C> .Zero) { if (number <= Numeric <T, C> .Zero) { throw new ArgumentException("Cannot raise a non-positive number to a negative power."); } return(calc.div(calc.fromInt(1), PowerInteger_Generic(number, calc.negate(power)))); } // Ноль в любой степени будет ноль: if (calc.eqv(number, calc.zero)) { return(calc.zero); } Numeric <T, C> res = calc.fromInt(1); // результат возведения в степень Numeric <T, C> copy = calc.getCopy(number); // изменяемая копия (переданное число может быть ссылочным типом) T two = calc.fromInt(2); T one = calc.fromInt(1); while (power > Numeric <T, C> .Zero) { // Если остаток от деления на 2 равен 1 if (calc.eqv(WhiteMath <T, C> .Modulus(power, two), one)) { res *= copy; } copy *= copy; power = calc.intPart(calc.div(power, two)); } return(res); }
/// <summary> /// Finds the greatest common divisor of two integer-like numbers /// using the simple Euclid algorithm. /// /// The calculator for the numbers is recommended to provide reasonable implementation /// of the remainder operation (%) - otherwise, the function /// Modulus from whiteMath class will be used. /// /// Will work with floating-point type numbers only if they are integers; /// In case of division errors the result will be rounded and thus not guaranteed. /// </summary> /// <param name="one"></param> /// <param name="two"></param> /// <returns></returns> public static T GreatestCommonDivisor(T one, T two) { Contract.Requires <ArgumentException>(one != Numeric <T, C> .Zero && two != Numeric <T, C> .Zero, "None of the numbers may be zero."); Contract.Ensures(Contract.Result <T>() > Numeric <T, C> .Zero); Contract.Ensures((Numeric <T, C>)one % Contract.Result <T>() == Numeric <T, C> .Zero); Contract.Ensures((Numeric <T, C>)two % Contract.Result <T>() == Numeric <T, C> .Zero); // T может быть ссылочным типом, поэтому необходимо // предостеречь объекты от изменения // а также отсечь знаки по необходимости T oneTmp; T twoTmp; if (calc.mor(calc.zero, one)) { oneTmp = calc.negate(one); } else { oneTmp = calc.getCopy(one); } if (calc.mor(calc.zero, two)) { twoTmp = calc.negate(two); } else { twoTmp = calc.getCopy(two); } try { while (!calc.eqv(oneTmp, calc.zero) && !calc.eqv(twoTmp, calc.zero)) { if (calc.mor(oneTmp, twoTmp)) { oneTmp = calc.rem(oneTmp, twoTmp); } else { twoTmp = calc.rem(twoTmp, oneTmp); } } } catch // calculator throws exception - working with fp's. { oneTmp = calc.intPart(oneTmp); twoTmp = calc.intPart(twoTmp); while (!calc.eqv(oneTmp, calc.zero) && !calc.eqv(twoTmp, calc.zero)) { if (calc.mor(oneTmp, twoTmp)) { oneTmp = WhiteMath <T, C> .Round(WhiteMath <T, C> .Modulus(oneTmp, twoTmp)); } else { twoTmp = WhiteMath <T, C> .Round(WhiteMath <T, C> .Modulus(twoTmp, oneTmp)); } } } return(calc.sum(oneTmp, twoTmp)); }