示例#1
0
        void DestructiveNormalization(Bignum target, int shift_left)
        {
            BignumDigit digit;
            int         scan_source = 0;
            BignumDigit carry       = (BignumDigit)0;
            int         scan_target = 0;
            int         end_source  = this.Length;
            int         end_target  = target.Length;
            int         shift_right = (BIGNUM_DIGIT_LENGTH - shift_left);
            BignumDigit mask        = (BignumDigit)((1UL << shift_right) - 1UL);

            while (scan_source < end_source)
            {
                digit = this[scan_source++];
                target [scan_target++] = (((digit & mask) << shift_left) | carry);
                carry = (digit >> shift_right);
            }
            if (scan_target < end_target)
            {
                target [scan_target] = carry;
            }
            else if (carry != 0)
            {
                throw new NotImplementedException();
            }
            else
            {
                return;
            }
        }
示例#2
0
 void DestructiveCopy(Bignum target)
 {
     for (int i = 0; i < this.Length; i++)
     {
         target [i] = this [i];
     }
 }
示例#3
0
        Bignum NewSign(bool sign)
        {
            Bignum result = new Bignum(sign, this.Length);

            this.DestructiveCopy(result);
            return(result);
        }
示例#4
0
 static public object ToInteger(Bignum item)
 {
     if (item.Length == 0)
     {
         return(0);
     }
     else if (item.Length == 1)
     {
         long answer = item [0].ToLong();
         if (item.IsNegative == true)
         {
             answer = -answer;
         }
         if ((answer < Int32.MinValue) || (answer > Int32.MaxValue))
         {
             return(answer);
         }
         else
         {
             return((int)answer);
         }
     }
     else
     {
         return(item);
     }
 }
示例#5
0
        // Note, bignums must be normalized (no leading zeros in representation)
        static bignum_comparison bignum_compare_unsigned(Bignum left, Bignum right)
        {
            int left_length  = left.Length;
            int right_length = right.Length;

            if (left_length < right_length)
            {
                return(bignum_comparison.less);
            }
            if (left_length > right_length)
            {
                return(bignum_comparison.greater);
            }
            int scan_left  = left_length;
            int scan_right = right_length;

            while (0 < scan_left)
            {
                BignumDigit digit_left  = left [--scan_left];
                BignumDigit digit_right = right [--scan_right];
                if (digit_left < digit_right)
                {
                    return(bignum_comparison.less);
                }
                if (digit_left > digit_right)
                {
                    return(bignum_comparison.greater);
                }
            }
            return(bignum_comparison.equal);
        }
示例#6
0
        Bignum Copy()
        {
            Bignum target = new Bignum(this.IsNegative, this.Length);

            this.DestructiveCopy(target);
            return(target);
        }
示例#7
0
        static void bignum_divide_unsigned_small_denominator(Bignum numerator, BignumDigit denominator, out Bignum quotient, out Bignum remainder, bool qsign, bool rsign)
        {
            Bignum      q = numerator.NewSign(qsign);
            BignumDigit r = q.DestructiveScaleDown(denominator);

            quotient  = q.Trim();
            remainder = new Bignum(rsign, r);
        }
 public static bool Subtract(out object answer, object left, object right)
 {
     if (left is int)
     {
         if (right is int)
         {
             answer = Narrow((long)(int)left - (long)(int)right);
         }
         else if (right is long)
         {
             answer = Narrow((long)(int)left - (long)right);
         }
         else
         {
             throw new NotImplementedException();
         }
     }
     else if (left is long)
     {
         if (right is int)
         {
             answer = Narrow((long)left - (long)(int)right);
         }
         else if (right is long)
         {
             answer = Narrow((long)left - (long)right);
         }
         else
         {
             throw new NotImplementedException();
         }
     }
     else if (left is Bignum)
     {
         if (right is int)
         {
             answer = Bignum.ToInteger((Bignum)left - (int)right);
         }
         else if (right is long)
         {
             answer = Bignum.ToInteger((Bignum)left - (long)right);
         }
         else if (right is Bignum)
         {
             answer = Bignum.ToInteger((Bignum)left - (Bignum)right);
         }
         else
         {
             throw new NotImplementedException();
         }
     }
     else
     {
         throw new NotImplementedException();
     }
     return(false);
 }
