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; } }
void DestructiveCopy(Bignum target) { for (int i = 0; i < this.Length; i++) { target [i] = this [i]; } }
Bignum NewSign(bool sign) { Bignum result = new Bignum(sign, this.Length); this.DestructiveCopy(result); return(result); }
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); } }
// 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); }
Bignum Copy() { Bignum target = new Bignum(this.IsNegative, this.Length); this.DestructiveCopy(target); return(target); }
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); }
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()); }
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()); }
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(); } } }
Bignum MaybeNewSign(bool sign) { if (this.IsNegative ? sign : (!sign)) { return(this); } Bignum answer = new Bignum(sign, this.Length); this.DestructiveCopy(answer); return(answer); }
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; }
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; }
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); } }
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)); }
Bignum NewSign (bool sign) { Bignum result = new Bignum (sign, this.Length); this.DestructiveCopy (result); return result; }
Bignum Copy () { Bignum target = new Bignum (this.IsNegative, this.Length); this.DestructiveCopy (target); return target; }
Bignum RemainderUnsignedSmallDenominator(Bignum d, bool sign) { throw new NotImplementedException(); }
static void bignum_divide_unsigned_medium_denominator (Bignum numerator, BignumDigit denominator, out Bignum quotient, out Bignum remainder, bool qsign, bool rsign) { throw new NotImplementedException (); }
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 (); } } }
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 (); }
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 (); }
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; }
Bignum MaybeNewSign (bool sign) { if (this.IsNegative ? sign : (!sign)) return this; Bignum answer = new Bignum (sign, this.Length); this.DestructiveCopy (answer); return answer; }
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 }
static void bignum_divide_unsigned_medium_denominator(Bignum numerator, BignumDigit denominator, out Bignum quotient, out Bignum remainder, bool qsign, bool rsign) { throw new NotImplementedException(); }
void DestructiveCopy (Bignum target) { for (int i = 0; i < this.Length; i++) target [i] = this [i]; }
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); }
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); }
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; }
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; }
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 }
// 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; }
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); }
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); }
Bignum RemainderUnsignedSmallDenominator (Bignum d, bool sign) { throw new NotImplementedException (); }
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; }
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); }