|
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 |
32 | 3 | *
|
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 |
40 | 5 | */
|
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. |
42 | 26 |
|
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; |
44 | 53 |
|
45 | 54 | import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject;
|
46 |
| -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; |
47 | 55 | import com.oracle.truffle.api.object.Shape;
|
48 | 56 |
|
49 | 57 | public class PRandom extends PythonBuiltinObject {
|
50 |
| - private static class PythonRandom extends Random { |
51 |
| - private static final long serialVersionUID = 1L; |
52 | 58 |
|
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}; |
59 | 64 |
|
60 |
| - private PythonRandom javaRandom; |
| 65 | + private int[] state = new int[N]; |
| 66 | + private int index; |
61 | 67 |
|
62 | 68 | public PRandom(Object cls, Shape instanceShape) {
|
63 | 69 | super(cls, instanceShape);
|
64 |
| - resetJavaRandom(); |
65 | 70 | }
|
66 | 71 |
|
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; |
70 | 104 | }
|
71 | 105 |
|
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; |
75 | 130 | }
|
76 | 131 |
|
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); |
79 | 135 | }
|
80 | 136 |
|
81 |
| - public double nextDouble() { |
82 |
| - return javaRandom.nextDouble(); |
| 137 | + int[] getState() { |
| 138 | + return state; |
83 | 139 | }
|
84 | 140 |
|
85 |
| - public Random getJavaRandom() { |
86 |
| - return javaRandom; |
| 141 | + int getIndex() { |
| 142 | + return index; |
87 | 143 | }
|
88 | 144 |
|
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; |
92 | 150 | }
|
93 | 151 | }
|
0 commit comments