示例#9
0
        static Bignum MultiplyUnsigned(Bignum x, Bignum y, bool negative)
        {
            if (y.Length > x.Length)
            {
                Bignum z = x;
                x = y;
                y = z;
            }
            BignumDigit carry;
            BignumDigit y_digit;
            long        y_digit_low;
            long        y_digit_high;
            BignumDigit x_digit;
            long        x_digit_low;
            long        x_digit_high;
            BignumDigit product_low;
            BignumDigit product_high;
            int         scan_r;
            int         scan_y;
            int         x_length = x.Length;
            int         y_length = y.Length;
            Bignum      r        = new Bignum(negative, x_length + y_length);
            int         scan_x   = 0;
            int         end_x    = x_length;
            int         start_y  = 0;
            int         end_y    = y_length;
            int         start_r  = 0;

            while (scan_x < end_x)
            {
                x_digit      = x [scan_x++];
                x_digit_low  = x_digit.Low;
                x_digit_high = x_digit.High;
                carry        = (BignumDigit)0L;
                scan_y       = start_y;
                scan_r       = start_r++;
                while (scan_y < end_y)
                {
                    y_digit      = y [scan_y++];
                    y_digit_low  = y_digit.Low;
                    y_digit_high = y_digit.High;
                    product_low  = (BignumDigit)(r [scan_r].ToLong() +
                                                 (x_digit_low * y_digit_low) +
                                                 carry.Low);
                    product_high = (BignumDigit)((x_digit_high * y_digit_low) +
                                                 (x_digit_low * y_digit_high) +
                                                 product_low.High +
                                                 carry.High);
                    r [scan_r++] = new BignumDigit(product_high.Low, product_low.Low);
                    carry        = (BignumDigit)((x_digit_high * y_digit_high) +
                                                 product_high.High);
                }
                r [scan_r] = (BignumDigit)(r [scan_r].ToLong() + carry.ToLong());
            }
            return(r.Trim());
        }
示例#10
0
        static Bignum MultiplyUnsignedSmallFactor(Bignum old, long digit, bool sign)
        {
            int    length_x = old.Length;
            Bignum p        = new Bignum(sign, length_x + 1);

            old.DestructiveCopy(p);
            p [length_x] = (BignumDigit)0L;
            bignum_destructive_scale_up(p, digit);
            return(p.Trim());
        }
示例#11
0
        static public Bignum Quotient(Bignum numerator, Bignum denominator)
        {
            if (denominator.IsZero)
            {
                throw new NotImplementedException();
            }
            else if (numerator.IsZero)
            {
                return(numerator);
            }
            else
            {
                bool q_negative_p = denominator.IsNegative ? (!numerator.IsNegative) : numerator.IsNegative;
                switch (bignum_compare_unsigned(numerator, denominator))
                {
                case bignum_comparison.equal:
                    return((Bignum)(q_negative_p ? -1 : 1));

                case bignum_comparison.less:
                    return((Bignum)(0));

                case bignum_comparison.greater:
                {
                    Bignum quotient;
                    Bignum remainder;
                    if (denominator.Length == 1)
                    {
                        BignumDigit digit = denominator [0];
                        if (digit == 1)
                        {
                            return(numerator.MaybeNewSign(q_negative_p));
                        }
                        else if (digit < BIGNUM_RADIX_ROOT)
                        {
                            bignum_divide_unsigned_small_denominator(numerator, digit, out quotient, out remainder, q_negative_p, false);
                        }
                        else
                        {
                            bignum_divide_unsigned_medium_denominator(numerator, digit, out quotient, out remainder, q_negative_p, false);
                        }
                    }
                    else
                    {
                        bignum_divide_unsigned_large_denominator(numerator, denominator, out quotient, out remainder, q_negative_p, false);
                    }

                    return(quotient);
                }

                default:
                    throw new NotImplementedException();
                }
            }
        }
示例#12
0
        Bignum MaybeNewSign(bool sign)
        {
            if (this.IsNegative ? sign : (!sign))
            {
                return(this);
            }

            Bignum answer = new Bignum(sign, this.Length);

            this.DestructiveCopy(answer);
            return(answer);
        }
示例#13
0
        static void bignum_divide_unsigned_large_denominator(Bignum numerator, Bignum denominator, out Bignum quotient, out Bignum remainder, bool qsign, bool rsign)
        {
            int    length_n = numerator.Length + 1;
            int    length_d = denominator.Length;
            Bignum q        = new Bignum(qsign, length_n - length_d);
            Bignum u        = new Bignum(rsign, length_n);

            int shift = 0;

            if (!(length_d > 1))
            {
                throw new NotImplementedException();
            }

            {
                BignumDigit v1 = denominator[length_d - 1];
                while (v1 < (BIGNUM_RADIX / 2))
                {
                    v1   <<= 1;
                    shift += 1;
                }
            }
            if (shift == 0)
            {
                numerator.DestructiveCopy(u);      // bignum_destructive_copy (numerator, u);
                u [length_n - 1] = (BignumDigit)0; // (BIGNUM_REF (u, (length_n - 1))) = 0;
                throw new NotImplementedException();
                // bignum_divide_unsigned_normalized (u, denominator, q);
            }
            else
            {
                Bignum v = new Bignum(false, length_d);         // (bignum_allocate (length_d, 0));
                numerator.DestructiveNormalization(u, shift);   //bignum_destructive_normalization (numerator, u, shift);
                denominator.DestructiveNormalization(v, shift); //bignum_destructive_normalization (denominator, v, shift);
                bignum_divide_unsigned_normalized(u, v, q);
                //bignum_divide_unsigned_normalized (u, v, q);
                //BIGNUM_DEALLOCATE (v);
                //if (remainder != ((bignum_type*) 0))
                //    bignum_destructive_unnormalization (u, shift);
            }
            quotient  = q.Trim();    // (bignum_trim (q));
            remainder = u.Trim();    //(bignum_trim (u));
            //else
            //    BIGNUM_DEALLOCATE (u);
            return;
        }
