Ejemplo n.º 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;
            }
        }
Ejemplo n.º 2
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);
        }
Ejemplo n.º 3
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);
        }
Ejemplo n.º 4
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());
        }
Ejemplo n.º 5
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();
                }
            }
        }
Ejemplo n.º 6
0
 Bignum(bool sign, BignumDigit digit)
 {
     if (digit == 0)
     {
         this.digits = new BignumDigit [0];
     }
     else
     {
         this.sign       = sign;
         this.digits     = new BignumDigit [1];
         this.digits [0] = digit;
     }
 }
Ejemplo n.º 7
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;
        }
Ejemplo n.º 8
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;
        }
Ejemplo n.º 9
0
        BignumDigit DestructiveScaleDown(BignumDigit denominator)
        {
            BignumDigit numerator;
            BignumDigit remainder = (BignumDigit)0L;
            BignumDigit twoDigits;
            int         start = 0;
            int         scan  = start + this.Length;

            while (start < scan)
            {
                twoDigits   = this [--scan];
                numerator   = new BignumDigit(remainder.ToLong(), twoDigits.High);
                remainder   = (BignumDigit)(numerator.ToLong() / denominator.ToLong());
                numerator   = new BignumDigit(numerator.ToLong() % denominator.ToLong(), twoDigits.Low);
                this [scan] = new BignumDigit(remainder.ToLong(), numerator.ToLong() / denominator.ToLong());
                remainder   = (BignumDigit)(numerator.ToLong() % denominator.ToLong());
            }
            return(remainder);
        }
Ejemplo n.º 10
0
        Bignum Trim()
        {
            int last_digit = this.Length;

            while (this [last_digit - 1].ToLong() == 0)
            {
                last_digit -= 1;
            }
            if (last_digit < this.Length)
            {
                BignumDigit [] new_digits = new BignumDigit [last_digit];
                for (int i = 0; i < last_digit; i++)
                {
                    new_digits [i] = this [i];
                }
                this.digits = new_digits;
            }
            return(this);
        }
Ejemplo n.º 11
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 ();
 }
Ejemplo n.º 12
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;
        }
Ejemplo n.º 13
0
 Bignum (bool sign, BignumDigit digit)
 {
     if (digit == 0)
     {
         this.digits = new BignumDigit [0];
     }
     else
     {
         this.sign = sign;
         this.digits = new BignumDigit [1];
         this.digits [0] = digit;
     }
 }
Ejemplo n.º 14
0
        public static BignumDigit Divide (BignumDigit uh, BignumDigit ul, BignumDigit v, out BignumDigit q)
        {
            long guess;
            BignumDigit comparand;
            long v1 = v.High; //(HD_HIGH (v));
            long v2 = v.Low; //(HD_LOW (v));
            long uj;
            BignumDigit uj_uj1;
            long q1;
            long q2;
            long [] u = new long [4];
            if (uh == 0) {
                if (ul < v) {
                    q = (BignumDigit) 0;
                    return ul;
                }
                else if (ul == v) {
                    q = (BignumDigit) 1;
                    return (BignumDigit) 0;
                }
            }
            (u [0]) = uh.High; // (HD_HIGH (uh));
            (u [1]) = uh.Low;  // (HD_LOW (uh));
            (u [2]) = ul.High; // (HD_HIGH (ul));
            (u [3]) = ul.Low;  // (HD_LOW (ul));
            v1 = v.High; // (HD_HIGH (v));
            v2 = v.Low; // (HD_LOW (v));
            //BDD_STEP (q1, 0);
            //#define BDD_STEP(qn, j)							
            {
                uj = (u [0]);
                if (uj != v1) {
                    uj_uj1 = new BignumDigit (uj, (u [0 + 1]));
                    guess = (uj_uj1 / v1);
                    comparand = new BignumDigit (uj_uj1 % v1, u [0 + 2]);
                }
                else {
                    guess = BIGNUM_RADIX_ROOT - 1;
                    comparand = new BignumDigit (u [0 + 1] + v1, u [0 + 2]);
                }
                while ((guess * v2) > comparand.ToLong ()) {
                    guess -= 1;
                    comparand += (v1 << BIGNUM_HALF_DIGIT_LENGTH);
                    if (comparand >= (BignumDigit) BIGNUM_RADIX)
                        break;
                }

                q1 = (DivideSubtract (v1, v2, guess, u));
            }
            {
                uj = (u [1]);
                if (uj != v1) {
                    uj_uj1 = new BignumDigit (uj, (u [1 + 1]));
                    guess = (uj_uj1 / v1);
                    comparand = new BignumDigit (uj_uj1 % v1, u [1 + 2]);
                }
                else {
                    guess = BIGNUM_RADIX_ROOT - 1;
                    comparand = new BignumDigit (u [1 + 1] + v1, u [1 + 2]);
                }
                while ((guess * v2) > comparand.ToLong ()) {
                    guess -= 1;
                    comparand += (v1 << BIGNUM_HALF_DIGIT_LENGTH);
                    if (comparand >= (BignumDigit) BIGNUM_RADIX)
                        break;
                }

                q2 = (DivideSubtract (v1, v2, guess, u));
            }
            //
            q = new BignumDigit (q1, q2); // (HD_CONS (q1, q2));
            return new BignumDigit (u [2], u [3]);
        }
