Exemplo n.º 1
0
        public void Split(ref BigInt D, ref BigInt E, short Part)
        {
            if (Part >= this.Size)
            {
                throw new ArgumentOutOfRangeException("The provided Part parameter is out of range");
            }

            short iPart = 0;

            for (short i = 0; i < this.Spart; i++)
            {
                if (i < Part)
                {
                    E.Value[i] = this.Value[i];
                }
                else
                {
                    D.Value[iPart] = this.Value[i];
                    iPart++;
                }
            }
            E.Reduce();
            D.Reduce();
            //for (int i = 0; i < Part; i++)
            //{
            //    D.ShiftLeft(16);
            //}

            //BigInt Tmp = D + E;
            //Tmp.Reduce();
        }
Exemplo n.º 2
0
        private static void _DivCellMod(ref BigInt Q, ref BigInt R, BigInt B, uint DefaultBase, signt ResultSign)
        {
            uint[] Result    = new uint[B.Size];
            short  ResultPos = 0;

            // First copy the Dividend (B) to the Remainder R
            B.Reduce();
            R = B.Clone();

            short Pos      = (short)(R.Spart - 1);
            ulong Dividend = R.Value[Pos];

            if (Dividend >= DefaultBase)
            {
                ulong LocalQuotient = Dividend / DefaultBase;
                Result[ResultPos++] = (uint)LocalQuotient;
                R.Value[Pos]        = (uint)(Dividend % DefaultBase);
            }
            Pos--;

            while (Pos >= 0)
            {
                Dividend = ((ulong)R.Value[Pos + 1] << CELL_SIZE) + (ulong)R.Value[Pos];
                ulong LocalQuotient = Dividend / DefaultBase;
                Result[ResultPos++] = (uint)LocalQuotient;

                R.Value[Pos + 1] = 0;
                R.Value[Pos--]   = (uint)(Dividend % DefaultBase);
            }

            Q.Spart = ResultPos;
            int j = 0;

            for (int i = Q.Spart - 1; i >= 0; i--, j++)
            {
                Q.Value[j] = Result[i];
            }
            for (; j < B.Size; j++)
            {
                Q.Value[j] = 0;
            }
            Q.Sign = ResultSign;
            Q.Reduce();
            R.Reduce();
        }
Exemplo n.º 3
0
        private static void _Sub(ref BigInt C, BigInt B1, BigInt B2, signt ResultSign)
        {
            long  Tmp;
            short Over = 0;

            B2 = (BigInt)B1.SameSize(B2);
            C.Resize((short)(B1.Spart + 1));

            for (int i = 0; i < B1.Spart; i++)
            {
                long B1Val = B1.Value[i], B2Val = B2.Value[i];
                Tmp        = B1Val - B2Val + Over;
                C.Value[i] = (uint)(Tmp & CELL_MASK);
                Over       = (short)((Tmp >> CELL_SIZE) & CELL_MASK);
            }

            C.Value[B1.Spart] = (uint)Over;
            C.Sign            = ResultSign;
            C.Reduce();
        }
