Skip to content

Commit e42db99

Browse files
committed
[GR-23353] Make test_random pass
PullRequest: graalpython/1256
2 parents 56b0725 + b839cb1 commit e42db99

File tree

10 files changed

+353
-118
lines changed

10 files changed

+353
-118
lines changed

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/objects/PythonObjectLibraryTests.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,16 @@
4040
*/
4141
package com.oracle.graal.python.test.objects;
4242

43+
import static org.junit.Assert.assertEquals;
4344
import static org.junit.Assert.assertNotNull;
4445
import static org.junit.Assert.assertNotSame;
4546
import static org.junit.Assert.assertSame;
4647
import static org.junit.Assert.fail;
4748

49+
import java.math.BigInteger;
4850
import java.util.concurrent.Callable;
4951

52+
import com.oracle.graal.python.builtins.objects.ints.PInt;
5053
import org.graalvm.polyglot.Context;
5154
import org.graalvm.polyglot.Value;
5255
import org.graalvm.polyglot.proxy.ProxyExecutable;
@@ -97,6 +100,17 @@ public void testLookupAttribute() {
97100
lookupAttr(() -> "abc", noSuchMethod, true);
98101
}
99102

103+
@Test
104+
public void testPIntAsJavaLong() {
105+
execInContext(() -> {
106+
PInt p = PythonObjectFactory.getUncached().createInt(BigInteger.valueOf(123));
107+
PythonObjectLibrary lib = PythonObjectLibrary.getFactory().getUncached();
108+
assertEquals(123, lib.asJavaLong(p));
109+
assertEquals(123, lib.asJavaLong(p, null));
110+
return null;
111+
});
112+
}
113+
100114
private void lookupAttr(Callable<Object> createValue, String attrName, boolean expectNoValue) {
101115
PythonObjectLibrary lib = PythonObjectLibrary.getFactory().getUncached();
102116
execInContext(() -> {
@@ -132,5 +146,4 @@ public void execInContext(Callable<Object> c) {
132146
});
133147
context.getPolyglotBindings().getMember("testSymbol").execute();
134148
}
135-
136149
}

graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_random.txt

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,49 @@
22
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_autoseed
33
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_bigrand
44
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_bigrand_ranges
5+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_bug_1727780
6+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_bug_27706
57
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_bug_31478
8+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_bug_31482
69
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_bug_9025
10+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_choice
11+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_choices
12+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_choices_algorithms
13+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_choices_subnormal
14+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_gauss
15+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_genrandbits
16+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_guaranteed_stable
17+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_long_seed
18+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_pickling
19+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_randbelow_logic
20+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_randbelow_without_getrandbits
21+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_randrange_bug_1590891
22+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_randrange_uses_getrandbits
23+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_rangelimits
24+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_referenceImplementation
25+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_sample
26+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_sample_distribution
27+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_sample_inputs
28+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_sample_on_dicts
29+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_saverestore
30+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_seed_when_randomness_source_not_found
31+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_seedargs
32+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_setstate_first_arg
33+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_setstate_middle_arg
34+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_shuffle
35+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_shuffle_random_argument
36+
*graalpython.lib-python.3.test.test_random.MersenneTwister_TestBasicOps.test_strong_reference_implementation
737
*graalpython.lib-python.3.test.test_random.SystemRandom_TestBasicOps.test_53_bits_per_float
838
*graalpython.lib-python.3.test.test_random.SystemRandom_TestBasicOps.test_autoseed
939
*graalpython.lib-python.3.test.test_random.SystemRandom_TestBasicOps.test_bigrand
1040
*graalpython.lib-python.3.test.test_random.SystemRandom_TestBasicOps.test_bigrand_ranges
41+
*graalpython.lib-python.3.test.test_random.SystemRandom_TestBasicOps.test_bug_1727780
1142
*graalpython.lib-python.3.test.test_random.SystemRandom_TestBasicOps.test_bug_9025
1243
*graalpython.lib-python.3.test.test_random.SystemRandom_TestBasicOps.test_choice
44+
*graalpython.lib-python.3.test.test_random.SystemRandom_TestBasicOps.test_choices
1345
*graalpython.lib-python.3.test.test_random.SystemRandom_TestBasicOps.test_choices_subnormal
1446
*graalpython.lib-python.3.test.test_random.SystemRandom_TestBasicOps.test_gauss
47+
*graalpython.lib-python.3.test.test_random.SystemRandom_TestBasicOps.test_genrandbits
1548
*graalpython.lib-python.3.test.test_random.SystemRandom_TestBasicOps.test_pickling
1649
*graalpython.lib-python.3.test.test_random.SystemRandom_TestBasicOps.test_randbelow_logic
1750
*graalpython.lib-python.3.test.test_random.SystemRandom_TestBasicOps.test_randrange_errors
@@ -24,4 +57,21 @@
2457
*graalpython.lib-python.3.test.test_random.SystemRandom_TestBasicOps.test_saverestore
2558
*graalpython.lib-python.3.test.test_random.SystemRandom_TestBasicOps.test_seed_when_randomness_source_not_found
2659
*graalpython.lib-python.3.test.test_random.SystemRandom_TestBasicOps.test_seedargs
60+
*graalpython.lib-python.3.test.test_random.SystemRandom_TestBasicOps.test_shuffle
2761
*graalpython.lib-python.3.test.test_random.SystemRandom_TestBasicOps.test_shuffle_random_argument
62+
*graalpython.lib-python.3.test.test_random.TestDistributions.test_avg_std
63+
*graalpython.lib-python.3.test.test_random.TestDistributions.test_betavariate_return_zero
64+
*graalpython.lib-python.3.test.test_random.TestDistributions.test_constant
65+
*graalpython.lib-python.3.test.test_random.TestDistributions.test_gammavariate_alpha_between_zero_and_one
66+
*graalpython.lib-python.3.test.test_random.TestDistributions.test_gammavariate_alpha_equal_one
67+
*graalpython.lib-python.3.test.test_random.TestDistributions.test_gammavariate_alpha_equal_one_equals_expovariate
68+
*graalpython.lib-python.3.test.test_random.TestDistributions.test_gammavariate_alpha_greater_one
69+
*graalpython.lib-python.3.test.test_random.TestDistributions.test_gammavariate_errors
70+
*graalpython.lib-python.3.test.test_random.TestDistributions.test_von_mises_large_kappa
71+
*graalpython.lib-python.3.test.test_random.TestDistributions.test_von_mises_range
72+
*graalpython.lib-python.3.test.test_random.TestDistributions.test_zeroinputs
73+
*graalpython.lib-python.3.test.test_random.TestModule.testMagicConstants
74+
*graalpython.lib-python.3.test.test_random.TestModule.test__all__
75+
*graalpython.lib-python.3.test.test_random.TestModule.test_after_fork
76+
*graalpython.lib-python.3.test.test_random.TestRandomSubclassing.test_random_subclass_with_kwargs
77+
*graalpython.lib-python.3.test.test_random.TestRandomSubclassing.test_subclasses_overriding_methods

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1717,6 +1717,11 @@ PBytes urandom(int size) {
17171717
secureRandom.nextBytes(bytes);
17181718
return factory().createBytes(bytes);
17191719
}
1720+
1721+
@Fallback
1722+
Object urandomError(Object size) {
1723+
throw raise(TypeError, ErrorMessages.ARG_EXPECTED_GOT, "integer", size);
1724+
}
17201725
}
17211726

17221727
@Builtin(name = "uname", minNumOfPositionalArgs = 0)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/RandomModuleBuiltins.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFa
4949
}
5050

