Add() public static method

Adds two big integers.
public static Add ( uint digits1, uint length1, uint digits2, uint length2, uint digitsRes ) : uint
digits1 uint First big integer digits.
length1 uint First big integer length.
digits2 uint Second big integer digits.
length2 uint Second big integer length.
digitsRes uint Resulting big integer digits.
return uint
示例#1
0
        /// <summary>
        /// Adds two big integers.
        /// </summary>
        /// <param name="int1">First big integer.</param>
        /// <param name="int2">Second big integer.</param>
        /// <returns>Resulting big integer.</returns>
        /// <exception cref="ArgumentException"><paramref name="int1" /> or <paramref name="int2" /> is too big for add operation.</exception>
        static public IntX Add(IntX int1, IntX int2)
        {
            // Process zero values in special way
            if (int2._length == 0)
            {
                return(new IntX(int1));
            }
            if (int1._length == 0)
            {
                IntX x = new IntX(int2);
                x._negative = int1._negative;                 // always get sign of the first big integer
                return(x);
            }

            // Determine big int with lower length
            IntX smallerInt;
            IntX biggerInt;

            DigitHelper.GetMinMaxLengthObjects(int1, int2, out smallerInt, out biggerInt);

            // Check for add operation possibility
            if (biggerInt._length == uint.MaxValue)
            {
                throw new ArgumentException(Strings.IntegerTooBig);
            }

            // Create new big int object of needed length
            IntX newInt = new IntX(biggerInt._length + 1, int1._negative);

            // Do actual addition
            newInt._length = DigitOpHelper.Add(
                biggerInt._digits,
                biggerInt._length,
                smallerInt._digits,
                smallerInt._length,
                newInt._digits);

            // Normalization may be needed
            newInt.TryNormalize();

            return(newInt);
        }
