1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#[cfg(test)]
mod tests {
use java_random::{Random, JAVA_LCG};
use crate::get_next_long;
#[test]
fn it_works() {
let mut r =Random::with_seed(123);
let value=r.next_long();
let res=get_next_long((value & 0xffff_ffff_ffff) as u64);
println!("{:?}", res);
assert!(res.contains(&(123^JAVA_LCG.multiplier as u64)));
}
#[test]
fn it_works_batch() {
for i in 0..1000000 {
let random_value:u64= ((Random::with_seed(i).next_long()) & 0xffff_ffff_ffff) as u64;
let mut r =Random::with_seed(random_value);
let value=r.next_long();
let res=get_next_long((value & 0xffff_ffff_ffff) as u64);
assert!(res.contains(&((random_value)^JAVA_LCG.multiplier as u64)),"Failed for {}",random_value);
}
}
}
fn floor_div(x: i64, y: i64) -> i64 {
let mut r = x / y;
if (x ^ y) < 0 && (r * y != x) {
r-=1;
}
return r;
}
pub fn get_next_long(mut structure_seed: u64) -> Vec<u64> {
let mut res: Vec<u64> = Vec::with_capacity(2);
structure_seed = structure_seed & 0xffff_ffff_ffff;
let lower_bits: i64 = (structure_seed & 0xffff_ffff) as i64;
let mut upper_bits: i64 = ((structure_seed as u64) >> 32) as i64;
if (lower_bits & 0x8000_0000) != 0 {
upper_bits += 1;
}
let bits_of_danger = 1;
let low_min:i64 = (lower_bits << 16 - bits_of_danger) as i64;
let low_max:i64 = (((lower_bits + 1) << 16 - bits_of_danger) - 1) as i64;
let upper_min:i64 = (((upper_bits << 16).wrapping_sub(107048004364969)) >> bits_of_danger) as i64;
let m1lv = floor_div(low_max.wrapping_mul(-33441i64).wrapping_add( upper_min.wrapping_mul(17549i64)) , 1i64 << 31 - bits_of_danger) + 1;
let m2lv = floor_div(low_min.wrapping_mul(46603i64).wrapping_add( upper_min.wrapping_mul( 39761i64)) , 1i64 << 32 - bits_of_danger) + 1;
for i in 0..2 {
for j in 0..2 {
let seed = (-39761i64.wrapping_mul(m1lv.wrapping_add(i))).wrapping_add( 35098i64.wrapping_mul(m2lv.wrapping_add(j)));
if ((46603i64.wrapping_mul(m1lv.wrapping_add(i))).wrapping_add( 66882i64.wrapping_mul(m2lv.wrapping_add(j))).wrapping_add(107048004364969i64) >> 16) == upper_bits as i64 {
if (seed as u64) >> 16 == lower_bits as u64 {
res.push((( seed.wrapping_mul(254681119335897).wrapping_add(120305458776662)) & 0xffff_ffff_ffff) as u64)
}
}
}
}
return res;
}