Xorshift32をRustで実装してみる
Xorshift32をRustで実装してみる
今回は、Rustで色々コード書いてみる一環として、疑似乱数生成法の1つであるXorshiftを実装してみたいと思います。
実装してみるのは32bitのXorshift(下のページのxorshift32)です。
https://ja.wikipedia.org/wiki/Xorshift
まずはC言語でこのコードを動かし、得られた数値を基にRustでテストを書きます。
#include <stdio.h> #include <stdint.h> struct xorshift32_state { uint32_t a; }; uint32_t xorshift32(struct xorshift32_state *state) { uint32_t x = state->a; x ^= x << 13; x ^= x >> 17; x ^= x << 5; return state->a = x; } void main() { struct xorshift32_state st = {1}; for (int i = 0; i < 10; i++) { printf("%u\n", xorshift32(&st)); } }
このコードを実行して得られる出力は以下の通りです。
270369 67634689 2647435461 307599695 2398689233 745495504 632435482 435756210 2005365029 2916098932
これで、xorshiftを実装した時の正しい値が分かりました。
では次にRustで実装を行います。
まずテストの部分です。
#[cfg(test)] mod tests { use super::*; #[test] fn test_xorshift32() { let mut rng = Xorshift32::new(1); let expected: [u32; 5] = [270369, 67634689, 2647435461, 307599695, 2398689233]; for e in expected.iter() { assert_eq!(e, &rng.next()); } } }
10個出力しましたが、まぁ5個も確認して合っていれば十分かな、ということで先頭から5個の値をテストします。
では実際のXorshiftの実装をしていきます。以下のような感じで書きました。
pub struct Xorshift32 { state: u32, } impl Xorshift32 { pub fn new(seed: u32) -> Xorshift32 { Xorshift32 { state: seed } } pub fn next(&mut self) -> u32 { let mut x: u32 = self.state; x ^= x << 13; x ^= x >> 17; x ^= x << 5; self.state = x; self.state } }
特に移植で難しい部分もなく書き移せました。では最後にcargo test
で確認します。
running 1 test test tests::test_xorshift32 ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s
無事テストが通ったということで、XorshiftをRustで実装することができました。
めでたしめでたし、ということで今回はここまでです。