static IList<int> DivieImpl(IList<int> dividentParts, IList<int> originalDivisor, out LongIntegerNumber remain) { remain = new LongIntegerNumber(dividentParts, false); IList<int> divisor = new List<int>(originalDivisor); int shiftCount = 0; while(CompareCore(remain.parts, divisor) >= 0) { ShiftLeft(divisor); shiftCount++; } ShiftRight(divisor); shiftCount--; List<int> result = new List<int>(); while(divisor.Count >= originalDivisor.Count) { int digit = FindDigit(remain, divisor); result.Insert(0, digit); Number temp = (new LongIntegerNumber(divisor, false)).Multiply(new LongIntegerNumber(new int[] { digit }, false)); remain = (LongIntegerNumber)remain.Subtract(temp); if(CompareCore(remain.parts, divisor) < 0) ShiftRight(divisor); } return result; }
static int FindDigit(LongIntegerNumber divident, IList<int> divisorParts) { LongIntegerNumber divisor = new LongIntegerNumber(divisorParts, false); if(divident == Zero || divisor > divident) { return 0; } int dividentPart = ((divident.parts.Count == divisor.parts.Count) ? divident.parts.Last() : divident.parts.Last() * BaseFull + divident.parts[divident.parts.Count - 2]); int divisorPart = divisor.parts.Last(); int lowDigit = Div(dividentPart, divisorPart + 1); //TODO optimize - no need to add 1 if divisor has zeros at the end #if DEBUG int checkCount = 0; #endif int topDigit = Div(dividentPart + 1, divisorPart); int digit = Bisect(lowDigit, topDigit); while(true) { Number mult = divisor.Multiply(new LongIntegerNumber(new int[] { digit }, false)); LongIntegerNumber remain = (LongIntegerNumber)divident.Subtract(mult); if(remain.isNegative) { #if DEBUG checkCount++; #endif topDigit = digit; digit = Bisect(lowDigit, topDigit); continue; } int comparisonResult = remain.Compare(divisor); if(comparisonResult >= 0) { #if DEBUG checkCount++; #endif lowDigit = digit + 1; digit = Bisect(lowDigit, topDigit); continue; } break; } #if DEBUG if(checkCount > 15) throw new InvalidOperationException(); #endif return digit; }
protected override Number Add(Number n) { var longNumber = n.ConvertCast<LongIntegerNumber>(); if(!isNegative && !longNumber.isNegative) return AddCore(longNumber); if(longNumber.isNegative) { var invertedRight = new LongIntegerNumber(longNumber.parts, false); if(this < invertedRight) return new LongIntegerNumber(invertedRight.Subtract(this).ConvertCast<LongIntegerNumber>().parts, true); } else { var invertedLeft = new LongIntegerNumber(this.parts, false); if(longNumber < invertedLeft) return new LongIntegerNumber(invertedLeft.Subtract(longNumber).ConvertCast<LongIntegerNumber>().parts, true); } return AddCore(longNumber); }