Exemplo n.º 4
0
        private static void _MulKara(ref BigInt C, ref BigInt B1, ref BigInt B2, signt ResultSign)
        {
            short B1Spart = B1.Spart;
            short B2Spart = B2.Spart;

            B1.Reduce();
            B2.Reduce();
            B2 = (BigInt)B1.SameSize(B2);
            C.Resize((short)(2 * B1.Spart + 1));

            if (B1.Spart <= SPART_LIMIT || ((B1Spart < SPART_LIMIT && (B2Spart - B1Spart) > SPART_LIMIT) || (B2Spart < SPART_LIMIT && (B1Spart - B2Spart) > SPART_LIMIT)))
            {
                _Mul(ref C, ref B1, ref B2, ResultSign);
            }
            else
            {
                B1.Reduce();
                B2.Reduce();
                short Part = B1.Spart < B2.Spart ? (short)(B1.Spart / 2) : (short)(B2.Spart / 2);

                //short PartCopy = Part;
                //while (PartCopy != 0 && PartCopy < (B1.Spart < B2.Spart ? B1.Spart : B2.Spart) && CELL_SIZE % PartCopy != 0)
                //{
                //    PartCopy++;
                //}
                //if (PartCopy != 0 && CELL_SIZE % PartCopy == 0)
                //{
                //    Part = PartCopy;
                //}
                //else
                //{
                //    PartCopy = Part;
                //    while (PartCopy > 0 && CELL_SIZE % PartCopy != 0)
                //    {
                //        PartCopy--;
                //    }
                //    Part = PartCopy;
                //}

                B2 = (BigInt)B1.SameSize(B2);

                BigInt D = new BigInt(B1.Size, 0), E = new BigInt(B1.Size, 0);
                BigInt F = new BigInt(B1.Size, 0), G = new BigInt(B1.Size, 0);
                BigInt Z0 = new BigInt(B1.Size, 0), Z1 = new BigInt(B1.Size, 0), Z2 = new BigInt(B1.Size, 0);
                // C  := Z2 * (Base ^ (2 * Part)) + (Z1 - Z2 - Z0) * (Base ^ Part) + Z0
                B1.Split(ref D, ref E, Part);
                B2.Split(ref F, ref G, Part);
                // K = D + E
                // L = F + G
                BigInt K = D + E;
                BigInt L = F + G;
                // Z0 := E*G
                // Z1 := K*L
                // Z2 := D*F
                _MulKara(ref Z0, ref E, ref G, ResultSign);
                _MulKara(ref Z1, ref K, ref L, ResultSign);
                _MulKara(ref Z2, ref D, ref F, ResultSign);
                Z0.Reduce();
                Z1.Reduce();
                Z2.Reduce();

                // Z2Copy = Z2 * (Base ^ (2 * Part))
                BigInt Z2Copy = Z2.Clone();
                for (int i = 0; i < 2 * Part; i++)
                {
                    // Z2 * Base
                    // Base = 2 ^ CELL_SIZE
                    Z2Copy.ShiftLeft(CELL_SIZE);
                }

                // (Z1 - Z2 - Z0) * (Base ^ Part)
                BigInt ZDiff = Z1 - Z2 - Z0;
                for (int i = 0; i < Part; i++)
                {
                    // ZDiff * Base
                    // Base = 2 ^ CELL_SIZE
                    ZDiff.ShiftLeft(CELL_SIZE);
                }

                C = Z2Copy + ZDiff + Z0;

                C.Reduce();
            }
        }