示例#14
0
        static void bignum_destructive_scale_up(Bignum bignum, long factor)
        {
            BignumDigit carry = (BignumDigit)0L;
            int         scan  = 0;
            BignumDigit two_digits;
            BignumDigit product_low;
            int         end = bignum.Length;

            while (scan < end)
            {
                two_digits      = bignum [scan];
                product_low     = (BignumDigit)((factor * two_digits.Low) + carry.Low);
                carry           = (BignumDigit)((factor * two_digits.High) + product_low.High + carry.High);
                bignum [scan++] = new BignumDigit(carry.Low, product_low.Low);
                carry           = (BignumDigit)(carry.High);
            }
            return;
        }
示例#15
0
        public static bool Divide(out object answer, object left, object right)
        {
            if (left is Bignum)
            {
                if (right is int)
                {
                    Bignum remainder;
                    Bignum q = Bignum.DivRem((Bignum)left, (Bignum)(long)(int)right, out remainder);
                    answer = new Cons(Bignum.ToInteger(q), Bignum.ToInteger(remainder));
                    return(false);
                }
                else if (right is long)
                {
                    Bignum remainder;
                    Bignum q = Bignum.DivRem((Bignum)left, (Bignum)(long)right, out remainder);
                    answer = new Cons(Bignum.ToInteger(q), Bignum.ToInteger(remainder));
                    return(false);
                }
                if (right is Bignum)
                {
                    Bignum remainder;
                    Bignum q = Bignum.DivRem((Bignum)left, (Bignum)right, out remainder);
                    answer = new Cons(Bignum.ToInteger(q), Bignum.ToInteger(remainder));
                    return(false);
                }
                else
                {
                    throw new NotImplementedException("Divide bignum by non-bignum.");
                }
            }
            else
            {
                long w0        = Widen(left);
                long w1        = Widen(right);
                long remainder = 0;
                long quotient  = Math.DivRem(w0, w1, out remainder);

                answer = new Cons(Narrow(quotient), Narrow(remainder));
                return(false);
            }
        }
示例#16
0
        static public Bignum Multiply(Bignum left, Bignum right)
        {
            int  x_length   = left.Length;
            int  y_length   = right.Length;
            bool negative_p = left.IsNegative ? (!right.IsNegative) : right.IsNegative;

            if (left.IsZero)
            {
                return(left);
            }
            if (right.IsZero)
            {
                return(right);
            }
            if (x_length == 1)
            {
                long digit = left [0].ToLong();
                if (digit == 1)
                {
                    return(right.MaybeNewSign(negative_p));
                }
                if (digit < BIGNUM_RADIX_ROOT)
                {
                    return(MultiplyUnsignedSmallFactor(right, digit, negative_p));
                }
            }
            if (y_length == 1)
            {
                long digit = right [0].ToLong();
                if (digit == 1)
                {
                    return(left.MaybeNewSign(negative_p));
                }
                if (digit < BIGNUM_RADIX_ROOT)
                {
                    return(MultiplyUnsignedSmallFactor(left, digit, negative_p));
                }
            }

            return(MultiplyUnsigned(left, right, negative_p));
        }
示例#17
0
 Bignum NewSign (bool sign)
 {
     Bignum result = new Bignum (sign, this.Length);
     this.DestructiveCopy (result);
     return result;
 }
示例#18
0
 Bignum Copy ()
 {
     Bignum target = new Bignum (this.IsNegative, this.Length);
     this.DestructiveCopy (target);
     return target;
 }
示例#19
0
 Bignum RemainderUnsignedSmallDenominator(Bignum d, bool sign)
 {
     throw new NotImplementedException();
 }
示例#20
0
 static void bignum_divide_unsigned_medium_denominator (Bignum numerator, BignumDigit denominator, out Bignum quotient, out Bignum remainder, bool qsign, bool rsign)
 {
     throw new NotImplementedException ();
 }
