Пример #1
0
        public uint [] Value; // array itself

        #region Constructors
        protected BigNumber()
        {
            Size  = INIT_SIZE;
            Value = new uint[Size];
            Spart = 1;
            Sign  = signt.positive;
        }
Пример #2
0
 protected BigNumber(ulong Val)
 {
     Size  = INIT_SIZE;
     Value = new uint[Size];
     Sign  = signt.positive;
     ToBigInt(Val);
 }
Пример #3
0
        protected BigNumber(short BitSize, ulong Val)
        {
            Size  = BitSize;
            Value = new uint[Size];
            Sign  = Val >= 0 ? signt.positive : signt.negative;
            ulong AbsVal = Val;

            ToBigInt(AbsVal);
        }
Пример #4
0
        protected BigNumber(long Val)
        {
            Size  = INIT_SIZE;
            Value = new uint[Size];
            Sign  = Val >= 0 ? signt.positive : signt.negative;
            ulong AbsVal = (ulong)Math.Abs(Val);

            ToBigInt(AbsVal);
        }
Пример #5
0
 public BigNumber(short BitSize, string Str)
 {
     Size  = BitSize;
     Value = new uint[Size];
     if (Str != null && Str.Length >= 1)
     {
         Sign = Str[0] == '-' ? signt.negative : signt.positive;
     }
     ToBigInt(Str);
 }
Пример #6
0
 protected BigNumber(BigNumber bn, signt s)
 {
     Value = new uint[bn.Size];
     Size  = bn.Size;
     Spart = bn.Spart;
     Sign  = s;
     for (int i = 0; i < Spart; i++)
     {
         Value[i] = bn.Value[i];
     }
 }
Пример #7
0
        public static string AsString(this signt sign)
        {
            switch (sign)
            {
            case signt.positive: return("+");

            case signt.negative: return("-");

            default: throw new ArgumentException();
            }
        }
Пример #8
0
        private static void _Mul(ref BigInt C, ref BigInt B1, ref BigInt B2, signt ResultSign)
        {
            ulong Tmp;

            B2 = (BigInt)B1.SameSize(B2);
            C.Resize((short)(2 * B1.Spart + 1));
            for (int i = 0; i < B2.Spart; i++)
            {
                for (int j = 0; j < B1.Spart; j++)
                {
                    ulong B1Val = B1.Value[j], B2Val = B2.Value[i];
                    Tmp = B1Val * B2Val;
                    C.AddCell2((short)(i + j), Tmp);
                }
            }
            C.Sign = ResultSign;
        }
Пример #9
0
        private static void _Add(ref BigInt C, BigInt B1, BigInt B2, signt ResultSign)
        {
            ulong Tmp, Over = 0;

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

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

            C.Value[B1.Spart] = (uint)Over;
            C.Sign            = ResultSign;
        }
Пример #10
0
        protected BigNumber(short BitSize, uint[] Value)
        {
            Spart = (short)Value.Length;
            if (Spart > BitSize)
            {
                throw (new ArithmeticException($"Cell overflow in constructor. The length of the array should be less than {INIT_SIZE}."));
            }

            Size       = BitSize;
            this.Value = new uint[Size];
            Sign       = signt.positive;

            for (int i = Spart - 1, j = 0; i >= 0; i--, j++)
            {
                this.Value[j] = Value[i];
            }

            Reduce();
        }
Пример #11
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();
            }
        }
Пример #12
0
 public BigInt(BigInt bi, signt s) : base(bi, s)
 {
 }
Пример #13
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();
        }
Пример #14
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();
        }