Exemplo n.º 5
0
        public override void ToBigInt(string Str)
        {
            BigInt ResultBigInt = new BigInt(this.Size, 0);
            string HString      = "0123456789ABCDEF";
            string StrUpper     = Str.ToUpper();

            if (IsNumeric(StrUpper))
            {
                if (StrUpper.StartsWith("+") || StrUpper.StartsWith("-"))
                {
                    StrUpper = StrUpper.Substring(1, StrUpper.Length - 1);
                }

                for (int i = 0; i < StrUpper.Length; i++)
                {
                    char cellVal = StrUpper[i];
                    int  n       = HString.IndexOf(cellVal);
                    if (n == -1)
                    {
                        throw (new ArgumentException("Invalid string in constructor."));
                    }
                    else
                    {
                        ResultBigInt = ResultBigInt.Mul10() + (uint)n;
                    }
                }
                ResultBigInt.Reduce();
            }
            else if (StrUpper.Contains('O'))
            {
                int xPos = StrUpper.IndexOf("O");
                if (xPos != -1)
                {
                    StrUpper = StrUpper.Substring(xPos + 1, (StrUpper.Length - xPos - 1));
                }
                for (int i = 0; i < StrUpper.Length; i++)
                {
                    char cellVal = StrUpper[i];
                    int  n       = HString.IndexOf(cellVal);
                    if (n == -1)
                    {
                        throw (new ArgumentException("Invalid string in constructor."));
                    }
                    else
                    {
                        ResultBigInt = ResultBigInt.Mul8() + (uint)n;
                    }
                }
                ResultBigInt.Reduce();
            }
            else
            {
                int xPos = StrUpper.IndexOf("X");
                if (xPos != -1)
                {
                    StrUpper = StrUpper.Substring(xPos + 1, (StrUpper.Length - xPos - 1));
                }
                for (int i = 0; i < StrUpper.Length; i++)
                {
                    char cellVal = StrUpper[i];
                    int  n       = HString.IndexOf(cellVal);
                    if (n == -1)
                    {
                        throw (new ArgumentException("Invalid string in constructor."));
                    }
                    else
                    {
                        ResultBigInt = ResultBigInt.Mul16() + (uint)n;
                    }
                }
                ResultBigInt.Reduce();
            }



            /*if (Sign == signt.negative) // overflow check for overflow on negative value
             * {
             *  if ((ResultBigInt.Value[Size - 1] & HIGH_BIT_MASK) == 0)
             *      throw (new OverflowException("Size overflow, while initialising the value array."));
             * }
             * else // overflow check for overflow on positive value
             * {
             *  if ((ResultBigInt.Value[Size - 1] & HIGH_BIT_MASK) != 0)
             *      throw (new OverflowException("Size overflow, while initialising the value array."));
             * }*/

            for (int i = 0; i < ResultBigInt.Spart; i++)
            {
                this.Value[i] = ResultBigInt.Value[i];
            }

            this.Spart = ResultBigInt.Spart;


            if (this.Spart == 0)
            {
                this.Spart = 1;
            }
        }