示例#21
0
        static public Bignum Quotient (Bignum numerator, Bignum denominator)
        {
            if (denominator.IsZero)
                throw new NotImplementedException ();
            else if (numerator.IsZero)
                return numerator;
            else
            {
                bool q_negative_p = denominator.IsNegative ? (!numerator.IsNegative) : numerator.IsNegative;
                switch (bignum_compare_unsigned (numerator, denominator))
                {

                    case bignum_comparison.equal:
                        return (Bignum) (q_negative_p ? -1 : 1);

                    case bignum_comparison.less:
                        return (Bignum) (0);

                    case bignum_comparison.greater:
                        {
                            Bignum quotient;
                            Bignum remainder;
                            if (denominator.Length == 1)
                            {
                                BignumDigit digit = denominator [0];
                                if (digit == 1)
                                    return numerator.MaybeNewSign (q_negative_p);
                                else if (digit < BIGNUM_RADIX_ROOT)
                                    bignum_divide_unsigned_small_denominator (numerator, digit, out quotient, out remainder, q_negative_p, false);
                                else
                                    bignum_divide_unsigned_medium_denominator (numerator, digit, out quotient, out remainder, q_negative_p, false);
                            }
                            else
                                bignum_divide_unsigned_large_denominator (numerator, denominator, out quotient, out remainder, q_negative_p, false);

                            return quotient;
                        }

                    default:
                        throw new NotImplementedException ();
                }
            }
        }
示例#22
0
 static Bignum MultiplyUnsigned (Bignum x, Bignum y, bool negative)
 {
     if (y.Length > x.Length)
     {
         Bignum z = x;
         x = y;
         y = z;
     }
     BignumDigit carry;
     BignumDigit y_digit;
     long y_digit_low;
     long y_digit_high;
     BignumDigit x_digit;
     long x_digit_low;
     long x_digit_high;
     BignumDigit product_low;
     BignumDigit product_high;
     int scan_r;
     int scan_y;
     int x_length = x.Length;
     int y_length = y.Length;
     Bignum r = new Bignum (negative, x_length + y_length);
     int scan_x = 0;
     int end_x = x_length;
     int start_y = 0;
     int end_y = y_length;
     int start_r = 0;
     while (scan_x < end_x)
     {
         x_digit = x [scan_x++];
         x_digit_low = x_digit.Low;
         x_digit_high = x_digit.High;
         carry = (BignumDigit) 0L;
         scan_y = start_y;
         scan_r = start_r++;
         while (scan_y < end_y)
         {
             y_digit = y [scan_y++];
             y_digit_low = y_digit.Low;
             y_digit_high = y_digit.High;
             product_low = (BignumDigit) (r [scan_r].ToLong () +
                           (x_digit_low * y_digit_low) +
                           carry.Low);
             product_high = (BignumDigit) ((x_digit_high * y_digit_low) +
                            (x_digit_low * y_digit_high) +
                            product_low.High +
                            carry.High);
             r [scan_r++] = new BignumDigit (product_high.Low, product_low.Low);
             carry = (BignumDigit) ((x_digit_high * y_digit_high) +
                     product_high.High);
         }
         r [scan_r] = (BignumDigit) (r [scan_r].ToLong () + carry.ToLong ());
     }
     return r.Trim ();
 }
示例#23
0
 static Bignum MultiplyUnsignedSmallFactor (Bignum old, long digit, bool sign)
 {
     int length_x = old.Length;
     Bignum p = new Bignum (sign, length_x + 1);
     old.DestructiveCopy (p);
     p [length_x] = (BignumDigit) 0L;
     bignum_destructive_scale_up (p, digit);
     return p.Trim ();
 }
示例#24
0
 static public object ToInteger (Bignum item)
 {
     if (item.Length == 0)
         return 0;
     else if (item.Length == 1)
     {
         long answer = item [0].ToLong ();
         if (item.IsNegative == true)
             answer = -answer;
         if ((answer < Int32.MinValue) || (answer > Int32.MaxValue))
             return answer;
         else
             return (int) answer;
     }
     else
         return item;
 }
示例#25
0
        Bignum MaybeNewSign (bool sign)
        {
            if (this.IsNegative ? sign : (!sign))
                return this;

            Bignum answer = new Bignum (sign, this.Length);
            this.DestructiveCopy (answer);
            return answer;
        }
