internal void SubtractPositive(Integer Result, Integer ToSub) { if (ToSub.IsULong()) { SubtractULong(Result, ToSub.GetAsULong()); return; } if (ToSub.GetIndex() > Result.GetIndex()) { throw(new Exception("In Subtract() ToSub.Index > Index.")); } int Max = ToSub.GetIndex(); for (int Count = 0; Count <= Max; Count++) { SignedD[Count] = (long)Result.GetD(Count) - (long)ToSub.GetD(Count); } Max = Result.GetIndex(); for (int Count = ToSub.GetIndex() + 1; Count <= Max; Count++) { SignedD[Count] = (long)Result.GetD(Count); } Max = Result.GetIndex(); for (int Count = 0; Count < Max; Count++) { if (SignedD[Count] < 0) { SignedD[Count] += (long)0xFFFFFFFF + 1; SignedD[Count + 1]--; } } if (SignedD[Result.GetIndex()] < 0) { throw(new Exception("Subtract() SignedD[Index] < 0.")); } Max = Result.GetIndex(); for (int Count = 0; Count <= Max; Count++) { Result.SetD(Count, (ulong)SignedD[Count]); } for (int Count = Result.GetIndex(); Count >= 0; Count--) { if (Result.GetD(Count) != 0) { Result.SetIndex(Count); return; } } // If it never found a non-zero digit it would get down to here. Result.SetIndex(0); }
// This is an optimization for multiplying when // only the top digit of a number has been set and // all of the other digits are zero. internal void MultiplyTop(Integer Result, Integer ToMul) { // try // { int TotalIndex = Result.GetIndex() + ToMul.GetIndex(); if (TotalIndex >= Integer.DigitArraySize) { throw(new Exception("MultiplyTop() overflow.")); } // Just like Multiply() except that all the other // rows are zero: int ToMulIndex = ToMul.GetIndex(); int ResultIndex = Result.GetIndex(); for (int Column = 0; Column <= ToMulIndex; Column++) { M[Column + ResultIndex, ResultIndex] = Result.GetD(ResultIndex) * ToMul.GetD(Column); } for (int Column = 0; Column < ResultIndex; Column++) { Result.SetD(Column, 0); } ulong Carry = 0; for (int Column = 0; Column <= ToMulIndex; Column++) { ulong Total = M[Column + ResultIndex, ResultIndex] + Carry; Result.SetD(Column + ResultIndex, Total & 0xFFFFFFFF); Carry = Total >> 32; } Result.SetIndex(TotalIndex); if (Carry != 0) { Result.SetIndex(Result.GetIndex() + 1); if (Result.GetIndex() >= Integer.DigitArraySize) { throw(new Exception("MultiplyTop() overflow.")); } Result.SetD(Result.GetIndex(), Carry); } /* * } * catch( Exception ) // Except ) * { * // "Exception in MultiplyTop: " + Except.Message * } */ }
internal int MultiplyUIntFromCopy(Integer Result, Integer FromCopy, ulong ToMul) { int FromCopyIndex = FromCopy.GetIndex(); Result.SetIndex(FromCopyIndex); for (int Column = 0; Column <= FromCopyIndex; Column++) { Scratch[Column] = ToMul * FromCopy.GetD(Column); } // Add these up with a carry. Result.SetD(0, Scratch[0] & 0xFFFFFFFF); ulong Carry = Scratch[0] >> 32; for (int Column = 1; Column <= FromCopyIndex; Column++) { ulong Total = Scratch[Column] + Carry; Result.SetD(Column, Total & 0xFFFFFFFF); Carry = Total >> 32; } if (Carry != 0) { Result.IncrementIndex(); // This might throw an exception if it overflows. Result.SetD(FromCopyIndex + 1, Carry); } return(Result.GetIndex()); }
// This is another optimization. This is used // when the top digit is 1 and all of the other // digits are zero. This is effectively just a // shift-left operation. internal void MultiplyTopOne(Integer Result, Integer ToMul) { // try // { int TotalIndex = Result.GetIndex() + ToMul.GetIndex(); if (TotalIndex >= Integer.DigitArraySize) { throw(new Exception("MultiplyTopOne() overflow.")); } int ToMulIndex = ToMul.GetIndex(); int ResultIndex = Result.GetIndex(); for (int Column = 0; Column <= ToMulIndex; Column++) { Result.SetD(Column + ResultIndex, ToMul.GetD(Column)); } for (int Column = 0; Column < ResultIndex; Column++) { Result.SetD(Column, 0); } // No Carrys need to be done. Result.SetIndex(TotalIndex); /* * } * catch( Exception ) // Except ) * { * // "Exception in MultiplyTopOne: " + Except.Message * } */ }
private bool ShortDivide(Integer ToDivide, Integer DivideBy, Integer Quotient, Integer Remainder) { Quotient.Copy(ToDivide); // DivideBy has an Index of zero: ulong DivideByU = DivideBy.GetD(0); ulong RemainderU = 0; // Get the first one set up. if (DivideByU > Quotient.GetD(Quotient.GetIndex())) { Quotient.SetD(Quotient.GetIndex(), 0); } else { ulong OneDigit = Quotient.GetD(Quotient.GetIndex()); Quotient.SetD(Quotient.GetIndex(), OneDigit / DivideByU); RemainderU = OneDigit % DivideByU; ToDivide.SetD(ToDivide.GetIndex(), RemainderU); } // Now do the rest. for (int Count = Quotient.GetIndex(); Count >= 1; Count--) { ulong TwoDigits = ToDivide.GetD(Count); TwoDigits <<= 32; TwoDigits |= ToDivide.GetD(Count - 1); Quotient.SetD(Count - 1, TwoDigits / DivideByU); RemainderU = TwoDigits % DivideByU; ToDivide.SetD(Count, 0); ToDivide.SetD(Count - 1, RemainderU); // What's left to divide. } // Set the index for the quotient. // The quotient would have to be at least 1 here, // so it will find where to set the index. for (int Count = Quotient.GetIndex(); Count >= 0; Count--) { if (Quotient.GetD(Count) != 0) { Quotient.SetIndex(Count); break; } } Remainder.SetD(0, RemainderU); Remainder.SetIndex(0); if (RemainderU == 0) { return(true); } else { return(false); } }
// This is a variation on ShortDivide that returns // the remainder. // Also, DivideBy is a ulong. internal ulong ShortDivideRem(Integer ToDivideOriginal, ulong DivideByU, Integer Quotient) { if (ToDivideOriginal.IsULong()) { ulong ToDiv = ToDivideOriginal.GetAsULong(); ulong Q = ToDiv / DivideByU; Quotient.SetFromULong(Q); return(ToDiv % DivideByU); } ToDivide.Copy(ToDivideOriginal); Quotient.Copy(ToDivide); ulong RemainderU = 0; if (DivideByU > Quotient.GetD(Quotient.GetIndex())) { Quotient.SetD(Quotient.GetIndex(), 0); } else { ulong OneDigit = Quotient.GetD(Quotient.GetIndex()); Quotient.SetD(Quotient.GetIndex(), OneDigit / DivideByU); RemainderU = OneDigit % DivideByU; ToDivide.SetD(ToDivide.GetIndex(), RemainderU); } for (int Count = Quotient.GetIndex(); Count >= 1; Count--) { ulong TwoDigits = ToDivide.GetD(Count); TwoDigits <<= 32; TwoDigits |= ToDivide.GetD(Count - 1); Quotient.SetD(Count - 1, TwoDigits / DivideByU); RemainderU = TwoDigits % DivideByU; ToDivide.SetD(Count, 0); ToDivide.SetD(Count - 1, RemainderU); } for (int Count = Quotient.GetIndex(); Count >= 0; Count--) { if (Quotient.GetD(Count) != 0) { Quotient.SetIndex(Count); break; } } return(RemainderU); }
internal void SubtractULong(Integer Result, ulong ToSub) { if (Result.IsULong()) { ulong ResultU = Result.GetAsULong(); if (ToSub > ResultU) { throw(new Exception("SubULong() (IsULong() and (ToSub > Result).")); } ResultU = ResultU - ToSub; Result.SetD(0, ResultU & 0xFFFFFFFF); Result.SetD(1, ResultU >> 32); if (Result.GetD(1) == 0) { Result.SetIndex(0); } else { Result.SetIndex(1); } return; } // If it got this far then Index is at least 2. SignedD[0] = (long)Result.GetD(0) - (long)(ToSub & 0xFFFFFFFF); SignedD[1] = (long)Result.GetD(1) - (long)(ToSub >> 32); if ((SignedD[0] >= 0) && (SignedD[1] >= 0)) { // No need to reorganize it. Result.SetD(0, (ulong)SignedD[0]); Result.SetD(1, (ulong)SignedD[1]); return; } int Max = Result.GetIndex(); for (int Count = 2; Count <= Max; Count++) { SignedD[Count] = (long)Result.GetD(Count); } Max = Result.GetIndex(); for (int Count = 0; Count < Max; Count++) { if (SignedD[Count] < 0) { SignedD[Count] += (long)0xFFFFFFFF + 1; SignedD[Count + 1]--; } } if (SignedD[Result.GetIndex()] < 0) { throw(new Exception("SubULong() SignedD[Index] < 0.")); } Max = Result.GetIndex(); for (int Count = 0; Count <= Max; Count++) { Result.SetD(Count, (ulong)SignedD[Count]); } Max = Result.GetIndex(); for (int Count = Max; Count >= 0; Count--) { if (Result.GetD(Count) != 0) { Result.SetIndex(Count); return; } } // If this was zero it wouldn't find a nonzero // digit to set the Index to and it would end up down here. Result.SetIndex(0); }
internal void DoSquare(Integer ToSquare) { if (ToSquare.GetIndex() == 0) { ToSquare.Square0(); return; } if (ToSquare.GetIndex() == 1) { ToSquare.Square1(); return; } if (ToSquare.GetIndex() == 2) { ToSquare.Square2(); return; } // Now Index is at least 3: int DoubleIndex = ToSquare.GetIndex() << 1; if (DoubleIndex >= Integer.DigitArraySize) { throw(new Exception("Square() overflowed.")); } for (int Row = 0; Row <= ToSquare.GetIndex(); Row++) { if (ToSquare.GetD(Row) == 0) { for (int Column = 0; Column <= ToSquare.GetIndex(); Column++) { M[Column + Row, Row] = 0; } } else { for (int Column = 0; Column <= ToSquare.GetIndex(); Column++) { M[Column + Row, Row] = ToSquare.GetD(Row) * ToSquare.GetD(Column); } } } // Add the columns up with a carry. ToSquare.SetD(0, M[0, 0] & 0xFFFFFFFF); ulong Carry = M[0, 0] >> 32; for (int Column = 1; Column <= DoubleIndex; Column++) { ulong TotalLeft = 0; ulong TotalRight = 0; for (int Row = 0; Row <= Column; Row++) { if (Row > ToSquare.GetIndex()) { break; } if (Column > (ToSquare.GetIndex() + Row)) { continue; } TotalRight += M[Column, Row] & 0xFFFFFFFF; TotalLeft += M[Column, Row] >> 32; } TotalRight += Carry; ToSquare.SetD(Column, TotalRight & 0xFFFFFFFF); Carry = TotalRight >> 32; Carry += TotalLeft; } ToSquare.SetIndex(DoubleIndex); if (Carry != 0) { ToSquare.SetIndex(ToSquare.GetIndex() + 1); if (ToSquare.GetIndex() >= Integer.DigitArraySize) { throw(new Exception("Square() overflow.")); } ToSquare.SetD(ToSquare.GetIndex(), Carry); } }
internal void Multiply(Integer Result, Integer ToMul) { // try // { if (Result.IsZero()) { return; } if (ToMul.IsULong()) { MultiplyULong(Result, ToMul.GetAsULong()); SetMultiplySign(Result, ToMul); return; } // It could never get here if ToMul is zero because GetIsULong() // would be true for zero. // if( ToMul.IsZero()) int TotalIndex = Result.GetIndex() + ToMul.GetIndex(); if (TotalIndex >= Integer.DigitArraySize) { throw(new Exception("Multiply() overflow.")); } int CountTo = ToMul.GetIndex(); for (int Row = 0; Row <= CountTo; Row++) { if (ToMul.GetD(Row) == 0) { int CountZeros = Result.GetIndex(); for (int Column = 0; Column <= CountZeros; Column++) { M[Column + Row, Row] = 0; } } else { int CountMult = Result.GetIndex(); for (int Column = 0; Column <= CountMult; Column++) { M[Column + Row, Row] = ToMul.GetD(Row) * Result.GetD(Column); } } } // Add the columns up with a carry. Result.SetD(0, M[0, 0] & 0xFFFFFFFF); ulong Carry = M[0, 0] >> 32; int ResultIndex = Result.GetIndex(); int MulIndex = ToMul.GetIndex(); for (int Column = 1; Column <= TotalIndex; Column++) { ulong TotalLeft = 0; ulong TotalRight = 0; for (int Row = 0; Row <= MulIndex; Row++) { if (Row > Column) { break; } if (Column > (ResultIndex + Row)) { continue; } // Split the ulongs into right and left sides // so that they don't overflow. TotalRight += M[Column, Row] & 0xFFFFFFFF; TotalLeft += M[Column, Row] >> 32; } TotalRight += Carry; Result.SetD(Column, TotalRight & 0xFFFFFFFF); Carry = TotalRight >> 32; Carry += TotalLeft; } Result.SetIndex(TotalIndex); if (Carry != 0) { Result.IncrementIndex(); // This can throw an exception if it overflowed the index. Result.SetD(Result.GetIndex(), Carry); } SetMultiplySign(Result, ToMul); }