Exemplo n.º 6
0
        private static void _Divmod(ref BigInt Q, ref BigInt R, ref BigInt B1, ref BigInt B2, signt ResultSign)
        {
            B1.Reduce(); B2.Reduce(); // B1: Dividend and B2: Divisor
            short B1Spart = B1.Spart;
            short B2Spart = B2.Spart;

            Q = new BigInt(B1.Size, 0);         // Q: Quotient
            R = new BigInt(B1, signt.positive); // R: Rest
            if (B2 == 0)
            {
                throw new ArithmeticException("Divide by zero");
            }

            if (B1 == Q || B1Spart < B2Spart || B1 < B2)
            {
                Q.Sign = ResultSign;
                Q.Reduce();
                R.Reduce();
            }
            else if (B1 == B2)
            {
                Q      = new BigInt(B1.Size, 1);
                Q.Sign = ResultSign;
                R      = new BigInt(B1.Size, 0);
            }
            else if (B1Spart < 3 && B2Spart < 3)
            {
                // Process cell2-Division
                ulong Cell2Dividend = B1.Spart == 2 ? ((ulong)B1.Value[1] << CELL_SIZE) + B1.Value[0] : B1.Value[0];
                ulong Cell2Divisor  = B2.Spart == 2 ? ((ulong)B2.Value[1] << CELL_SIZE) + B2.Value[0] : B2.Value[0];
                Q = new BigInt(B1.Size, Cell2Dividend / Cell2Divisor);
                R = new BigInt(B1.Size, Cell2Dividend % Cell2Divisor);
            }
            else if (B2Spart < 2)
            {
                B2.Reduce();
                _DivCellMod(ref Q, ref R, B1, B2.Value[B2.Spart - 1], ResultSign);
            }
            else
            {
                B1.Reduce();
                B2.Reduce();
                uint[] Result = new uint[B1.Size];
                int    RemainderLength = B1.Spart + 1;
                uint[] Remainder = new uint[RemainderLength];
                uint   Mask = HIGH_BIT_MASK;
                uint   Val = B2.Value[B2.Spart - 1];
                int    Shift = 0, ResultPos = 0;

                while (Mask != 0 && (Val & Mask) == 0)
                {
                    Shift++; Mask >>= 1;
                }

                for (int i = 0; i < B1.Spart; i++)
                {
                    Remainder[i] = B1.Value[i];
                }

                ShiftLeft(Remainder, (short)Shift);
                B2.ShiftLeft((short)Shift);
                B2.Reduce();
                int J = RemainderLength - B2.Spart;
                int Pos = RemainderLength - 1;

                ulong FirstDivisorCell = B2.Value[B2.Spart - 1];
                ulong SecondDiviorCell = B2.Value[B2.Spart - 2];

                int    DivisorLength = B2.Spart + 1;
                uint[] DividendPart  = new uint[DivisorLength];

                while (J > 0)
                {
                    ulong Dividend = ((ulong)Remainder[Pos] << CELL_SIZE) + (ulong)Remainder[Pos - 1];

                    ulong Q_hat = Dividend / FirstDivisorCell;
                    ulong R_hat = Dividend % FirstDivisorCell;

                    bool Done = false;
                    while (!Done)
                    {
                        Done = true;

                        if (Q_hat == MAX_CELL_VALUE ||
                            (Q_hat * SecondDiviorCell) > ((R_hat << CELL_SIZE) + Remainder[Pos - 2]))
                        {
                            Q_hat--;
                            R_hat += FirstDivisorCell;

                            if (R_hat < MAX_CELL_VALUE)
                            {
                                Done = false;
                            }
                        }
                    }

                    for (int h = 0; h < DivisorLength; h++)
                    {
                        DividendPart[h] = Remainder[Pos - h];
                    }

                    BigInt K = new BigInt(B1.Size, DividendPart);
                    BigInt S = B2 * Q_hat;
                    //uint f = 1;
                    //BigInt B2Divisor = B2.Clone();
                    while (S > K)
                    {
                        //Q_hat = Q_hat - f;
                        //S = S - B2Divisor;
                        Q_hat--;
                        S -= B2;
                        //f = f << 1;
                        //B2Divisor.ShiftLeft(1);
                    }
                    //f = f >> 1;
                    //B2Divisor.ShiftRigth(1);
                    //Q_hat = Q_hat + f;
                    //S = S + B2Divisor;
                    BigInt Y = K - S;
                    B2.Reduce();

                    for (int h = 0; h < DivisorLength; h++)
                    {
                        Remainder[Pos - h] = Y.Value[B2.Spart - h];
                    }

                    Result[ResultPos++] = (uint)Q_hat;
                    Pos--;
                    J--;
                }

                Q.Spart = (short)ResultPos;
                int y = 0;
                for (int x = Q.Spart - 1; x >= 0; x--, y++)
                {
                    Q.Value[y] = Result[x];
                }
                for (; y < B1.Size; y++)
                {
                    Q.Value[y] = 0;
                }

                Q.Reduce();

                R.Spart = (short)ShiftRigth(Remainder, (short)Shift);

                for (y = 0; y < R.Spart; y++)
                {
                    R.Value[y] = Remainder[y];
                }
                for (; y < B1.Size; y++)
                {
                    R.Value[y] = 0;
                }
            }

            R.Reduce();
            //BigInt RCopy = R.Clone();
            //int Cmp = Compare(B1, B2);
            //if (Cmp == -1 && B1.Sign == signt.negative && B2.Sign == signt.positive)
            //{
            //    RCopy.Sign = ResultSign;
            //}

            Q.Sign = ResultSign;
            BigInt B1E = Q * B2 + R;

            if (R != 0 && Compare(B1E, B1) != 0)
            {
                if (B2.Sign == signt.negative)
                {
                    if (ResultSign == signt.positive)
                    {
                        Q++;
                    }
                    else
                    {
                        Q--;
                    }
                }
                else if (B1.Sign == signt.negative)
                {
                    if (ResultSign == signt.positive)
                    {
                        Q--;
                    }
                    else
                    {
                        Q++;
                    }
                }
            }
            Q.Reduce();
        }