示例#26
0
        static void bignum_divide_unsigned_normalized(Bignum u, Bignum v, Bignum q)
        {
            int         u_length     = u.Length; //(BIGNUM_LENGTH (u));
            int         v_length     = v.Length; // (BIGNUM_LENGTH (v));
            int         u_start      = 0;        // (BIGNUM_START_PTR (u));
            int         u_scan       = (u_start + u_length);
            int         u_scan_limit = (u_start + v_length);
            int         u_scan_start = (u_scan - v_length);
            int         v_start      = 0; // (BIGNUM_START_PTR (v));
            int         v_end        = (v_start + v_length);
            int         q_scan       = 0;
            BignumDigit v1           = v[v_end - 1];
            BignumDigit v2           = v[v_end - 2];
            BignumDigit ph;            /* high half of double-digit product */
            BignumDigit pl;            /* low half of double-digit product */
            BignumDigit guess;
            long        gh;            /* high half-digit of guess */
            BignumDigit ch;            /* high half of double-digit comparand */
            long        v2l = v2.Low;  //(HD_LOW (v2));
            long        v2h = v2.High; // (HD_HIGH (v2));
            BignumDigit cl;            /* low half of double-digit comparand */

            BignumDigit gm;            /* memory loc for reference parameter */

            //if (q != BIGNUM_OUT_OF_BAND)
            //  q_scan = ((BIGNUM_START_PTR (q)) + (BIGNUM_LENGTH (q)));
            q_scan = 0 + q.Length;
            while (u_scan_limit < u_scan)
            {
                pl = u [--u_scan]; //uj = (*--u_scan);
                if (pl != v1)
                {
                    /* comparand =
                     * (((((uj * BIGNUM_RADIX) + uj1) % v1) * BIGNUM_RADIX) + uj2);
                     * guess = (((uj * BIGNUM_RADIX) + uj1) / v1); */
                    cl    = u[u_scan - 2];
                    ch    = BignumDigit.Divide(pl, u[u_scan - 1], v1, out gm);
                    guess = gm;
                }
                else
                {
                    cl    = u [u_scan - 2];
                    ch    = u [u_scan - 1] + v1;
                    guess = new BignumDigit(BIGNUM_RADIX - 1);
                }
//#define gl ph			/* low half-digit of guess */
//#define uj pl
//#define qj ph
                while (true)
                {
                    /* product = (guess * v2); */
                    ph = (BignumDigit)(guess.Low); // gl = (HD_LOW (guess));
                    gh = guess.High;               // (HD_HIGH (guess));
                    pl = ph * v2l;
                    ph = ((BignumDigit)(v2l * gh) + (ph * v2h) + (BignumDigit)(pl.High));
                    pl = new BignumDigit(ph.Low, pl.Low); // (HD_CONS ((HD_LOW (ph)), (HD_LOW (pl))));
                    ph = ((BignumDigit)(v2h * gh) + ph.High);
                    /* if (comparand >= product) */
                    if ((ch > ph) || ((ch == ph) && (cl >= pl)))
                    {
                        break;
                    }
                    guess -= 1;
                    /* comparand += (v1 << BIGNUM_DIGIT_LENGTH) */
                    ch += v1;
                    /* if (comparand >= (BIGNUM_RADIX * BIGNUM_RADIX)) */
                    if (ch >= BIGNUM_RADIX)
                    {
                        break;
                    }
                }

                ph           = (bignum_divide_subtract(v, v_start, v_end, guess, u, (--u_scan_start)));
                q [--q_scan] = ph; // (*--q_scan) = qj;
            }
            return;
//#undef gl
//#undef uj
//#undef qj
        }
示例#27
0
 static void bignum_divide_unsigned_medium_denominator(Bignum numerator, BignumDigit denominator, out Bignum quotient, out Bignum remainder, bool qsign, bool rsign)
 {
     throw new NotImplementedException();
 }
示例#28
0
 void DestructiveCopy (Bignum target)
 {
     for (int i = 0; i < this.Length; i++)
         target [i] = this [i];
 }
示例#29
0
 public static bool Multiply(out object answer, object left, object right)
 {
     if (left is int)
     {
         if (right is int)
         {
             answer = Narrow(Widen(left) * Widen(right));
         }
         else if (right is long)
         {
             answer = Bignum.ToInteger((Bignum)(long)(int)left * (Bignum)(long)(right));
         }
         else if (right is Bignum)
         {
             answer = Bignum.ToInteger((Bignum)(long)(int)left * (Bignum)(right));
         }
         else
         {
             throw new NotImplementedException();
         }
     }
     else if (left is long)
     {
         if (right is int)
         {
             answer = Bignum.ToInteger((Bignum)(long)(left) * (Bignum)(long)(int)(right));
         }
         else if (right is long)
         {
             answer = Bignum.ToInteger((Bignum)(long)(left) * (Bignum)(long)(right));
         }
         else if (right is Bignum)
         {
             answer = Bignum.ToInteger((Bignum)(long)(left) * (Bignum)(right));
         }
         else
         {
             throw new NotImplementedException();
         }
     }
     else if (left is Bignum)
     {
         if (right is int)
         {
             answer = Bignum.ToInteger((Bignum)(left) * (Bignum)(int)(right));
         }
         else if (right is long)
         {
             answer = Bignum.ToInteger((Bignum)(left) * (Bignum)(long)(right));
         }
         else if (right is Bignum)
         {
             answer = Bignum.ToInteger((Bignum)(left) * (Bignum)(right));
         }
         else
         {
             throw new NotImplementedException();
         }
     }
     else
     {
         throw new NotImplementedException();
     }
     return(false);
 }
