1313177Sgnn/*- 2313177Sgnn * Copyright (c) 2016 (Graeme Jenkinson) 3313177Sgnn * All rights reserved. 4313177Sgnn * 5313177Sgnn * This software was developed by BAE Systems, the University of Cambridge 6313177Sgnn * Computer Laboratory, and Memorial University under DARPA/AFRL contract 7313177Sgnn * FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent Computing 8313177Sgnn * (TC) research program. 9313177Sgnn * 10313177Sgnn * Redistribution and use in source and binary forms, with or without 11313177Sgnn * modification, are permitted provided that the following conditions 12313177Sgnn * are met: 13313177Sgnn * 1. Redistributions of source code must retain the above copyright 14313177Sgnn * notice, this list of conditions and the following disclaimer. 15313177Sgnn * 2. Redistributions in binary form must reproduce the above copyright 16313177Sgnn * notice, this list of conditions and the following disclaimer in the 17313177Sgnn * documentation and/or other materials provided with the distribution. 18313177Sgnn * 19313177Sgnn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20313177Sgnn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21313177Sgnn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22313177Sgnn * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23313177Sgnn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24313177Sgnn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25313177Sgnn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26313177Sgnn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27313177Sgnn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28313177Sgnn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29313177Sgnn * SUCH DAMAGE. 30313177Sgnn * 31313177Sgnn */ 32313177Sgnn 33313177Sgnn#include <sys/types.h> 34313177Sgnn 35313177Sgnn#include "dtrace_xoroshiro128_plus.h" 36313177Sgnn 37313177Sgnnstatic __inline uint64_t 38313177Sgnnrotl(const uint64_t x, int k) 39313177Sgnn{ 40313177Sgnn return (x << k) | (x >> (64 - k)); 41313177Sgnn} 42313177Sgnn 43313177Sgnn/* 44313177Sgnn * This is the jump function for the generator. It is equivalent to 2^64 calls 45313177Sgnn * to next(); it can be used to generate 2^64 non-overlapping subsequences for 46313177Sgnn * parallel computations. 47313177Sgnn */ 48313177Sgnnvoid 49313177Sgnndtrace_xoroshiro128_plus_jump(uint64_t * const state, 50313177Sgnn uint64_t * const jump_state) 51313177Sgnn{ 52313177Sgnn static const uint64_t JUMP[] = { 0xbeac0467eba5facb, 53313177Sgnn 0xd86b048b86aa9922 }; 54313177Sgnn 55313177Sgnn uint64_t s0 = 0; 56313177Sgnn uint64_t s1 = 0; 57313177Sgnn int i = 0; 58313177Sgnn int b = 0; 59313177Sgnn for (i = 0; i < sizeof JUMP / sizeof *JUMP; i++) { 60313177Sgnn for (b = 0; b < 64; b++) { 61313177Sgnn if (JUMP[i] & 1ULL << b) { 62313177Sgnn s0 ^= state[0]; 63313177Sgnn s1 ^= state[1]; 64313177Sgnn } 65313177Sgnn dtrace_xoroshiro128_plus_next(state); 66313177Sgnn } 67313177Sgnn } 68313177Sgnn jump_state[0] = s0; 69313177Sgnn jump_state[1] = s1; 70313177Sgnn} 71313177Sgnn 72313177Sgnn/* 73313177Sgnn * xoroshiro128+ - XOR/rotate/shift/rotate 74313177Sgnn * xorshift.di.unimi.it 75313177Sgnn */ 76313177Sgnnuint64_t 77313177Sgnndtrace_xoroshiro128_plus_next(uint64_t * const state) 78313177Sgnn{ 79313177Sgnn const uint64_t s0 = state[0]; 80313177Sgnn uint64_t s1 = state[1]; 81313177Sgnn uint64_t result; 82313177Sgnn result = s0 + s1; 83313177Sgnn 84313177Sgnn s1 ^= s0; 85313177Sgnn state[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); 86313177Sgnn state[1] = rotl(s1, 36); 87313177Sgnn 88313177Sgnn return result; 89313177Sgnn} 90