/// <summary> /// Converts digits from internal representaion into given base. /// </summary> /// <param name="digits">Big integer digits.</param> /// <param name="length">Big integer length.</param> /// <param name="numberBase">Base to use for output.</param> /// <param name="outputLength">Calculated output length (will be corrected inside).</param> /// <returns>Conversion result (later will be transformed to string).</returns> override public uint[] ToString(uint[] digits, uint length, uint numberBase, ref uint outputLength) { uint[] outputArray = base.ToString(digits, length, numberBase, ref outputLength); // Maybe base method already converted this number if (outputArray != null) { return(outputArray); } // Create an output array for storing of number in other base outputArray = new uint[outputLength + 1]; // Make a copy of initial data uint[] digitsCopy = new uint[length]; Array.Copy(digits, digitsCopy, length); // Calculate output numbers by dividing uint outputIndex; for (outputIndex = 0; length > 0; ++outputIndex) { length = DigitOpHelper.DivMod(digitsCopy, length, numberBase, digitsCopy, out outputArray[outputIndex]); } outputLength = outputIndex; return(outputArray); }
/// <summary> /// Divides two big integers. /// Also modifies <paramref name="digitsPtr1" /> and <paramref name="length1"/> (it will contain remainder). /// </summary> /// <param name="digitsPtr1">First big integer digits.</param> /// <param name="digitsBufferPtr1">Buffer for first big integer digits. May also contain remainder.</param> /// <param name="length1">First big integer length.</param> /// <param name="digitsPtr2">Second big integer digits.</param> /// <param name="digitsBufferPtr2">Buffer for second big integer digits. Only temporarily used.</param> /// <param name="length2">Second big integer length.</param> /// <param name="digitsResPtr">Resulting big integer digits.</param> /// <param name="resultFlags">Which operation results to return.</param> /// <param name="cmpResult">Big integers comparsion result (pass -2 if omitted).</param> /// <returns>Resulting big integer length.</returns> virtual unsafe public uint DivMod( uint *digitsPtr1, uint *digitsBufferPtr1, ref uint length1, uint *digitsPtr2, uint *digitsBufferPtr2, uint length2, uint *digitsResPtr, DivModResultFlags resultFlags, int cmpResult) { // Base implementation covers some special cases bool divNeeded = (resultFlags & DivModResultFlags.Div) != 0; bool modNeeded = (resultFlags & DivModResultFlags.Mod) != 0; // // Special cases // // Case when length1 == 0 if (length1 == 0) { return(0); } // Case when both lengths are 1 if (length1 == 1 && length2 == 1) { if (divNeeded) { *digitsResPtr = *digitsPtr1 / *digitsPtr2; if (*digitsResPtr == 0) { length2 = 0; } } if (modNeeded) { *digitsBufferPtr1 = *digitsPtr1 % *digitsPtr2; if (*digitsBufferPtr1 == 0) { length1 = 0; } } return(length2); } // Compare digits first (if was not previously compared) if (cmpResult == -2) { cmpResult = DigitOpHelper.Cmp(digitsPtr1, length1, digitsPtr2, length2); } // Case when first value is smaller then the second one - we will have remainder only if (cmpResult < 0) { // Maybe we should copy first digits into remainder (if remainder is needed at all) if (modNeeded) { DigitHelper.DigitsBlockCopy(digitsPtr1, digitsBufferPtr1, length1); } // Zero as division result return(0); } // Case when values are equal if (cmpResult == 0) { // Maybe remainder must be marked as empty if (modNeeded) { length1 = 0; } // One as division result if (divNeeded) { *digitsResPtr = 1; } return(1); } // Case when second length equals to 1 if (length2 == 1) { // Call method basing on fact if div is needed uint modRes; if (divNeeded) { length2 = DigitOpHelper.DivMod(digitsPtr1, length1, *digitsPtr2, digitsResPtr, out modRes); } else { modRes = DigitOpHelper.Mod(digitsPtr1, length1, *digitsPtr2); } // Maybe save mod result if (modNeeded) { if (modRes != 0) { length1 = 1; *digitsBufferPtr1 = modRes; } else { length1 = 0; } } return(length2); } // This is regular case, not special return(uint.MaxValue); }