示例#30
0
        static public Bignum Multiply (Bignum left, Bignum right)
        {
            int x_length = left.Length;
            int y_length = right.Length;
            bool negative_p = left.IsNegative ? (!right.IsNegative) : right.IsNegative;
            if (left.IsZero)
                return left;
            if (right.IsZero)
                return right;
            if (x_length == 1)
            {
                long digit = left [0].ToLong ();
                if (digit == 1)
                    return right.MaybeNewSign (negative_p);
                if (digit < BIGNUM_RADIX_ROOT)
                    return MultiplyUnsignedSmallFactor (right, digit, negative_p);
            }
            if (y_length == 1)
            {
                long digit = right [0].ToLong ();
                if (digit == 1)
                    return left.MaybeNewSign (negative_p);
                if (digit < BIGNUM_RADIX_ROOT)
                    return MultiplyUnsignedSmallFactor (left, digit, negative_p);
            }

            return MultiplyUnsigned (left, right, negative_p);
        }
示例#31
0
 void DestructiveNormalization (Bignum target, int shift_left)
 {
     BignumDigit digit;
     int scan_source = 0;
     BignumDigit carry = (BignumDigit) 0;
     int scan_target = 0;
     int end_source = this.Length;
     int end_target = target.Length;
     int shift_right = (BIGNUM_DIGIT_LENGTH - shift_left);
     BignumDigit mask = (BignumDigit) ((1UL << shift_right) - 1UL);
     while (scan_source < end_source) {
         digit = this[scan_source++];
         target [scan_target++] = (((digit & mask) << shift_left) | carry);
         carry = (digit >> shift_right);
     }
     if (scan_target < end_target)
         target [scan_target] = carry;
     else if (carry != 0)
         throw new NotImplementedException ();
     else
         return;
 }
示例#32
0
        static void bignum_destructive_scale_up (Bignum bignum, long factor)
        {
            BignumDigit carry = (BignumDigit) 0L;
            int scan = 0;
            BignumDigit two_digits;
            BignumDigit product_low;
            int end = bignum.Length;

            while (scan < end)
            {
                two_digits = bignum [scan];
                product_low = (BignumDigit) ((factor * two_digits.Low) + carry.Low);
                carry = (BignumDigit) ((factor * two_digits.High) + product_low.High + carry.High);
                bignum [scan++] = new BignumDigit (carry.Low, product_low.Low);
                carry = (BignumDigit) (carry.High);
            }
            return;
        }
示例#33
0
static void bignum_divide_unsigned_normalized (Bignum u, Bignum v, Bignum q)
{
  int u_length = u.Length; //(BIGNUM_LENGTH (u));
  int v_length = v.Length; // (BIGNUM_LENGTH (v));
  int u_start = 0; // (BIGNUM_START_PTR (u));
  int u_scan = (u_start + u_length);
  int u_scan_limit = (u_start + v_length);
  int u_scan_start = (u_scan - v_length);
  int v_start = 0; // (BIGNUM_START_PTR (v));
  int v_end = (v_start + v_length);
  int q_scan = 0;
  BignumDigit v1 = v[v_end -1];
  BignumDigit v2 = v[v_end -2];
  BignumDigit ph;	/* high half of double-digit product */
  BignumDigit pl;	/* low half of double-digit product */
  BignumDigit guess;
  long gh;	/* high half-digit of guess */
  BignumDigit ch;	/* high half of double-digit comparand */
  long v2l = v2.Low; //(HD_LOW (v2));
  long v2h = v2.High; // (HD_HIGH (v2));
  BignumDigit cl;	/* low half of double-digit comparand */

  BignumDigit gm;		/* memory loc for reference parameter */
  //if (q != BIGNUM_OUT_OF_BAND)
  //  q_scan = ((BIGNUM_START_PTR (q)) + (BIGNUM_LENGTH (q)));
  q_scan = 0 + q.Length;
  while (u_scan_limit < u_scan)
    {
      pl = u [--u_scan] ; //uj = (*--u_scan);
      if (pl != v1)
	{
	  /* comparand =
	     (((((uj * BIGNUM_RADIX) + uj1) % v1) * BIGNUM_RADIX) + uj2);
	     guess = (((uj * BIGNUM_RADIX) + uj1) / v1); */
	  cl = u[u_scan -2];
	  ch = BignumDigit.Divide (pl, u[u_scan -1], v1, out gm);
	  guess = gm;
	}
      else
	{
	  cl = u [u_scan-2];
	  ch = u [u_scan-1] + v1;
	  guess = new BignumDigit (BIGNUM_RADIX - 1);
	}
//#define gl ph			/* low half-digit of guess */
//#define uj pl
//#define qj ph
      while (true)
	{
	  /* product = (guess * v2); */
	  ph = (BignumDigit) (guess.Low); // gl = (HD_LOW (guess));
	  gh = guess.High; // (HD_HIGH (guess));
      pl = ph * v2l;
	  ph = ((BignumDigit)(v2l * gh) + (ph * v2h) + (BignumDigit)(pl.High));
	  pl = new BignumDigit (ph.Low, pl.Low); // (HD_CONS ((HD_LOW (ph)), (HD_LOW (pl))));
	  ph = ((BignumDigit)(v2h * gh) + ph.High);
	  /* if (comparand >= product) */
	  if ((ch > ph) || ((ch == ph) && (cl >= pl)))
	    break;
	  guess -= 1;
	  /* comparand += (v1 << BIGNUM_DIGIT_LENGTH) */
	  ch += v1;
	  /* if (comparand >= (BIGNUM_RADIX * BIGNUM_RADIX)) */
	  if (ch >= BIGNUM_RADIX)
	    break;
	}
      
      ph = (bignum_divide_subtract (v, v_start, v_end, guess, u, (--u_scan_start)));
      q [--q_scan] = ph; // (*--q_scan) = qj;
	
    }
  return;
//#undef gl
//#undef uj
//#undef qj
}
示例#34
0
 // Note, bignums must be normalized (no leading zeros in representation)
 static bignum_comparison bignum_compare_unsigned (Bignum left, Bignum right)
 {
     int left_length = left.Length;
     int right_length = right.Length;
     if (left_length < right_length)
         return bignum_comparison.less;
     if (left_length > right_length)
         return bignum_comparison.greater;
     int scan_left = left_length;
     int scan_right = right_length;
     while (0 < scan_left)
     {
         BignumDigit digit_left = left [--scan_left];
         BignumDigit digit_right = right [--scan_right];
         if (digit_left < digit_right)
             return bignum_comparison.less;
         if (digit_left > digit_right)
             return bignum_comparison.greater;
     }
     return bignum_comparison.equal;
 }
