Skip to content

Commit

Permalink
Showing 3 changed files with 42 additions and 30 deletions.
24 changes: 12 additions & 12 deletions core/src/main/java/org/jruby/RubyArray.java
Original file line number Diff line number Diff line change
@@ -4084,7 +4084,7 @@ public IRubyObject sample(ThreadContext context, IRubyObject[] args) {

if (args.length == 0) {
if (realLength == 0) return context.nil;
return eltOk(realLength == 1 ? 0 : randomReal(context, randgen, realLength));
return eltOk(realLength == 1 ? 0 : RubyRandom.randomLongLimited(context, randgen, realLength - 1));
}

final Ruby runtime = context.runtime;
@@ -4093,10 +4093,10 @@ public IRubyObject sample(ThreadContext context, IRubyObject[] args) {
if (n < 0) throw runtime.newArgumentError("negative sample number");
if (n > realLength) n = realLength;

double[] rnds = new double[SORTED_THRESHOLD];
long[] rnds = new long[SORTED_THRESHOLD];
if (n <= SORTED_THRESHOLD) {
for (int idx = 0; idx < n; ++idx) {
rnds[idx] = RubyRandom.randomReal(context, randgen);
rnds[idx] = RubyRandom.randomLongLimited(context, randgen, realLength - idx - 1);
}
}

@@ -4105,18 +4105,18 @@ public IRubyObject sample(ThreadContext context, IRubyObject[] args) {
case 0:
return newEmptyArray(runtime);
case 1:
return realLength <= 0 ? newEmptyArray(runtime) : newArray(runtime, eltOk((int) (rnds[0] * realLength)));
return realLength <= 0 ? newEmptyArray(runtime) : newArray(runtime, eltOk((int) rnds[0]));
case 2:
i = (int) (rnds[0] * realLength);
j = (int) (rnds[1] * (realLength - 1));
i = (int) rnds[0];
j = (int) rnds[1];

if (j >= i) j++;

return newArray(runtime, eltOk(i), eltOk(j));
case 3:
i = (int) (rnds[0] * realLength);
j = (int) (rnds[1] * (realLength - 1));
k = (int) (rnds[2] * (realLength - 2));
i = (int) rnds[0];
j = (int) rnds[1];
k = (int) rnds[2];

int l = j, g = i;

@@ -4136,9 +4136,9 @@ public IRubyObject sample(ThreadContext context, IRubyObject[] args) {
if (n < SORTED_THRESHOLD) {
int idx[] = new int[SORTED_THRESHOLD];
int sorted[] = new int[SORTED_THRESHOLD];
sorted[0] = idx[0] = (int) (rnds[0] * len);
sorted[0] = idx[0] = (int) rnds[0];
for (i = 1; i < n; i++) {
k = (int) (rnds[i] * --len);
k = (int) rnds[i];
for (j = 0; j < i; j++, k++) {
if (k < sorted[j]) break;
}
@@ -4154,7 +4154,7 @@ public IRubyObject sample(ThreadContext context, IRubyObject[] args) {
IRubyObject[] result = new IRubyObject[len];
System.arraycopy(values, begin, result, 0, len);
for (i = 0; i < n; i++) {
j = randomReal(context, randgen, len - i) + i;
j = (int) RubyRandom.randomLongLimited(context, randgen, len - i - 1) + i;
IRubyObject tmp = result[j];
result[j] = result[i];
result[i] = tmp;
44 changes: 30 additions & 14 deletions core/src/main/java/org/jruby/RubyRandom.java
Original file line number Diff line number Diff line change
@@ -717,23 +717,39 @@ public IRubyObject bytes(ThreadContext context, IRubyObject arg) {
}
return context.runtime.newString(new ByteList(bytes));
}


private static RandomType tryGetRandomType(ThreadContext context, IRubyObject obj) {
if (obj.equals(context.runtime.getRandomClass())) return getDefaultRand(context);
if (obj instanceof RubyRandom) return ((RubyRandom) obj).random;
return null;
}

// rb_random_ulong_limited
public static long randomLongLimited(ThreadContext context, IRubyObject obj, long limit) {
RandomType rnd = tryGetRandomType(context, obj);

if (rnd == null) {
RubyInteger v = Helpers.invoke(context, obj, "rand").convertToInteger();
long r = RubyNumeric.num2long(v);
if (r < 0) throw context.runtime.newRangeError("random number too small " + r);
if (r > limit) throw context.runtime.newRangeError("random number too big " + r);

return r;
}

return randLimitedFixnumInner(rnd.mt, limit);
}

// 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();
}
RandomType random = tryGetRandomType(context, obj);

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

if (d < 0.0 || d >= 1.0) throw context.runtime.newRangeError("random number too big: " + d);

return d;
}

4 changes: 0 additions & 4 deletions spec/tags/ruby/core/array/sample_tags.txt

This file was deleted.

0 comments on commit 63c06b3

Please sign in to comment.