alpaka
Abstraction Library for Parallel Kernel Acceleration
Loading...
Searching...
No Matches
PhiloxStateless.hpp
Go to the documentation of this file.
1/* Copyright 2022 Jiri Vyskocil, Bernhard Manfred Gruber, Jeffrey Kelling
2 * SPDX-License-Identifier: MPL-2.0
3 */
4
5#pragma once
6
10#include "alpaka/vec/Vec.hpp"
11
12#include <utility>
13
15{
16 /** Philox algorithm parameters
17 *
18 * @tparam TCounterSize number of elements in the counter
19 * @tparam TWidth width of one counter element (in bits)
20 * @tparam TRounds number of S-box rounds
21 */
22 template<unsigned TCounterSize, unsigned TWidth, unsigned TRounds>
24 {
25 static constexpr unsigned counterSize = TCounterSize;
26 static constexpr unsigned width = TWidth;
27 static constexpr unsigned rounds = TRounds;
28 };
29
30 /** Class basic Philox family counter-based PRNG
31 *
32 * Checks the validity of passed-in parameters and calls the backend methods to perform N rounds of the
33 * Philox shuffle.
34 *
35 * @tparam TParams Philox algorithm parameters \sa PhiloxParams
36 */
37 template<typename TParams>
38 class PhiloxStateless : public PhiloxConstants<TParams>
39 {
40 static constexpr unsigned numRounds()
41 {
42 return TParams::rounds;
43 }
44
45 static constexpr unsigned vectorSize()
46 {
47 return TParams::counterSize;
48 }
49
50 static constexpr unsigned numberWidth()
51 {
52 return TParams::width;
53 }
54
55 static_assert(numRounds() > 0, "Number of Philox rounds must be > 0.");
56 static_assert(vectorSize() % 2 == 0, "Philox counter size must be an even number.");
57 static_assert(vectorSize() <= 16, "Philox SP network is not specified for sizes > 16.");
58 static_assert(numberWidth() % 8 == 0, "Philox number width in bits must be a multiple of 8.");
59
60 static_assert(numberWidth() == 32, "Philox implemented only for 32 bit numbers.");
61
62 public:
64 using Key = alpaka::Vec<alpaka::DimInt<TParams::counterSize / 2>, std::uint32_t>;
66
67 protected:
68 /** Single round of the Philox shuffle
69 *
70 * @param counter state of the counter
71 * @param key value of the key
72 * @return shuffled counter
73 */
74 static ALPAKA_FN_HOST_ACC auto singleRound(Counter const& counter, Key const& key)
75 {
76 std::uint32_t H0, L0, H1, L1;
79 return Counter{H1 ^ counter[1] ^ key[0], L1, H0 ^ counter[3] ^ key[1], L0};
80 }
81
82 /** Bump the \a key by the Weyl sequence step parameter
83 *
84 * @param key the key to be bumped
85 * @return the bumped key
86 */
87 static ALPAKA_FN_HOST_ACC auto bumpKey(Key const& key)
88 {
89 return Key{key[0] + Constants::WEYL_32_0(), key[1] + Constants::WEYL_32_1()};
90 }
91
92 /** Performs N rounds of the Philox shuffle
93 *
94 * @param counter_in initial state of the counter
95 * @param key_in initial state of the key
96 * @return result of the PRNG shuffle; has the same size as the counter
97 */
98 static ALPAKA_FN_HOST_ACC auto nRounds(Counter const& counter_in, Key const& key_in) -> Counter
99 {
100 Key key{key_in};
101 Counter counter = singleRound(counter_in, key);
102
103 ALPAKA_UNROLL(numRounds())
104 for(unsigned int n = 0; n < numRounds(); ++n)
105 {
106 key = bumpKey(key);
107 counter = singleRound(counter, key);
108 }
109
110 return counter;
111 }
112
113 public:
114 /** Generates a random number (\p TCounterSize x32-bit)
115 *
116 * @param counter initial state of the counter
117 * @param key initial state of the key
118 * @return result of the PRNG shuffle; has the same size as the counter
119 */
120 static ALPAKA_FN_HOST_ACC auto generate(Counter const& counter, Key const& key) -> Counter
121 {
122 return nRounds(counter, key);
123 }
124 };
125} // namespace alpaka::rand::engine
#define ALPAKA_UNROLL(...)
Suggests unrolling of the directly following loop to the compiler.
Definition Unroll.hpp:24
A n-dimensional vector.
Definition Vec.hpp:38
static constexpr std::uint32_t WEYL_32_0()
1st Weyl sequence parameter, 32 bits
static constexpr std::uint32_t MULTIPLITER_4x32_1()
Second Philox S-box multiplier.
static constexpr std::uint32_t WEYL_32_1()
2nd Weyl sequence parameter, 32 bits
static constexpr std::uint32_t MULTIPLITER_4x32_0()
First Philox S-box multiplier.
static ALPAKA_FN_HOST_ACC auto generate(Counter const &counter, Key const &key) -> Counter
static ALPAKA_FN_HOST_ACC auto nRounds(Counter const &counter_in, Key const &key_in) -> Counter
static ALPAKA_FN_HOST_ACC auto bumpKey(Key const &key)
static ALPAKA_FN_HOST_ACC auto singleRound(Counter const &counter, Key const &key)
#define ALPAKA_FN_HOST_ACC
Definition Common.hpp:39
The random number generator engine specifics.
ALPAKA_FN_HOST_ACC constexpr void multiplyAndSplit64to32(std::uint64_t const a, std::uint64_t const b, std::uint32_t &resultHigh, std::uint32_t &resultLow)
std::integral_constant< std::size_t, N > DimInt
static constexpr unsigned counterSize
static constexpr unsigned rounds
static constexpr unsigned width