示例#35
0
static BignumDigit bignum_divide_subtract (Bignum v, int v_start, int v_end, BignumDigit guess, Bignum u, int u_start)
{
  int v_scan = v_start;
  int u_scan = u_start;
  BignumDigit carry = (BignumDigit)0;
  if (guess == 0) return (BignumDigit)0;
  {
    long gl = guess.Low; //(HD_LOW (guess));
    long gh = guess.High; //(HD_HIGH (guess));
    BignumDigit vx;
    BignumDigit pl;
    BignumDigit vl;
//#define vh vx
//#define ph carry
//#define diff pl
    while (v_scan < v_end)
      {
	vx = v[v_scan++];
	vl = (BignumDigit)(vx.Low); //(HD_LOW (v));
	vx = (BignumDigit)(vx.High); // (HD_HIGH (v));
	pl = ((vl * gl) + carry.Low);
	carry = ((vl * gh) + (vx * gl) + pl.High + carry.High);
	pl = u[u_scan] - new BignumDigit (carry.Low, pl.Low); //(HD_CONS ((HD_LOW (ph)), (HD_LOW (pl)))));
	if (pl < 0)
	  {
	    u[u_scan++] = pl + (BignumDigit)(BIGNUM_RADIX);
	    carry = ((vx * gh) + carry.High + 1);
	  }
	else
	  {
	    u[u_scan++] = carry;
	    carry = ((vx * gh) + carry.High);
	  }
      }
    if (carry == 0)
      return (guess);
    pl = u[u_scan] - carry;
    if (pl < 0)
      u[u_scan] = (pl + BIGNUM_RADIX);
    else
      {
	u[u_scan] = pl;
	return (guess);
      }
//#undef vh
//#undef diff
  }
  /* Subtraction generated carry, implying guess is one too large.
     Add v back in to bring it back down. */
  v_scan = v_start;
  u_scan = u_start;
  carry = (BignumDigit) 0;
  while (v_scan < v_end)
    {
      BignumDigit sum = (v[v_scan++] + u[u_scan] + carry);
      if (sum < BIGNUM_RADIX)
	{
	  u[u_scan++] = sum;
	  carry = (BignumDigit)0;
	}
      else
	{
	  u[u_scan++] = (sum - BIGNUM_RADIX);
	  carry = (BignumDigit) 1;
	}
    }
  if (carry == 1)
    {
      BignumDigit sum = (u[u_scan] + carry);
      u[u_scan] = ((sum < BIGNUM_RADIX) ? sum : (sum - BIGNUM_RADIX));
    }
  return (guess - 1);
}
示例#36
0
 static void bignum_divide_unsigned_small_denominator (Bignum numerator, BignumDigit denominator, out Bignum quotient, out Bignum remainder, bool qsign, bool rsign)
 {
     Bignum q = numerator.NewSign (qsign);
     BignumDigit r = q.DestructiveScaleDown (denominator);
     quotient = q.Trim ();
     remainder = new Bignum (rsign, r);
 }
