C/C++ API Reference
Loading...
Searching...
No Matches
xor_shift.h
1// Copyright 2020 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14#pragma once
15
16#include <algorithm>
17#include <cstdint>
18#include <cstring>
19
20#include "pw_assert/check.h"
21#include "pw_bytes/span.h"
22#include "pw_random/random.h"
23#include "pw_span/span.h"
24#include "pw_status/status_with_size.h"
25
26namespace pw::random {
27
29
52 public:
53 XorShiftStarRng64(uint64_t initial_seed) : state_(initial_seed) {}
54
59 void Get(ByteSpan dest) final {
60 while (!dest.empty()) {
61 uint64_t random = Regenerate();
62 size_t copy_size = std::min(dest.size_bytes(), sizeof(state_));
63 std::memcpy(dest.data(), &random, copy_size);
64 dest = dest.subspan(copy_size);
65 }
66 }
67
73 void InjectEntropyBits(uint32_t data, uint_fast8_t num_bits) final {
74 if (num_bits == 0) {
75 return;
76 } else if (num_bits > 32) {
77 num_bits = 32;
78 }
79
80 // Rotate state.
81 uint64_t untouched_state = state_ >> (kNumStateBits - num_bits);
82 state_ = untouched_state | (state_ << num_bits);
83 // Zero-out all irrelevant bits, then XOR entropy into state.
84 uint32_t mask =
85 static_cast<uint32_t>((static_cast<uint64_t>(1) << num_bits) - 1);
86 state_ ^= (data & mask);
87 }
88
89 private:
90 // Calculate and return the next value based on the "xorshift*" algorithm
91 uint64_t Regenerate() {
92 // State must be nonzero, or the algorithm will get stuck and always return
93 // zero.
94 if (state_ == 0) {
95 state_--;
96 }
97 state_ ^= state_ >> 12;
98 state_ ^= state_ << 25;
99 state_ ^= state_ >> 27;
100 return state_ * kMultConst;
101 }
102 uint64_t state_;
103 static constexpr uint8_t kNumStateBits = sizeof(state_) * 8;
104
105 // For information on why this constant was selected, see:
106 // https://www.jstatsoft.org/article/view/v008i14
107 // http://vigna.di.unimi.it/ftp/papers/xorshift.pdf
108 static constexpr uint64_t kMultConst = 0x2545F4914F6CDD1D;
109};
110
111} // namespace pw::random
Definition: random.h:36
Definition: xor_shift.h:51
void InjectEntropyBits(uint32_t data, uint_fast8_t num_bits) final
Definition: xor_shift.h:73
void Get(ByteSpan dest) final
Definition: xor_shift.h:59