// 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_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)); }