public LargeInteger Pow(ulong power) { LargeInteger.Logger.Debug($"Entering Pow. this: {this}, power: {power}"); this.Ensure(); if (this == 0 && power == 0) { throw new DivideByZeroException("LargeInteger: divide by zero"); } var result = new LargeInteger(1); for (var i = 0uL; i < power; i++) { result *= this; } LargeInteger.Logger.Debug($"Exiting Pow. result: {result.PrintLargeInteger()}"); return result; }
/// <summary> /// Divides the current instance by the divisor. /// </summary> /// <param name="divisor">Divisor</param> /// <returns>Tuple<Quotient, Remainder></returns> public Tuple<LargeInteger, LargeInteger> Divide(LargeInteger divisor) { LargeInteger.Logger.Debug($"Entering Divide. this (dividend): {this.PrintLargeInteger()}, divisor: {divisor.PrintLargeInteger()}"); this.Ensure().Ensure(ref divisor); if (this < divisor) { return new Tuple<LargeInteger, LargeInteger>(0, this); } // This is long division. var quotient = new LargeInteger { data = new List<uint>() }; var testDividend = new LargeInteger { data = new List<uint>() }; int dividendPosition = this.data.Count - 1; for (int i = 0; i < divisor.data.Count; i++) { testDividend.data.Insert(0, this.data[dividendPosition--]); } if (testDividend < divisor) { testDividend.data.Insert(0, this.data[dividendPosition--]); } int numberOfPlacesAddedToLastTestDividend = 0; do { int adjusterLength = testDividend.data.Count - divisor.data.Count + 1; QuotienScratchAdjuster adjuster = new LargeInteger { data = new List<uint>(adjusterLength) }; for (int i = 0; i < adjusterLength; i++) { ((LargeInteger)adjuster).data.Add(0); } ((LargeInteger)adjuster).data.Add(1); LargeInteger quotientScratch = ((LargeInteger)adjuster).Clone(); LargeInteger compareDividend; do { compareDividend = quotientScratch * divisor; if (compareDividend > testDividend) { if (adjuster == 1) { quotientScratch--; compareDividend -= divisor; if (compareDividend < testDividend) { break; } } else { adjuster.Halve(); quotientScratch -= adjuster; } } else if (compareDividend < testDividend) { if (adjuster == 1) { LargeInteger tempCompareDividend = compareDividend; compareDividend += divisor; if (compareDividend > testDividend) { compareDividend = tempCompareDividend; break; } quotientScratch++; } else { adjuster.Halve(); quotientScratch += adjuster; } } else { break; } } while (true); if (numberOfPlacesAddedToLastTestDividend > quotientScratch.data.Count) { if (numberOfPlacesAddedToLastTestDividend + 1 != quotientScratch.data.Count) { throw new ApplicationException( $"Internal error: numberOfPlacesAddedToLastTestDividend > quotientScratch.data.Count && numberOfPlacesAddedToLastTestDividend {numberOfPlacesAddedToLastTestDividend} + 1 != quotientScratch.data.Count {quotientScratch.data.Count}. \r\nDividend:\r\n{this.PrintLargeInteger()}\r\nDivisor:\r\n{divisor.PrintLargeInteger()}"); } quotient.data.Insert(0, 0); } for (int i = quotientScratch.data.Count - 1; i >= 0; i--) { quotient.data.Insert(0, quotientScratch.data[i]); } testDividend -= compareDividend; numberOfPlacesAddedToLastTestDividend = 0; for (int i = 0; i < divisor.data.Count; i++) { if (dividendPosition < 0) { break; } testDividend.data.Insert(0, this.data[dividendPosition--]); numberOfPlacesAddedToLastTestDividend++; } if (testDividend < divisor) { if (dividendPosition < 0) { LargeInteger.Logger.Debug($"Exiting Divide. quotient: {quotient.PrintLargeInteger()}, remainder: {testDividend.PrintLargeInteger()}"); return new Tuple<LargeInteger, LargeInteger>(quotient, testDividend); } testDividend.data.Insert(0, this.data[dividendPosition--]); numberOfPlacesAddedToLastTestDividend++; } } while (true); }