5151
// _random.Random([seed])
52-
@Builtin(name = "Random", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, constructsClass = PythonBuiltinClassType.PRandom)
52+
@Builtin(name = "Random", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, constructsClass = PythonBuiltinClassType.PRandom, takesVarKeywordArgs = true)
5353
@GenerateNodeFactory
5454
abstract static class PRandomNode extends PythonBuiltinNode {
5555
@Child LookupAndCallBinaryNode setSeed = LookupAndCallBinaryNode.create("seed");

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ints/PInt.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,13 @@ public boolean canBeJavaLong() {
267267

268268
@ExportMessage
269269
public long asJavaLong(
270-
@Cached CastToJavaLongLossyNode castToLong) {
270+
@Cached @Shared("asJavaLong") CastToJavaLongLossyNode castToLong) {
271+
return castToLong.execute(this);
272+
}
273+
274+
@ExportMessage
275+
public long asJavaLongWithState(@SuppressWarnings("unused") ThreadState threadState,
276+
@Cached @Shared("asJavaLong") CastToJavaLongLossyNode castToLong) {
271277
return castToLong.execute(this);
272278
}
273279

Lines changed: 124 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,151 @@
1-
/*
2-
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
3-
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4-
*
5-
* The Universal Permissive License (UPL), Version 1.0
6-
*
7-
* Subject to the condition set forth below, permission is hereby granted to any
8-
* person obtaining a copy of this software, associated documentation and/or
9-
* data (collectively the "Software"), free of charge and under any and all
10-
* copyright rights in the Software, and any and all patent rights owned or
11-
* freely licensable by each licensor hereunder covering either (i) the
12-
* unmodified Software as contributed to or provided by such licensor, or (ii)
13-
* the Larger Works (as defined below), to deal in both
14-
*
15-
* (a) the Software, and
16-
*
17-
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18-
* one is included with the Software each a "Larger Work" to which the Software
19-
* is contributed by such licensors),
20-
*
21-
* without restriction, including without limitation the rights to copy, create
22-
* derivative works of, display, perform, and distribute the Software and make,
23-
* use, sell, offer for sale, import, export, have made, and have sold the
24-
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25-
* either these or other terms.
26-
*
27-
* This license is subject to the following condition:
28-
*
29-
* The above copyright notice and either this complete permission notice or at a
30-
* minimum a reference to the UPL must be included in all copies or substantial
31-
* portions of the Software.
1+
/* Copyright (c) 2020, Oracle and/or its affiliates.
2+
* Copyright (C) 1996-2020 Python Software Foundation
323
*
33-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39-
* SOFTWARE.
4+
* Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
405
*/
41-
package com.oracle.graal.python.builtins.objects.random;
6+
/*
7+
The Mersenne Twister implementation was based on:
8+
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html
9+
which included these comments:
10+
11+
A C-program for MT19937, with initialization improved 2002/1/26.
12+
Coded by Takuji Nishimura and Makoto Matsumoto.
13+
14+
Before using, initialize the state by using init_genrand(seed)
15+
or init_by_array(init_key, key_length).
16+
17+
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
18+
All rights reserved.
19+
20+
Redistribution and use in source and binary forms, with or without
21+
modification, are permitted provided that the following conditions
22+
are met:
23+
24+
1. Redistributions of source code must retain the above copyright
25+
notice, this list of conditions and the following disclaimer.
4226
43-
import java.util.Random;
27+
2. Redistributions in binary form must reproduce the above copyright
28+
notice, this list of conditions and the following disclaimer in the
29+
documentation and/or other materials provided with the distribution.
30+
31+
3. The names of its contributors may not be used to endorse or promote
32+
products derived from this software without specific prior written
33+
permission.
34+
35+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
39+
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
40+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
41+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
42+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
43+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
44+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
45+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46+
47+
48+
Any feedback is very welcome.
49+
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
50+
email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
51+
*/
52+
package com.oracle.graal.python.builtins.objects.random;
4453

4554
import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject;
46-
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
4755
import com.oracle.truffle.api.object.Shape;
4856

4957
public class PRandom extends PythonBuiltinObject {
50-
private static class PythonRandom extends Random {
51-
private static final long serialVersionUID = 1L;
5258

53-
long getSeed() {
54-
int nextseed = this.next(48); // 48 magic number of bits shifted away in superclass
55-
this.setSeed(nextseed);
56-
return nextseed;
57-
}
58-
}
59+
public static final int N = 624;
60+
private static final int M = 397;
61+
private static final int UPPER_MASK = 0x80000000;
62+
private static final int LOWER_MASK = 0x7fffffff;
63+
private static final int[] MAG01 = {0x0, 0x9908b0df};
5964

60-
private PythonRandom javaRandom;
65+
private int[] state = new int[N];
66+
private int index;
6167

6268
public PRandom(Object cls, Shape instanceShape) {
6369
super(cls, instanceShape);
64-
resetJavaRandom();
6570
}
6671

67-
@TruffleBoundary
68-
public void setSeed(long seed) {
69-
javaRandom.setSeed(seed);
72+
void seed(int[] seed) {
73+
int[] mt = state;
74+
mt[0] = 19650218;
75+
for (int mti = 1; mti < N; mti++) {
76+
mt[mti] = (1812433253 * (mt[mti - 1] ^ (mt[mti - 1] >>> 30)) + mti);
77+
}
78+
index = N;
79+
80+
int i = 1;
81+
int j = 0;
82+
int keyLength = seed.length;
83+
for (int k = N > keyLength ? N : keyLength; k != 0; k--) {
84+
mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >>> 30)) * 1664525)) + seed[j] + j;
85+
i++;
86+
j++;
87+
if (i >= N) {
88+
mt[0] = mt[N - 1];
89+
i = 1;
90+
}
91+
if (j >= keyLength) {
92+
j = 0;
93+
}
94+
}
95+
for (int k = N - 1; k != 0; k--) {
96+
mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >>> 30)) * 1566083941)) - i;
97+
i++;
98+
if (i >= N) {
99+
mt[0] = mt[N - 1];
100+
i = 1;
101+
}
102+
}
103+
mt[0] = 0x80000000;
70104
}
71105