示例#2
0
        /// <summary>
        /// Parses provided string representation of <see cref="IntX" /> object.
        /// </summary>
        /// <param name="value">Number as string.</param>
        /// <param name="startIndex">Index inside string from which to start.</param>
        /// <param name="endIndex">Index inside string on which to end.</param>
        /// <param name="numberBase">Number base.</param>
        /// <param name="charToDigits">Char->digit dictionary.</param>
        /// <param name="digitsRes">Resulting digits.</param>
        /// <returns>Parsed integer length.</returns>
        override unsafe public uint Parse(string value, int startIndex, int endIndex, uint numberBase, IDictionary <char, uint> charToDigits, uint[] digitsRes)
        {
            uint newLength = base.Parse(value, startIndex, endIndex, numberBase, charToDigits, digitsRes);

            // Maybe base method already parsed this number
            if (newLength != 0)
            {
                return(newLength);
            }

            // Check length - maybe use classic parser instead
            uint initialLength = (uint)digitsRes.LongLength;

            if (initialLength < Constants.FastParseLengthLowerBound || initialLength > Constants.FastParseLengthUpperBound)
            {
                return(_classicParser.Parse(value, startIndex, endIndex, numberBase, charToDigits, digitsRes));
            }

            uint valueLength  = (uint)(endIndex - startIndex + 1);
            uint digitsLength = 1U << Bits.CeilLog2(valueLength);

            // Prepare array for digits in other base
            uint[] valueDigits = ArrayPool <uint> .Instance.GetArray(digitsLength);

            // This second array will store integer lengths initially
            uint[] valueDigits2 = ArrayPool <uint> .Instance.GetArray(digitsLength);

            fixed(uint *valueDigitsStartPtr = valueDigits, valueDigitsStartPtr2 = valueDigits2)
            {
                // In the string first digit means last in digits array
                uint *valueDigitsPtr  = valueDigitsStartPtr + valueLength - 1;
                uint *valueDigitsPtr2 = valueDigitsStartPtr2 + valueLength - 1;

                // Reverse copy characters into digits
                fixed(char *valueStartPtr = value)
                {
                    char *valuePtr    = valueStartPtr + startIndex;
                    char *valueEndPtr = valuePtr + valueLength;

                    for (; valuePtr < valueEndPtr; ++valuePtr, --valueDigitsPtr, --valueDigitsPtr2)
                    {
                        // Get digit itself - this call will throw an exception if char is invalid
                        *valueDigitsPtr = StrRepHelper.GetDigit(charToDigits, *valuePtr, numberBase);

                        // Set length of this digit (zero for zero)
                        *valueDigitsPtr2 = *valueDigitsPtr == 0U ? 0U : 1U;
                    }
                }

                // We have retrieved lengths array from pool - it needs to be cleared before using
                DigitHelper.SetBlockDigits(valueDigitsStartPtr2 + valueLength, digitsLength - valueLength, 0);

                // Now start from the digit arrays beginning
                valueDigitsPtr  = valueDigitsStartPtr;
                valueDigitsPtr2 = valueDigitsStartPtr2;

                // Current multiplier (classic or fast) will be used
                IMultiplier multiplier = MultiplyManager.GetCurrentMultiplier();

                // Here base in needed power will be stored
                IntX baseInt = null;

                // Temporary variables used on swapping
                uint[] tempDigits;
                uint * tempPtr;

                // Variables used in cycle
                uint *ptr1, ptr2, valueDigitsPtrEnd;
                uint  loLength, hiLength;

                // Outer cycle instead of recursion
                for (uint innerStep = 1, outerStep = 2; innerStep < digitsLength; innerStep <<= 1, outerStep <<= 1)
                {
                    // Maybe baseInt must be multiplied by itself
                    baseInt = baseInt == null ? numberBase : baseInt * baseInt;

                    // Using unsafe here
                    fixed(uint *baseDigitsPtr = baseInt._digits)
                    {
                        // Start from arrays beginning
                        ptr1 = valueDigitsPtr;
                        ptr2 = valueDigitsPtr2;

                        // vauleDigits array end
                        valueDigitsPtrEnd = valueDigitsPtr + digitsLength;

                        // Cycle thru all digits and their lengths
                        for (; ptr1 < valueDigitsPtrEnd; ptr1 += outerStep, ptr2 += outerStep)
                        {
                            // Get lengths of "lower" and "higher" value parts
                            loLength = *ptr2;
                            hiLength = *(ptr2 + innerStep);

                            if (hiLength != 0)
                            {
                                // We always must clear an array before multiply
                                DigitHelper.SetBlockDigits(ptr2, outerStep, 0U);

                                // Multiply per baseInt
                                hiLength = multiplier.Multiply(
                                    baseDigitsPtr,
                                    baseInt._length,
                                    ptr1 + innerStep,
                                    hiLength,
                                    ptr2);
                            }

                            // Sum results
                            if (hiLength != 0 || loLength != 0)
                            {
                                *ptr1 = DigitOpHelper.Add(
                                    ptr2,
                                    hiLength,
                                    ptr1,
                                    loLength,
                                    ptr2);
                            }
                            else
                            {
                                *ptr1 = 0U;
                            }
                        }
                    }

                    // After inner cycle valueDigits will contain lengths and valueDigits2 will contain actual values
                    // so we need to swap them here
                    tempDigits   = valueDigits;
                    valueDigits  = valueDigits2;
                    valueDigits2 = tempDigits;

                    tempPtr         = valueDigitsPtr;
                    valueDigitsPtr  = valueDigitsPtr2;
                    valueDigitsPtr2 = tempPtr;
                }
            }

            // Determine real length of converted number
            uint realLength = valueDigits2[0];

            // Copy to result
            Array.Copy(valueDigits, digitsRes, realLength);

            // Return arrays to pool
            ArrayPool <uint> .Instance.AddArray(valueDigits);

            ArrayPool <uint> .Instance.AddArray(valueDigits2);

            return(realLength);
        }