Ejemplo n.º 15
0
 Bignum Trim ()
 {
     int last_digit = this.Length;
     while (this [last_digit - 1].ToLong () == 0)
     {
         last_digit -= 1;
     }
     if (last_digit < this.Length)
     {
         BignumDigit [] new_digits = new BignumDigit [last_digit];
         for (int i = 0; i < last_digit; i++)
         {
             new_digits [i] = this [i];
         }
         this.digits = new_digits;
     }
     return this;
 }
Ejemplo n.º 16
0
        BignumDigit DestructiveScaleDown (BignumDigit denominator)
        {
            BignumDigit numerator;
            BignumDigit remainder = (BignumDigit) 0L;
            BignumDigit twoDigits;
            int start = 0;
            int scan = start + this.Length;

            while (start < scan)
            {
                twoDigits = this [--scan];
                numerator = new BignumDigit (remainder.ToLong (), twoDigits.High);
                remainder = (BignumDigit) (numerator.ToLong () / denominator.ToLong ());
                numerator = new BignumDigit (numerator.ToLong () % denominator.ToLong (), twoDigits.Low);
                this [scan] = new BignumDigit (remainder.ToLong (), numerator.ToLong () / denominator.ToLong ());
                remainder = (BignumDigit) (numerator.ToLong () % denominator.ToLong ());
            }
            return remainder;
        }
Ejemplo n.º 17
0
        public static BignumDigit Divide(BignumDigit uh, BignumDigit ul, BignumDigit v, out BignumDigit q)
        {
            long        guess;
            BignumDigit comparand;
            long        v1 = v.High; //(HD_HIGH (v));
            long        v2 = v.Low;  //(HD_LOW (v));
            long        uj;
            BignumDigit uj_uj1;
            long        q1;
            long        q2;

            long [] u = new long [4];
            if (uh == 0)
            {
                if (ul < v)
                {
                    q = (BignumDigit)0;
                    return(ul);
                }
                else if (ul == v)
                {
                    q = (BignumDigit)1;
                    return((BignumDigit)0);
                }
            }
            (u [0]) = uh.High; // (HD_HIGH (uh));
            (u [1]) = uh.Low;  // (HD_LOW (uh));
            (u [2]) = ul.High; // (HD_HIGH (ul));
            (u [3]) = ul.Low;  // (HD_LOW (ul));
            v1      = v.High;  // (HD_HIGH (v));
            v2      = v.Low;   // (HD_LOW (v));
            //BDD_STEP (q1, 0);
            //#define BDD_STEP(qn, j)
            {
                uj = (u [0]);
                if (uj != v1)
                {
                    uj_uj1    = new BignumDigit(uj, (u [0 + 1]));
                    guess     = (uj_uj1 / v1);
                    comparand = new BignumDigit(uj_uj1 % v1, u [0 + 2]);
                }
                else
                {
                    guess     = BIGNUM_RADIX_ROOT - 1;
                    comparand = new BignumDigit(u [0 + 1] + v1, u [0 + 2]);
                }
                while ((guess * v2) > comparand.ToLong())
                {
                    guess     -= 1;
                    comparand += (v1 << BIGNUM_HALF_DIGIT_LENGTH);
                    if (comparand >= (BignumDigit)BIGNUM_RADIX)
                    {
                        break;
                    }
                }

                q1 = (DivideSubtract(v1, v2, guess, u));
            }
            {
                uj = (u [1]);
                if (uj != v1)
                {
                    uj_uj1    = new BignumDigit(uj, (u [1 + 1]));
                    guess     = (uj_uj1 / v1);
                    comparand = new BignumDigit(uj_uj1 % v1, u [1 + 2]);
                }
                else
                {
                    guess     = BIGNUM_RADIX_ROOT - 1;
                    comparand = new BignumDigit(u [1 + 1] + v1, u [1 + 2]);
                }
                while ((guess * v2) > comparand.ToLong())
                {
                    guess     -= 1;
                    comparand += (v1 << BIGNUM_HALF_DIGIT_LENGTH);
                    if (comparand >= (BignumDigit)BIGNUM_RADIX)
                    {
                        break;
                    }
                }

                q2 = (DivideSubtract(v1, v2, guess, u));
            }
            //
            q = new BignumDigit(q1, q2);  // (HD_CONS (q1, q2));
            return(new BignumDigit(u [2], u [3]));
        }
