// c: rb_f_srand public static IRubyObject srandCommon( ThreadContext context, IRubyObject recv, IRubyObject newSeed) { RandomType defaultRand = getDefaultRand(context); IRubyObject previousSeed = defaultRand.getSeed(); defaultRand = new RandomType(newSeed); context.runtime.setDefaultRand(defaultRand); ((RubyRandom) (context.runtime.getRandomClass()).getConstant("DEFAULT")) .setRandomType(defaultRand); return previousSeed; }
// c: random_dump @JRubyMethod(name = "marshal_dump") public IRubyObject marshal_dump(ThreadContext context) { RubyBignum state = random.getState(); RubyInteger left = (RubyInteger) RubyNumeric.int2fix(context.runtime, random.getLeft()); RubyArray dump = RubyArray.newArray(context.runtime, state, left, random.getSeed()); if (hasVariables()) { dump.syncVariables(this); } return dump; }
// c: limited_big_rand private static IRubyObject randLimitedBignum( ThreadContext context, RandomType random, RubyBignum limit) { byte[] buf = limit.getBigIntegerValue().toByteArray(); byte[] bytes = new byte[buf.length]; int len = (buf.length + 3) / 4; // take care before code cleanup; it might break random sequence compatibility retry: while (true) { long mask = 0; boolean boundary = true; for (int idx = len - 1; 0 <= idx; --idx) { long lim = getIntBigIntegerBuffer(buf, idx) & 0xffffffffL; mask = (mask != 0) ? 0xffffffffL : makeMask(lim); long rnd; if (mask != 0) { rnd = (random.genrandInt32() & 0xffffffffL) & mask; if (boundary) { if (lim < rnd) { continue retry; } if (rnd < lim) { boundary = false; } } } else { rnd = 0; } setIntBigIntegerBuffer(bytes, idx, (int) rnd); } break; } return RubyBignum.newBignum(context.runtime, new BigInteger(bytes)); }
// c: rb_random_real public static double randomReal(ThreadContext context, IRubyObject obj) { RandomType random = null; if (obj.equals(context.runtime.getRandomClass())) { random = getDefaultRand(context); } if (obj instanceof RubyRandom) { random = ((RubyRandom) obj).random; } if (random != null) { return random.genrandReal(); } double d = RubyNumeric.num2dbl(Helpers.invoke(context, obj, "rand")); if (d < 0.0 || d >= 1.0) { throw context.runtime.newRangeError("random number too big: " + d); } return d; }
// c: random_equal @Deprecated @Override @JRubyMethod(name = "==", required = 1) public IRubyObject op_equal_19(ThreadContext context, IRubyObject obj) { if (!getType().equals(obj.getType())) { return context.runtime.getFalse(); } return context.runtime.newBoolean(random.equals(((RubyRandom) obj).random)); }
// c: rb_random_bytes @JRubyMethod(name = "bytes") public IRubyObject bytes(ThreadContext context, IRubyObject arg) { int n = RubyNumeric.num2int(arg); byte[] bytes = new byte[n]; int idx = 0; for (; n >= 4; n -= 4) { int r = random.genrandInt32(); for (int i = 0; i < 4; ++i) { bytes[idx++] = (byte) (r & 0xff); r >>>= 8; } } if (n > 0) { int r = random.genrandInt32(); for (int i = 0; i < n; ++i) { bytes[idx++] = (byte) (r & 0xff); r >>>= 8; } } return context.runtime.newString(new ByteList(bytes)); }
// c: random_left @JRubyMethod(name = "left", visibility = PRIVATE) public IRubyObject leftObj(ThreadContext context) { return RubyNumeric.int2fix(context.runtime, random.getLeft()); }
// c: random_state @JRubyMethod(name = "state", visibility = PRIVATE) public IRubyObject stateObj(ThreadContext context) { return random.getState(); }
// c: random_rand private static IRubyObject randomRand( ThreadContext context, IRubyObject vmax, RandomType random) { IRubyObject v; RangeLike range = null; if (vmax.isNil()) { v = context.nil; } else if ((v = checkMaxInt(context, vmax)) != null) { v = randInt(context, random, (RubyInteger) v, true); } else if (!(v = TypeConverter.checkFloatType(context.runtime, vmax)).isNil()) { double max = floatValue(v); if (max > 0.0) { v = context.runtime.newFloat(max * random.genrandReal()); } else { v = context.nil; } } else if ((range = rangeValues(context, vmax)) != null) { if ((v = checkMaxInt(context, range.range)) != null) { if (v instanceof RubyFixnum) { long max = ((RubyFixnum) v).getLongValue(); if (range.excl) { max -= 1; } if (max >= 0) { v = randLimitedFixnum(context, random, max); } else { v = context.nil; } } else if (v instanceof RubyBignum) { BigInteger big = ((RubyBignum) v).getBigIntegerValue(); if (!big.equals(BigInteger.ZERO) && (big.signum() > 0)) { if (range.excl) { big = big.subtract(BigInteger.ONE); } v = randLimitedBignum(context, random, RubyBignum.newBignum(context.runtime, big)); } else { v = context.nil; } } else { v = context.nil; } } else if (!(v = TypeConverter.checkFloatType(context.runtime, range.range)).isNil()) { int scale = 1; double max = ((RubyFloat) v).getDoubleValue(); double mid = 0.5; double r; if (Double.isInfinite(max)) { double min = floatValue(range.begin) / 2.0; max = floatValue(range.end) / 2.0; scale = 2; mid = max + min; max -= min; } else { floatValue(v); } v = context.nil; if (max > 0.0) { if (range.excl) { r = random.genrandReal(); } else { r = random.genrandReal2(); } if (scale > 1) { return context.runtime.newFloat(+(+(+(r - 0.5) * max) * scale) + mid); } v = context.runtime.newFloat(r * max); } else if (max == 0.0 && !range.excl) { v = context.runtime.newFloat(0.0); } } } else { v = context.nil; RubyNumeric.num2long(vmax); // need check here to raise TypeError } if (v.isNil()) { throw context.runtime.newArgumentError("invalid argument - " + vmax.toString()); } if (range == null) { return v; } if ((range.begin instanceof RubyFixnum) && (v instanceof RubyFixnum)) { long x = ((RubyFixnum) range.begin).getLongValue() + ((RubyFixnum) v).getLongValue(); return context.runtime.newFixnum(x); } if (v instanceof RubyBignum) { return ((RubyBignum) v).op_plus(context, range.begin); } else if (v instanceof RubyFloat) { IRubyObject f = TypeConverter.checkFloatType(context.runtime, range.begin); if (!f.isNil()) { return ((RubyFloat) v).op_plus(context, f); } } return Helpers.invoke(context, range.begin, "+", v); }
public static RubyFloat randFloat(ThreadContext context, RandomType random) { return context.runtime.newFloat(random.genrandReal()); }
@JRubyMethod public IRubyObject seed(ThreadContext context) { return random.getSeed(); }