Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 40844ffaa39d
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 17ff676dbbd8
Choose a head ref
  • 4 commits
  • 13 files changed
  • 1 contributor

Commits on Sep 28, 2015

  1. Copy the full SHA
    61c7a8e View commit details
  2. Copy the full SHA
    e79dbfd View commit details
  3. Copy the full SHA
    48a4e24 View commit details
  4. 2
    Copy the full SHA
    17ff676 View commit details
84 changes: 54 additions & 30 deletions core/src/main/java/org/jruby/RubyRandom.java
Original file line number Diff line number Diff line change
@@ -56,39 +56,55 @@ public static class RandomType {
RandomType(IRubyObject vseed) {
this.seed = vseed.convertToInteger();
if (seed instanceof RubyFixnum) {
long v = Math.abs(RubyNumeric.num2long(seed));
if (v == (v & 0xffffffffL)) {
this.mt = new Random((int) v);
} else {
int[] ints = new int[2];
ints[0] = (int) v;
ints[1] = (int) (v >> 32);
this.mt = new Random(ints);
}
this.mt = randomFromFixnum((RubyFixnum) seed);
} else if (seed instanceof RubyBignum) {
BigInteger big = ((RubyBignum) seed).getBigIntegerValue();
if (big.signum() < 0) {
big = big.abs();
}
byte[] buf = big.toByteArray();
int buflen = buf.length;
if (buf[0] == 0) {
buflen -= 1;
}
int len = Math.min((buflen + 3) / 4, Random.N);
int[] ints = bigEndianToInts(buf, len);
if (len <= 1) {
this.mt = new Random(ints[0]);
} else {
this.mt = new Random(ints);
}
this.mt = randomFromBignum((RubyBignum) seed);
} else {
throw vseed.getRuntime().newTypeError(
String.format("failed to convert %s into Integer", vseed.getMetaClass()
.getName()));
}
}

public static Random randomFromFixnum(RubyFixnum seed) {
return randomFromLong(RubyNumeric.num2long(seed));
}

public static Random randomFromLong(long seed) {
long v = Math.abs(seed);
if (v == (v & 0xffffffffL)) {
return new Random((int) v);
} else {
int[] ints = new int[2];
ints[0] = (int) v;
ints[1] = (int) (v >> 32);
return new Random(ints);
}
}

public static Random randomFromBignum(RubyBignum seed) {
BigInteger big = seed.getBigIntegerValue();
return randomFromBigInteger(big);
}

public static Random randomFromBigInteger(BigInteger big) {
if (big.signum() < 0) {
big = big.abs();
}
byte[] buf = big.toByteArray();
int buflen = buf.length;
if (buf[0] == 0) {
buflen -= 1;
}
int len = Math.min((buflen + 3) / 4, Random.N);
int[] ints = bigEndianToInts(buf, len);
if (len <= 1) {
return new Random(ints[0]);
} else {
return new Random(ints);
}
}

RandomType(IRubyObject vseed, RubyBignum state, int left) {
this.seed = vseed.convertToInteger();
byte[] bytes = state.getBigIntegerValue().toByteArray();
@@ -152,7 +168,7 @@ int getLeft() {
}

// big endian of bytes to reversed ints
private int[] bigEndianToInts(byte[] buf, int initKeyLen) {
private static int[] bigEndianToInts(byte[] buf, int initKeyLen) {
int[] initKey = new int[initKeyLen];
for (int idx = 0; idx < initKey.length; ++idx) {
initKey[idx] = getIntBigIntegerBuffer(buf, idx);
@@ -197,11 +213,15 @@ static void setIntBigIntegerBuffer(byte[] dest, int loc, int value) {

private static final int DEFAULT_SEED_CNT = 4;

public static BigInteger randomSeedBigInteger(java.util.Random random) {
byte[] seed = new byte[DEFAULT_SEED_CNT * 4];
random.nextBytes(seed);
return new BigInteger(seed).abs();
}

// c: random_seed
public static RubyBignum randomSeed(Ruby runtime) {
byte[] seed = new byte[DEFAULT_SEED_CNT * 4];
runtime.getRandom().nextBytes(seed);
return RubyBignum.newBignum(runtime, (new BigInteger(seed)).abs());
return RubyBignum.newBignum(runtime, randomSeedBigInteger(runtime.getRandom()));
}

public static RubyClass createRandomClass(Ruby runtime) {
@@ -358,6 +378,10 @@ public static RubyFloat randFloat(ThreadContext context, RandomType random) {
// limited_rand gets/returns ulong but we do this in signed long only.
private static IRubyObject randLimitedFixnum(ThreadContext context, RandomType random,
long limit) {
return RubyFixnum.newFixnum(context.getRuntime(), randLimitedFixnumInner(random.mt, limit));
}

public static long randLimitedFixnumInner(Random random, long limit) {
long val;
if (limit == 0) {
val = 0;
@@ -378,7 +402,7 @@ private static IRubyObject randLimitedFixnum(ThreadContext context, RandomType r
break;
}
}
return context.runtime.newFixnum(val);
return val;
}

// c: limited_big_rand
3 changes: 3 additions & 0 deletions core/src/main/java/org/jruby/util/Random.java
Original file line number Diff line number Diff line change
@@ -46,6 +46,9 @@ private static int TWIST(int u, int v) {
private final int[] state = new int[N];
private int left = 1;

public Random() {
}

public Random(int s) {
initGenrand(s);
}
85 changes: 85 additions & 0 deletions spec/truffle/specs/truffle/rand.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
# code is released under a tri EPL/GPL/LGPL license. You can use it,
# redistribute it and/or modify it under the terms of the:
#
# Eclipse Public License version 1.0
# GNU General Public License version 2
# GNU Lesser General Public License version 2.1

require_relative '../../../ruby/spec_helper'

describe "Random" do

describe "#rand" do

it "with no argument returns the same numbers as other implementations of Ruby, given the same seed" do
sequences = {
0 => [0.5488135039273248,
0.7151893663724195,
0.6027633760716439,
0.5448831829968969,
0.4236547993389047,
0.6458941130666561,
0.4375872112626925,
0.8917730007820798,
0.9636627605010293,
0.3834415188257777],
493 => [0.9242902863998772,
0.9535656843746261,
0.6644462711803232,
0.36372128443753204,
0.9372152897557885,
0.7102477795195669,
0.7378911367923787,
0.5161160225418484,
0.9743222615926629,
0.5440861076647412]
}

sequences.each do |seed, sequence|
r = Random.new(seed)
sequence.each do |n|
r.rand.to_s.should == n.to_s
end
end
end

end

describe "#rand" do

it "with a maximum of 100 returns the same numbers as other implementations of Ruby, given the same seed" do
sequences = {
0 => [44,
47,
64,
67,
67,
9,
83,
21,
36,
87],
493 => [82,
34,
44,
25,
17,
1,
87,
76,
86,
46]
}

sequences.each do |seed, sequence|
r = Random.new(seed)
sequence.each do |n|
r.rand(100).should == n
end
end
end

end

end
1 change: 0 additions & 1 deletion spec/truffle/tags/core/random/bytes_tags.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
fails:Random#bytes returns the same output for a given seed
fails:Random#bytes returns the same numeric output for a given seed accross all implementations and platforms
fails:Random#bytes returns the same numeric output for a given huge seed accross all implementations and platforms
10 changes: 0 additions & 10 deletions spec/truffle/tags/core/random/rand_tags.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1 @@
fails:Random.rand returns the same sequence for a given seed if no max argument is passed
fails:Random.rand returns the same sequence for a given seed if an Integer argument is passed
fails:Random#rand with Fixnum eventually returns all possible values
fails:Random#rand with Bignum typically returns a Bignum
fails:Random#rand with Bignum returns the same sequence for a given seed
fails:Random#rand with Float returns the same sequence for a given seed
fails:Random#rand with Fixnum returns the same sequence for a given seed
fails:Random#rand with Range works with inclusive ranges
fails:Random#rand with Range works with exclusive ranges
fails:Random#rand with Range returns the same sequence for a given seed
fails:Random#rand with Range eventually returns all possible values
1 change: 0 additions & 1 deletion spec/truffle/tags/core/random/srand_tags.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
fails:Random.srand seeds Random.rand such that its return value is deterministic
fails:Random.srand seeds Kernel.rand such that its return value is deterministic

This file was deleted.

Loading