Ejemplo n.º 18
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
}
Ejemplo n.º 19
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();
 }
Ejemplo n.º 20
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
        }
Ejemplo n.º 21
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);
        }
Ejemplo n.º 22
0
        public double ToDouble()
        {
            if (this.IsZero)
            {
                return(0.0);
            }

            {
                int         length      = this.Length;
                int         index       = length - 1;
                int         scale_words = length - 1;
                BignumDigit msd         = this [index];

                int bits_to_get = 53; //DBL_MANT_DIG; /* includes implicit 1 */

                double value                   = 0;
                long   mask                    = 0;
                long   guard_bit_mask          = BIGNUM_RADIX >> 1;
                long   rounding_correction     = 0;
                int    current_digit_bit_count = 0;
                long   w = msd.ToLong();
                current_digit_bit_count = 0;

                while (w > 0xff)
                {
                    current_digit_bit_count += 8;
                    w >>= 8;
                }

                while (w > 0)
                {
                    current_digit_bit_count += 1;
                    w >>= 1;
                }

                mask = (1 << (current_digit_bit_count)) - 1;

                while (true)
                {
                    if (current_digit_bit_count > bits_to_get)
                    {
                        guard_bit_mask          = (1 << (current_digit_bit_count - bits_to_get - 1));
                        mask                   &= ~((guard_bit_mask << 1) - 1);
                        current_digit_bit_count = bits_to_get;
                        bits_to_get             = 0;
                    }
                    else
                    {
                        bits_to_get -= current_digit_bit_count;
                    }

                    value = (value * BIGNUM_RADIX) + (this [index].ToLong() & mask);

                    if (bits_to_get == 0)
                    {
                        scale_words = index;
                        if (current_digit_bit_count == BIGNUM_DIGIT_LENGTH)
                        {
                            if (index == 0) /* there is no guard bit */
                            {
                                goto finished;
                            }
                            guard_bit_mask      = (1 << (BIGNUM_DIGIT_LENGTH - 1));
                            rounding_correction = 1;
                            index -= 1;
                        }
                        else
                        {
                            rounding_correction = (guard_bit_mask << 1);
                        }
                        break;
                    }
                    if (index == 0)  /* fewer than DBL_MANT_DIG bits */
                    {
                        goto finished;
                    }

                    index -= 1;
                    current_digit_bit_count = BIGNUM_DIGIT_LENGTH;
                    mask = BIGNUM_DIGIT_MASK;
                }

                /* round-to-even depending on lsb, guard and following bits: lgfffff */

                if ((this [index].ToLong() & guard_bit_mask) == 0)  /* case x0xxxx */
                {
                    goto round_down;
                }

                if ((this [index].ToLong() & (guard_bit_mask - 1)) != 0)  /* case x1xx1x */
                {
                    goto round_up;
                }

                /* cases 110000 and 1101xx: test "odd?", i.e. round-to-even rounds up */
                if ((guard_bit_mask << 1) == BIGNUM_RADIX)
                {
                    if ((this [index + 1].ToLong() & 1) != 0)   /* "odd?" */
                    {
                        goto round_up;
                    }
                }
                else
                {
                    if ((this [index].ToLong() & (guard_bit_mask << 1)) != 0)
                    {
                        goto round_up;
                    }
                }

                if (index == 0)   /* case 010000, no more words of following bits */
                {
                    goto finished;
                }

                { /* distinguish between cases 0100...00 and 0100..1xx, multiple words */
                    int index2 = index - 1;
                    while (index2 >= 0)
                    {
                        if (this [index] != 0)
                        {
                            goto round_up;
                        }
                        index2--;
                    }
                    goto round_down;
                }

round_up:
                value += rounding_correction;
round_down:

                /* note, ldexp `sticks' at the maximal non-infinity value, which
                 * is a reasonable compromise for numbers with DBL_MAX_EXP bits
                 * that round up */
                if (scale_words > 0)
                {
                    value = FloatArithmetic.LdExp(value, scale_words * BIGNUM_DIGIT_LENGTH);
                }

finished:
                return(this.IsNegative ? (-value) : value);
            }
        }
Ejemplo n.º 23
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);
 }
Ejemplo n.º 24
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 ();
 }
Ejemplo n.º 25
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);
}