Exemplo n.º 1
0
        private static void _MulCell(ref BigInt C, ref BigInt B1, ulong A)
        {
            BigInt B1C = B1.Clone(); // C = B

            while (A > 1)
            {
                if (A % 16 == 0)
                {
                    B1C.ShiftLeft(2);         // C = C * 4
                    B1C.ShiftLeft(2);         // C = C * 4
                    A = A / 16;
                }
                else if (A % 10 == 0)
                {
                    B1C.ShiftLeft(2);         // C = C * 4
                    B1C = B1C + B1;           // C = C + B
                    B1C.ShiftLeft(1);         // C = C * 2
                    A = A / 10;
                }
                else if (A % 2 == 0)
                {
                    B1C = B1.Clone();
                    B1C.ShiftLeft(1);
                    A = A / 2;
                }
                else
                {
                    // A is not a multiple of 2, 10 or 16
                    BigInt C1 = new BigInt(B1C.Size, 0);
                    BigInt A1 = new BigInt(B1C.Size, A);
                    _Mul(ref C1, ref B1C, ref A1, B1C.Sign);
                    B1C = C1.Clone();
                    break;
                }
            }

            C = B1C.Clone();
        }
Exemplo n.º 2
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.º 3
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();
        }