示例#37
0
 Bignum RemainderUnsignedSmallDenominator (Bignum d, bool sign)
 {
     throw new NotImplementedException ();
 }
示例#38
0
        static void bignum_divide_unsigned_large_denominator (Bignum numerator, Bignum denominator, out Bignum quotient, out Bignum remainder, bool qsign, bool rsign)
        {
            int length_n = numerator.Length + 1;
            int length_d = denominator.Length;
            Bignum q = new Bignum (qsign, length_n - length_d);
            Bignum u = new Bignum (rsign, length_n);

            int shift = 0;
            if (!(length_d > 1)) throw new NotImplementedException ();

            {
                BignumDigit v1 = denominator[length_d - 1];
                while (v1 < (BIGNUM_RADIX / 2)) {
                    v1 <<= 1;
                    shift += 1;
                }
            }
            if (shift == 0) {
                numerator.DestructiveCopy (u); // bignum_destructive_copy (numerator, u);
                u [length_n - 1] = (BignumDigit) 0; // (BIGNUM_REF (u, (length_n - 1))) = 0;
                throw new NotImplementedException ();
                // bignum_divide_unsigned_normalized (u, denominator, q);
            }
            else {
                Bignum v = new Bignum (false, length_d); // (bignum_allocate (length_d, 0));
                numerator.DestructiveNormalization (u, shift);   //bignum_destructive_normalization (numerator, u, shift);
                denominator.DestructiveNormalization (v, shift); //bignum_destructive_normalization (denominator, v, shift);
                bignum_divide_unsigned_normalized (u, v, q);
                //bignum_divide_unsigned_normalized (u, v, q);
                //BIGNUM_DEALLOCATE (v);
                //if (remainder != ((bignum_type*) 0))
                //    bignum_destructive_unnormalization (u, shift);
            }
                quotient = q.Trim ();// (bignum_trim (q));
                remainder = u.Trim(); //(bignum_trim (u));
            //else
            //    BIGNUM_DEALLOCATE (u);
            return;
        }
示例#39
0
        static BignumDigit bignum_divide_subtract(Bignum v, int v_start, int v_end, BignumDigit guess, Bignum u, int u_start)
        {
            int         v_scan = v_start;
            int         u_scan = u_start;
            BignumDigit carry  = (BignumDigit)0;

            if (guess == 0)
            {
                return((BignumDigit)0);
            }
            {
                long        gl = guess.Low;  //(HD_LOW (guess));
                long        gh = guess.High; //(HD_HIGH (guess));
                BignumDigit vx;
                BignumDigit pl;
                BignumDigit vl;
//#define vh vx
//#define ph carry
//#define diff pl
                while (v_scan < v_end)
                {
                    vx    = v[v_scan++];
                    vl    = (BignumDigit)(vx.Low);  //(HD_LOW (v));
                    vx    = (BignumDigit)(vx.High); // (HD_HIGH (v));
                    pl    = ((vl * gl) + carry.Low);
                    carry = ((vl * gh) + (vx * gl) + pl.High + carry.High);
                    pl    = u[u_scan] - new BignumDigit(carry.Low, pl.Low); //(HD_CONS ((HD_LOW (ph)), (HD_LOW (pl)))));
                    if (pl < 0)
                    {
                        u[u_scan++] = pl + (BignumDigit)(BIGNUM_RADIX);
                        carry       = ((vx * gh) + carry.High + 1);
                    }
                    else
                    {
                        u[u_scan++] = carry;
                        carry       = ((vx * gh) + carry.High);
                    }
                }
                if (carry == 0)
                {
                    return(guess);
                }
                pl = u[u_scan] - carry;
                if (pl < 0)
                {
                    u[u_scan] = (pl + BIGNUM_RADIX);
                }
                else
                {
                    u[u_scan] = pl;
                    return(guess);
                }
//#undef vh
//#undef diff
            }

            /* Subtraction generated carry, implying guess is one too large.
             * Add v back in to bring it back down. */
            v_scan = v_start;
            u_scan = u_start;
            carry  = (BignumDigit)0;
            while (v_scan < v_end)
            {
                BignumDigit sum = (v[v_scan++] + u[u_scan] + carry);
                if (sum < BIGNUM_RADIX)
                {
                    u[u_scan++] = sum;
                    carry       = (BignumDigit)0;
                }
                else
                {
                    u[u_scan++] = (sum - BIGNUM_RADIX);
                    carry       = (BignumDigit)1;
                }
            }
            if (carry == 1)
            {
                BignumDigit sum = (u[u_scan] + carry);
                u[u_scan] = ((sum < BIGNUM_RADIX) ? sum : (sum - BIGNUM_RADIX));
            }
            return(guess - 1);
        }