public override object Clone() { RBignum big = new RBignum(ruby, len, sign); Array.Copy(digits, big.digits, len); return(big); }
static private RBignum to_big(NetRuby ruby, object o) { RBignum y = null; if (o is RFixnum) { o = ((RFixnum)o).GetData(); } if (o is RBignum) { y = (RBignum)o; } if (o is int) { y = Int2Big(ruby, (int)o); } else if (o is long) { y = Long2Big(ruby, (long)o); } else if (o is double) { y = Dbl2Big(ruby, (double)o); } else if (o is RFloat) { y = Dbl2Big(ruby, ((RFloat)o).Double); } return(y); }
public static RBignum operator %(RBignum x, RBignum y) { RBignum mod; RBignum div = x.divrem(y, out mod); return(mod); }
public override RNumeric Divide(object o) { RBignum z; RBignum y = divmod(o, out z); return(y.Normalize); }
public override RArray DivMod(object o) { RBignum z; RBignum y = divmod(o, out z); return(RArray.AssocNew(ruby, y.Normalize, z.Normalize)); }
private RBignum sub(RBignum y) { uint[] xx = digits; uint[] yy = y.digits; int xlen = len; int ylen = y.len; bool sig = true; int i; if (len < y.len) { xx = y.digits; yy = digits; sig = false; xlen = y.len; ylen = len; } else if (len == y.len) { for (i = len; i > 0;) { i--; if (xx[i] > yy[i]) { break; } if (xx[i] < yy[i]) { xx = y.digits; yy = digits; xlen = y.len; ylen = len; sig = false; } } } uint[] z = new uint[xlen]; long num = 0; for (i = 0; i < ylen; i++) { num += (long)xx[i] - yy[i]; z[i] = BIGLO(num); num = BIGDN(num); } while (num != 0 && i < xlen) { num += xx[i]; z[i++] = BIGLO(num); num = BIGDN(num); } while (i < xlen) { z[i] = xx[i]; i++; } return(new RBignum(ruby, z, sig)); }
public static RBignum Ulong2Big(NetRuby ruby, ulong n) { ulong num = (ulong)n; RBignum big = new RBignum(ruby, 2, true); big.digits[0] = (uint)n; big.digits[1] = (uint)(n >> 32); return(big); }
public static RBignum Uint2Big(NetRuby ruby, uint n) { RBignum big = new RBignum(ruby, 1, true); big.digits[0] = n; if (n == 0) { big.len = 0; } return(big); }
private RBignum add(RBignum y, bool s) { bool sig = (s == y.sign); if (sign != sig) { if (sig) { return(y.sub(this)); } return(sub(y)); } uint[] xx = digits; uint[] yy = y.digits; int xlen = len; int ylen = y.len; int nl = len; if (nl > y.len) { nl++; xx = y.digits; yy = digits; xlen = y.len; ylen = len; } else { nl = y.len + 1; } uint[] z = new uint[nl]; ulong num = 0; int i; for (i = 0; i < xlen; i++) { num += (ulong)xx[i] + (ulong)yy[i]; z[i] = BIGLO(num); num = BIGDN(num); } while (num != 0 && i < ylen) { num += yy[i]; z[i++] = BIGLO(num); num = BIGDN(num); } while (i < ylen) { z[i] = yy[i]; i++; } z[i] = (uint)num; return(new RBignum(ruby, z, sig)); }
static internal RInteger ToInteger(NetRuby ruby, double d) { if (d <= Int32.MaxValue && d >= Int32.MinValue) { return(new RFixnum(ruby, (int)d)); } else if (d <= Int64.MaxValue && d >= Int64.MinValue) { return(new RBignum(ruby, (long)d)); } return(RBignum.Dbl2Big(ruby, d)); }
public override bool LE(object o) { RBignum r = to_big(ruby, o); if (r == null) { return((bool)CoerceBin(o)); } int i = CompareTo(r); return(i <= 0); }
private RBignum divmod(object o, out RBignum mod) { mod = null; RBignum y = to_big(ruby, o); RBignum dv = divrem(y, out mod); if (sign != y.sign && mod.len > 0) { dv = dv - to_big(ruby, 1); mod = mod + y; } return(dv); }
public bool Eq(object o) { RBignum y = null; if (o is RFixnum) { o = ((RFixnum)o).GetData(); } if (o is int) { y = Int2Big(ruby, (int)o); } else if (o is long) { y = Long2Big(ruby, (long)o); } else if (o is double) { return(Big2Dbl() == (double)o); } else if (o is RFloat) { return(Big2Dbl() == ((RFloat)o).Double); } else if (o is RBignum == false) { return(false); } else { y = (RBignum)o; } if (sign != y.sign) { return(false); } if (len != y.len) { return(false); } for (int i = 0; i < len; i++) { if (digits[i] != y.digits[i]) { return(false); } } return(true); }
public static RBignum Int2Big(NetRuby ruby, int n) { bool neg = false; if (n < 0) { n = -n; neg = true; } RBignum big = Uint2Big(ruby, (uint)n); if (neg) { big.sign = false; } return(big); }
public static RBignum Long2Big(NetRuby ruby, long n) { bool neg = false; if (n < 0) { n = -n; neg = true; } RBignum big = Ulong2Big(ruby, (ulong)n); if (neg) { big.sign = false; } return(big); }
public RInteger Negate() { RBignum z = (RBignum)Clone(); if (sign == false) { z.TwoComp(); } for (int i = 0; i < len; i++) { z.digits[i] = ~z.digits[i]; } if (sign) { z.TwoComp(); } z.sign = !z.sign; return(z.Normalize); }
public int CompareTo(object o) { RBignum r = to_big(ruby, o); if (r == null) { throw new ArgumentException("object is not a Bignum"); } if (sign && !r.sign) { return(1); } if (!sign && r.sign) { return(-1); } if (len < r.len) { return((sign) ? -1 : 1); } if (len > r.len) { return((sign) ? 1 : -1); } int xlen = len; while ((xlen-- > 0) && digits[xlen] == r.digits[xlen]) { ; } if (xlen < 0) { return(0); } return((digits[xlen] > r.digits[xlen]) ? (sign ? 1 : -1) : (sign ? -1 : 1)); }
private RBignum divrem(RBignum y, out RBignum mod) { mod = null; uint dd; int ny = y.len; int nx = len; int i; ulong t2; if (ny == 0 && y.digits[0] == 0) throw new DivideByZeroException("divided by 0"); if (nx < ny || nx == ny && digits[nx - 1] < y.digits[ny - 1]) { mod = this; return new RBignum(ruby, (uint)0, true); } if (ny == 1) { dd = y.digits[0]; RBignum z = (RBignum)Clone(); i = nx; t2 = 0; while (i-- != 0) { t2 = (ulong)BIGUP(t2) + z.digits[i]; z.digits[i] = (uint)(t2 / dd); t2 %= dd; } z.sign = (sign == y.sign); mod = Uint2Big(ruby, (uint)t2); mod.sign = sign; return z; } uint[] zz = new uint[(nx == ny) ? nx + 2 : nx + 1]; if (nx == ny) zz[nx + 1] = 0; while (y.digits[ny - 1] == 0) ny--; dd = 0; uint q = y.digits[ny - 1]; int j = 0; uint[] ys = y.digits; while ((q & ((uint)1 << (int)(BITSPERDIG-1))) == 0) { q <<= 1; dd++; } if (dd != 0) { RBignum yy = (RBignum)y.Clone(); j = 0; t2 = 0; while (j < ny) { t2 += ((ulong)y.digits[j]) << (int)dd; yy.digits[j++] = BIGLO(t2); t2 = BIGDN(t2); } ys = yy.digits; j = 0; t2 = 0; while (j < nx) { t2 += ((ulong)digits[j]) << (int)dd; zz[j++] = BIGLO(t2); t2 = BIGDN(t2); } zz[j] = (uint)t2; } else { zz[nx] = 0; j = nx; while (j-- != 0) zz[j] = digits[j]; } j = (nx == ny) ? nx + 1 : nx; do { if (zz[j] == ys[ny - 1]) q = (uint)(BIGRAD - 1); else q = (uint)((BIGUP(zz[j]) + zz[j - 1])/ys[ny - 1]); if (q != 0) { i = 0; long num = 0; t2 = 0; do { t2 += (ulong)ys[i] * q; ulong ee = (ulong)(num - BIGLO(t2)); num = (long)(zz[j - ny + i] + ee); if (ee != 0) zz[j - ny + i] = BIGLO(num); num = BIGDN(num); t2 = BIGDN(t2); } while (++i < ny); num += (long)(zz[j - ny + i] - t2); while (num != 0) { i = 0; num = 0; q--; do { ulong ee = (ulong)(num + ys[i]); num = (long)((ulong)zz[j - ny + i] + ee); if (ee != 0) zz[j - ny + i] = BIGLO(num); num = BIGDN(num); } while (++i < ny); num--; } } zz[j] = q; } while (--j >= ny); RBignum div = new RBignum(ruby, zz, sign == y.sign); mod = (RBignum)div.Clone(); j = (nx == ny ? nx + 2 : nx + 1) - ny; for (i = 0; i < j; i++) div.digits[i] = div.digits[i + ny]; div.len = i; while (ny-- != 0 && mod.digits[ny] == 0); ny++; if (dd != 0) { t2 = 0; i = ny; while (i-- != 0) { t2 = (t2 | mod.digits[i]) >> (int)dd; q = mod.digits[i]; mod.digits[i] = BIGLO(t2); t2 = BIGUP(q); } mod.len = ny; mod.sign = sign; } return div; }
private RBignum add(RBignum y, bool s) { bool sig = (s == y.sign); if (sign != sig) { if (sig) return y.sub(this); return sub(y); } uint[] xx = digits; uint[] yy = y.digits; int xlen = len; int ylen = y.len; int nl = len; if (nl > y.len) { nl++; xx = y.digits; yy = digits; xlen = y.len; ylen = len; } else { nl = y.len + 1; } uint[] z = new uint[nl]; ulong num = 0; int i; for (i = 0; i < xlen; i++) { num += (ulong)xx[i] + (ulong)yy[i]; z[i] = BIGLO(num); num = BIGDN(num); } while (num != 0 && i < ylen) { num += yy[i]; z[i++] = BIGLO(num); num = BIGDN(num); } while (i < ylen) { z[i] = yy[i]; i++; } z[i] = (uint)num; return new RBignum(ruby, z, sig); }
private RBignum sub(RBignum y) { uint[] xx = digits; uint[] yy = y.digits; int xlen = len; int ylen = y.len; bool sig = true; int i; if (len < y.len) { xx = y.digits; yy = digits; sig = false; xlen = y.len; ylen = len; } else if (len == y.len) { for (i = len; i > 0; ) { i--; if (xx[i] > yy[i]) break; if (xx[i] < yy[i]) { xx = y.digits; yy = digits; xlen = y.len; ylen = len; sig = false; } } } uint[] z = new uint[xlen]; long num = 0; for (i = 0; i < ylen; i++) { num += (long)xx[i] - yy[i]; z[i] = BIGLO(num); num = BIGDN(num); } while (num != 0 && i < xlen) { num += xx[i]; z[i++] = BIGLO(num); num = BIGDN(num); } while (i < xlen) { z[i] = xx[i]; i++; } return new RBignum(ruby, z, sig); }
private RBignum divmod(object o, out RBignum mod) { mod = null; RBignum y = to_big(ruby, o); RBignum dv = divrem(y, out mod); if (sign != y.sign && mod.len > 0) { dv = dv - to_big(ruby, 1); mod = mod + y; } return dv; }
public static RBignum Ulong2Big(NetRuby ruby, ulong n) { ulong num = (ulong)n; RBignum big = new RBignum(ruby, 2, true); big.digits[0] = (uint)n; big.digits[1] = (uint)(n >> 32); return big; }
public static RBignum Uint2Big(NetRuby ruby, uint n) { RBignum big = new RBignum(ruby, 1, true); big.digits[0] = n; if (n == 0) big.len = 0; return big; }
internal static object StringToInteger(NetRuby ruby, string astr, int radix) { RBignum z = null; bool badcheck = (radix == 0) ? true : false; string str = astr.Trim().ToUpper().Replace("_", ""); bool sign = true; int idx = 0; if (astr.Length == 1) { return Convert.ToInt32(str); } if (str[0] == '+') { idx++; } else if (str[0] == '-') { idx++; sign = false; } if (str[idx] == '+' || str[idx] == '-') { if (badcheck) goto bad; return 0; } if (radix == 0) { if (str[idx] == '0' && (idx + 1) < str.Length) { char c = str[idx + 1]; if (c == 'X') { radix = 16; } else if (c == 'B') { radix = 2; } else { radix = 8; } } else { radix = 10; } } int len = str.Length; if (radix == 8) { while (idx < str.Length && str[idx] == '0') idx++; if (idx == str.Length) return 0; str = str.Substring(idx); len = 3 * str.Length; } else { if (radix == 16 && str[idx] == '0' && str[idx + 1] == 'X') idx += 2; else if (radix == 2 && str[idx] == '0' && str[idx + 1] == 'B') idx += 2; while (idx < str.Length && str[idx] == '0') idx++; if (idx == str.Length) { if (badcheck) goto bad; return 0; } str = str.Substring(idx); len = 4 * str.Length; } uint x; if (len <= 32) { try { x = Convert.ToUInt32(str, radix); if (x > (uint)Int32.MaxValue) { return new RBignum(ruby, x, sign); } else { int xx = (int)x; return (sign) ? xx : -xx; } } catch (OverflowException) { ; } catch { goto bad; } } len = (int)(len / BITSPERDIG) + 1; uint[] zds = new uint[len]; int blen = 1; for (idx = 0; idx < str.Length; idx++) { char c = str[idx]; switch (c) { case '8': case '9': if (radix == 8) { c = (char)radix; break; } goto case '0'; case '7': case '6': case '5': case '4': case '3': case '2': case '1': case '0': c = (char)(c - '0'); break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': if (radix != 16) c = (char)radix; else c = (char)(c - 'A' + 10); break; default: c = (char)radix; break; } if (c >= radix) break; int i = 0; ulong num = c; for (;;) { while (i < blen) { num += (ulong)zds[i] * (ulong)radix; zds[i++] = BIGLO(num); num = BIGDN(num); } if (num != 0) { blen++; continue; } break; } } z = new RBignum(ruby, zds, sign); return z; bad: throw new eArgError("Invalid value for Integer: \"" + astr + "\""); }
internal static object StringToInteger(NetRuby ruby, string astr, int radix) { RBignum z = null; bool badcheck = (radix == 0) ? true : false; string str = astr.Trim().ToUpper().Replace("_", ""); bool sign = true; int idx = 0; if (astr.Length == 1) { return(Convert.ToInt32(str)); } if (str[0] == '+') { idx++; } else if (str[0] == '-') { idx++; sign = false; } if (str[idx] == '+' || str[idx] == '-') { if (badcheck) { goto bad; } return(0); } if (radix == 0) { if (str[idx] == '0' && (idx + 1) < str.Length) { char c = str[idx + 1]; if (c == 'X') { radix = 16; } else if (c == 'B') { radix = 2; } else { radix = 8; } } else { radix = 10; } } int len = str.Length; if (radix == 8) { while (idx < str.Length && str[idx] == '0') { idx++; } if (idx == str.Length) { return(0); } str = str.Substring(idx); len = 3 * str.Length; } else { if (radix == 16 && str[idx] == '0' && str[idx + 1] == 'X') { idx += 2; } else if (radix == 2 && str[idx] == '0' && str[idx + 1] == 'B') { idx += 2; } while (idx < str.Length && str[idx] == '0') { idx++; } if (idx == str.Length) { if (badcheck) { goto bad; } return(0); } str = str.Substring(idx); len = 4 * str.Length; } uint x; if (len <= 32) { try { x = Convert.ToUInt32(str, radix); if (x > (uint)Int32.MaxValue) { return(new RBignum(ruby, x, sign)); } else { int xx = (int)x; return((sign) ? xx : -xx); } } catch (OverflowException) { ; } catch { goto bad; } } len = (int)(len / BITSPERDIG) + 1; uint[] zds = new uint[len]; int blen = 1; for (idx = 0; idx < str.Length; idx++) { char c = str[idx]; switch (c) { case '8': case '9': if (radix == 8) { c = (char)radix; break; } goto case '0'; case '7': case '6': case '5': case '4': case '3': case '2': case '1': case '0': c = (char)(c - '0'); break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': if (radix != 16) { c = (char)radix; } else { c = (char)(c - 'A' + 10); } break; default: c = (char)radix; break; } if (c >= radix) { break; } int i = 0; ulong num = c; for (;;) { while (i < blen) { num += (ulong)zds[i] * (ulong)radix; zds[i++] = BIGLO(num); num = BIGDN(num); } if (num != 0) { blen++; continue; } break; } } z = new RBignum(ruby, zds, sign); return(z); bad: throw new eArgError("Invalid value for Integer: \"" + astr + "\""); }
public override object Clone() { RBignum big = new RBignum(ruby, len, sign); Array.Copy(digits, big.digits, len); return big; }
internal static object sprintf(RBasic r, params object[] args) { NetRuby ruby = r.ruby; PFlag flags = PFlag.NONE; bool tainted = false; object ofmt; int nextarg = getarg(args, 0, out ofmt); if (ofmt is RBasic) { tainted = ((RBasic)ofmt).IsTainted; } string fmt = ofmt.ToString(); string result = String.Empty; int width, prec; for (int i = 0; i < fmt.Length; i++) { int n, ix; for (ix = i; ix < fmt.Length && fmt[ix] != '%'; ix++) { ; } result += fmt.Substring(i, ix - i); if (ix >= fmt.Length) { break; } i = ix + 1; width = prec = -1; retry: switch (fmt[i]) { case ' ': flags |= PFlag.SPACE; i++; goto retry; case '#': flags |= PFlag.SHARP; i++; goto retry; case '+': flags |= PFlag.PLUS; i++; goto retry; case '-': flags |= PFlag.MINUS; i++; goto retry; case '0': flags |= PFlag.ZERO; i++; goto retry; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': n = 0; for (; i < fmt.Length && Char.IsDigit(fmt[i]); i++) { n = 10 * n + (int)Char.GetNumericValue(fmt[i]); } if (i >= fmt.Length) { throw new ArgumentException("malformed format string - %%[0-9]"); } if (fmt[i] == '$') { nextarg = n; i++; goto retry; } width = n; flags |= PFlag.WIDTH; goto retry; case '*': if ((flags & PFlag.WIDTH) != 0) { throw new ArgumentException("width given twice"); } flags |= PFlag.WIDTH; width = getaster(fmt, ref i, ref nextarg, args); if (width < 0) { flags |= PFlag.MINUS; width = -width; } i++; goto retry; case '.': if ((flags & PFlag.PREC) != 0) { throw new ArgumentException("precision given twice"); } flags |= PFlag.PREC; prec = 0; i++; if (fmt[i] == '*') { prec = getaster(fmt, ref i, ref nextarg, args); if (prec < 0) /* ignore negative precision */ { flags &= ~PFlag.PREC; } i++; goto retry; } for (; i < fmt.Length && Char.IsDigit(fmt[i]); i++) { prec = 10 * prec + (int)Char.GetNumericValue(fmt[i]); } if (i >= fmt.Length) { throw new ArgumentException("malformed format string - %%.[0-9]"); } goto retry; case '\n': i--; goto case '%'; case '\0': case '%': if (flags != PFlag.NONE) { throw new ArgumentException("illegal format character - %%"); } result += '%'; break; case 'c': { object val; nextarg = getarg(args, nextarg, out val); if ((flags & PFlag.MINUS) == 0) { if (width > 0) { result = result.PadRight(result.Length + width); } } char c = (char)Convert.ToInt32(val); result += c; result = result.PadRight(result.Length + width); break; } case 's': { object arg; nextarg = getarg(args, nextarg, out arg); RString rs = RString.AsRString(ruby, arg); if (rs.IsTainted) { tainted = true; } int len = rs.Length; if ((flags & PFlag.PREC) != 0) { if (prec < len) { len = prec; } } if ((flags & PFlag.WIDTH) != 0) { if (width > len) { width -= len; if ((flags & PFlag.MINUS) == 0) { if (width > 0) { result = result.PadRight(result.Length + width); } } result += rs.ToString(); if ((flags & PFlag.MINUS) != 0) { if (width > 0) { result = result.PadRight(result.Length + width); } } break; } } result += rs.ToString().Substring(0, len); break; } case 'd': case 'i': case 'o': case 'x': case 'X': case 'b': case 'u': { char sc = '\0'; char ch = fmt[i]; object val; nextarg = getarg(args, nextarg, out val); bool sign = false; bool bignum = false; long num = 0; string prefix = String.Empty; string s = String.Empty; switch (ch) { case 'd': case 'i': sign = true; break; case 'o': case 'x': case 'X': case 'b': case 'u': default: if ((flags & (PFlag.PLUS | PFlag.SPACE)) != 0) { sign = true; } break; } if ((flags & PFlag.SHARP) != 0) { if (fmt[i] == 'o') { prefix = "0"; } else if (fmt[i] == 'x') { prefix = "0x"; } else if (fmt[i] == 'X') { prefix = "0X"; } else if (fmt[i] == 'b') { prefix = "0b"; } if (prefix.Length > 0) { width -= prefix.Length; } } bin_retry: if (val is RFloat) { val = ((RFloat)val).ToInteger(); goto bin_retry; } else if (val is double) { val = RFloat.ToInteger(ruby, (double)val); goto bin_retry; } else if (val is string) { val = RInteger.StringToInteger(ruby, (string)val, 0); goto bin_retry; } else if (val is RString) { val = ((RString)val).ToInteger(); goto bin_retry; } else if (val is int) { num = (long)(int)val; } else if (val is long) { num = (long)val; } else if (val is uint) { num = (long)(uint)val; } else if (val is RBignum) { bignum = true; } else { num = RInteger.ToLong(ruby, val); } int bas = 0; if (ch == 'u' || ch == 'd' || ch == 'i') { bas = 10; } else if (ch == 'x' || ch == 'X') { bas = 16; } else if (ch == 'o') { bas = 8; } else if (ch == 'b') { bas = 2; } if (!bignum) { if (sign) { if (ch == 'i') { ch = 'd'; /* %d and %i are identical */ } if (num < 0) { num = -num; sc = '-'; width--; } else if ((flags & PFlag.PLUS) != 0) { sc = '+'; width--; } else if ((flags & PFlag.SPACE) != 0) { sc = ' '; width--; } s = Convert.ToString(num, bas); goto format_integer; } else { s = Convert.ToString(num, bas); goto format_integer; } } // bignum RBignum big = (RBignum)val; if (sign) { s = big.ToRString(bas).ToString(); if (s[0] == '-') { s = s.Substring(1); sc = '-'; width--; } else if ((flags & PFlag.PLUS) != 0) { sc = '+'; width--; } else if ((flags & PFlag.SPACE) != 0) { sc = ' '; width--; } goto format_integer; } if (big.Sign == false) { big = (RBignum)big.Clone(); big.TwoComp(); } s = big.ToRString(bas).ToString(); if (s[0] == '-') { s = remove_sign_bits(s.Substring(1), bas); StringBuilder sb = new StringBuilder(s.Length + 3); sb.Append(".."); switch (bas) { case 16: if (s[0] != 'f') { sb.Append('f'); } break; case 8: if (s[0] != '7') { sb.Append('7'); } break; } sb.Append(s); s = sb.ToString(); } format_integer: int pos = -1; int len = s.Length; if (ch == 'X') { s = s.ToUpper(); } if (prec < len) { prec = len; } width -= prec; if ((flags & (PFlag.ZERO | PFlag.MINUS)) == 0 && s[0] != '.') { if (width > 0) { s = s.PadLeft(s.Length + width); } } if (sc != '\0') { result += sc; } if (prefix.Length > 0) { result += prefix; if (pos != 0) { pos += prefix.Length; } } if ((flags & PFlag.MINUS) == 0) { char c = ' '; if (s[0] == '.') { c = '.'; if ((flags & PFlag.PREC) != 0 && prec > len) { pos = result.Length; } else { pos = result.Length + 2; } } else if ((flags & PFlag.ZERO) != 0) { c = '0'; } if (width > 0) { result = result.PadRight(result.Length + width, c); } } if (len < prec) { if (width > 0) { result = result.PadRight(result.Length + (prec - len), (s[0] == '.'?'.':'0')); } } result += s; if (width > 0) { result = result.PadRight(result.Length + width); } break; } case 'f': case 'g': case 'G': case 'e': case 'E': { object val; nextarg = getarg(args, nextarg, out val); double fval = 0.0; if (val is RString || val is string) { fval = Convert.ToDouble(((RString)val).ToString()); } else if (val is int || val is long || val is uint) { fval = Convert.ToDouble(val); } else if (val is RFloat) { fval = ((RFloat)val).Double; } else if (val is double) { fval = (double)val; } string buf; if (fmt[i] != 'e' && fmt[i] != 'E') { buf = new String(fmt[i], 1); if ((flags & PFlag.PREC) != 0) { buf += prec.ToString(); } } else { buf = "#"; if ((flags & PFlag.SHARP) != 0) { buf += ".0"; } buf += fmt[i]; if ((flags & PFlag.PLUS) != 0) { buf += '+'; } if ((flags & PFlag.PREC) != 0) { buf += new String('0', prec); } else { buf += '0'; } } buf = fval.ToString(buf); if ((flags & PFlag.WIDTH) != 0) { } result += buf; break; } default: throw new ArgumentException(String.Format("malformed format string - %{0}", fmt[i])); } flags = PFlag.NONE; } if (tainted) { return(new RString(ruby, result, true)); } return(result); }
private RBignum divrem(RBignum y, out RBignum mod) { mod = null; uint dd; int ny = y.len; int nx = len; int i; ulong t2; if (ny == 0 && y.digits[0] == 0) { throw new DivideByZeroException("divided by 0"); } if (nx < ny || nx == ny && digits[nx - 1] < y.digits[ny - 1]) { mod = this; return(new RBignum(ruby, (uint)0, true)); } if (ny == 1) { dd = y.digits[0]; RBignum z = (RBignum)Clone(); i = nx; t2 = 0; while (i-- != 0) { t2 = (ulong)BIGUP(t2) + z.digits[i]; z.digits[i] = (uint)(t2 / dd); t2 %= dd; } z.sign = (sign == y.sign); mod = Uint2Big(ruby, (uint)t2); mod.sign = sign; return(z); } uint[] zz = new uint[(nx == ny) ? nx + 2 : nx + 1]; if (nx == ny) { zz[nx + 1] = 0; } while (y.digits[ny - 1] == 0) { ny--; } dd = 0; uint q = y.digits[ny - 1]; int j = 0; uint[] ys = y.digits; while ((q & ((uint)1 << (int)(BITSPERDIG - 1))) == 0) { q <<= 1; dd++; } if (dd != 0) { RBignum yy = (RBignum)y.Clone(); j = 0; t2 = 0; while (j < ny) { t2 += ((ulong)y.digits[j]) << (int)dd; yy.digits[j++] = BIGLO(t2); t2 = BIGDN(t2); } ys = yy.digits; j = 0; t2 = 0; while (j < nx) { t2 += ((ulong)digits[j]) << (int)dd; zz[j++] = BIGLO(t2); t2 = BIGDN(t2); } zz[j] = (uint)t2; } else { zz[nx] = 0; j = nx; while (j-- != 0) { zz[j] = digits[j]; } } j = (nx == ny) ? nx + 1 : nx; do { if (zz[j] == ys[ny - 1]) { q = (uint)(BIGRAD - 1); } else { q = (uint)((BIGUP(zz[j]) + zz[j - 1]) / ys[ny - 1]); } if (q != 0) { i = 0; long num = 0; t2 = 0; do { t2 += (ulong)ys[i] * q; ulong ee = (ulong)(num - BIGLO(t2)); num = (long)(zz[j - ny + i] + ee); if (ee != 0) { zz[j - ny + i] = BIGLO(num); } num = BIGDN(num); t2 = BIGDN(t2); }while (++i < ny); num += (long)(zz[j - ny + i] - t2); while (num != 0) { i = 0; num = 0; q--; do { ulong ee = (ulong)(num + ys[i]); num = (long)((ulong)zz[j - ny + i] + ee); if (ee != 0) { zz[j - ny + i] = BIGLO(num); } num = BIGDN(num); }while (++i < ny); num--; } } zz[j] = q; }while (--j >= ny); RBignum div = new RBignum(ruby, zz, sign == y.sign); mod = (RBignum)div.Clone(); j = (nx == ny ? nx + 2 : nx + 1) - ny; for (i = 0; i < j; i++) { div.digits[i] = div.digits[i + ny]; } div.len = i; while (ny-- != 0 && mod.digits[ny] == 0) { ; } ny++; if (dd != 0) { t2 = 0; i = ny; while (i-- != 0) { t2 = (t2 | mod.digits[i]) >> (int)dd; q = mod.digits[i]; mod.digits[i] = BIGLO(t2); t2 = BIGUP(q); } mod.len = ny; mod.sign = sign; } return(div); }