herald  2.0.0
randomness.h
1 // Copyright 2020-2021 Herald Project Contributors
2 // SPDX-License-Identifier: Apache-2.0
3 //
4 
5 #ifndef HERALD_RANDOMNESS_H
6 #define HERALD_RANDOMNESS_H
7 
8 #include "data.h"
9 
10 #include <string>
11 #include <random>
12 #include <climits>
13 
14 namespace herald {
15 namespace datatype {
16 
26 // class RandomnessSource {
27 // public:
28 // RandomnessSource() = default;
29 // virtual ~RandomnessSource() = default;
30 
31 // virtual std::string methodName() const = 0;
32 
33 // virtual void nextBytes(std::size_t count, Data& into) = 0;
34 // virtual int nextInt() = 0;
35 // virtual double nextDouble() = 0;
36 
37 // };
38 
44 public:
45  AllZerosNotRandom() = default;
46  AllZerosNotRandom(AllZerosNotRandom&& other) noexcept = default;
47  ~AllZerosNotRandom() = default;
48 
49  std::string methodName() const {
50  return "allzeros";
51  }
52 
53  void nextBytes(std::size_t count, Data& into) {
54  for (std::size_t i = 0;i < count;i++) {
55  into.append(std::byte(0));
56  }
57  }
58 
59  int nextInt() {
60  return 0;
61  }
62 
63  double nextDouble() {
64  return 0.0;
65  }
66 };
67 
69 public:
71  : rd(), gen(rd()), distrib(LONG_MIN,LONG_MAX)
72  {
73  ;
74  }
75 
77  : rd(), // Doesn't have a move or copy constructor
78  gen(rd()),
79  distrib(other.distrib)
80  {
81  ;
82  }
83 
84  ~IntegerDistributedRandomSource() = default;
85 
86  std::string methodName() const {
87  return "integerdistributed";
88  }
89 
90  void nextBytes(std::size_t count, Data& into) {
91  for (std::size_t i = 0;i < count;i++) {
92  into.append(std::byte(distrib(gen)));
93  }
94  }
95 
96  int nextInt() {
97  return (int)distrib(gen);
98  }
99 
100  double nextDouble() {
101  return (double)distrib(gen);
102  }
103 
104 private:
105  std::random_device rd; // Will be used to obtain a seed for the random number engine
106  std::mt19937 gen; // Standard mersenne_twister_engine seeded with rd()
107  std::uniform_int_distribution<int64_t> distrib;
108 };
109 
125 template <typename RandomnessSourceT>
127 public:
128  RandomnessGenerator(RandomnessSourceT&& toOwn)
129  : m_source(std::move(toOwn)),
130  m_entropy(0)
131  {
132  ;
133  }
134 
135  ~RandomnessGenerator() = default;
136 
137  template <typename T>
138  void addEntropy(T entropy) {
139  // Get size of amount of entropy we have
140  constexpr std::size_t size = sizeof(T);
141  // TODO consider whether there's benefit to detecting most significant set bits.
142  // This may provide a benefit if the method of combination isn't XOR.
143 
144  // See if we are at multiples of std::size_t
145  constexpr std::size_t multiple = sizeof(std::size_t) / size; // integer division, rounds down
146  // Note the above cannot ever be 0 because std::size_t is always the largest size on a given architecture
147 
148  std::size_t toXor = 0;
149  for (std::size_t i = 0;i < multiple;i++) {
150  if (0 != i) {
151  toXor << size;
152  }
153  toXor += entropy;
154  }
155 
156  // XOR will ensure the same distribution of 0 and 1 over multiple applications
157  m_entropy = m_entropy ^ toXor;
158  }
159 
160 
161  std::string methodName() const {
162  return m_source.methodName();
163  }
164 
165  void nextBytes(std::size_t count, Data& into) {
166  constexpr std::size_t byteSize = sizeof(std::byte);
167  constexpr std::size_t sizeTSize = sizeof(std::size_t);
168  constexpr std::size_t shifts = sizeTSize / byteSize;
169  Data sourcedInto;
170  m_source.nextBytes(count,sourcedInto);
171 
172  // now add in entropy
173  for (std::size_t byteIndex = 0;byteIndex < count;byteIndex++) {
174  into.append((std::byte)(
175  std::size_t(sourcedInto.at(byteIndex))
176  ^
177  (m_entropy >> 8 * (byteIndex % shifts))
178  ));
179  }
180  }
181 
182  int nextInt() {
183  return (int)(m_source.nextInt() ^ m_entropy);
184  }
185 
186  double nextDouble() {
187  return (double)(((std::size_t)m_source.nextDouble()) ^ m_entropy);
188  }
189 
190 private:
191  RandomnessSourceT m_source;
192  std::size_t m_entropy;
193 };
194 
195 } // end namespace
196 } // end namespace
197 
198 #endif
Definition: randomness.h:43
The main data workhorse class of the Herald API.
Definition: data.h:33
std::byte at(std::size_t index) const
Returns the individual byte at index position, or a byte value of zero if index is out of bounds.
Definition: data.h:178
void append(const DataRef &rawData, std::size_t offset, std::size_t length)
Copies another DataRef into this instance, expanding if required.
Definition: data.h:201
Definition: randomness.h:126
Acts as a non-global memory arena for arbitrary classes.
Definition: aggregates.h:15