72-
@TruffleBoundary
73-
public long getSeed() {
74-
return javaRandom.getSeed();
106+
int nextInt() {
107+
int[] mt = state;
108+
if (index >= N) {
109+
int kk;
110+
for (kk = 0; kk < N - M; kk++) {
111+
int y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
112+
mt[kk] = mt[kk + M] ^ (y >>> 1) ^ MAG01[y & 0x1];
113+
}
114+
for (; kk < N - 1; kk++) {
115+
int y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
116+
mt[kk] = mt[kk + (M - N)] ^ (y >>> 1) ^ MAG01[y & 0x1];
117+
}
118+
int y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
119+
mt[N - 1] = mt[M - 1] ^ (y >>> 1) ^ MAG01[y & 0x1];
120+
121+
index = 0;
122+
}
123+
124+
int y = mt[index++];
125+
y ^= (y >>> 11);
126+
y ^= (y << 7) & 0x9d2c5680;
127+
y ^= (y << 15) & 0xefc60000;
128+
y ^= (y >>> 18);
129+
return y;
75130
}
76131

77-
public long nextLong() {
78-
return javaRandom.nextLong();
132+
double nextDouble() {
133+
int a = nextInt() >>> 5, b = nextInt() >>> 6;
134+
return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0);
79135
}
80136

81-
public double nextDouble() {
82-
return javaRandom.nextDouble();
137+
int[] getState() {
138+
return state;
83139
}
84140

85-
public Random getJavaRandom() {
86-
return javaRandom;
141+
int getIndex() {
142+
return index;
87143
}
88144

89-
@TruffleBoundary
90-
public void resetJavaRandom() {
91-
javaRandom = new PythonRandom();
145+
void restore(int[] new_state, int new_index) {
146+
assert new_state.length == N;
147+
assert new_index >= 0 && new_index <= N;
148+
state = new_state;
149+
index = new_index;
92150
}
93151
}

0 commit comments

Comments
 (0)