libhatchet
Loading...
Searching...
No Matches
hxrandom.hpp
Go to the documentation of this file.
1#pragma once
2// SPDX-FileCopyrightText: © 2017-2026 Adrian Johnston.
3// SPDX-License-Identifier: MIT
4// This file is licensed under the MIT license found in the LICENSE.md file.
5
8
9#include "libhatchet.h"
10
11// HX_USE_MACROS_WITH_MODULE allows including macros alongside the module.
12#if HX_USE_MACROS_WITH_MODULE
13#error Header does not provide macros alone.
14#endif
15
16HX_NS_BEGIN_
17
25class hxrandom {
26public:
29 hxinline hxconstexpr hxrandom(uint64_t stream_ = 31u) : m_state_(stream_) { }
30
33 uint32_t operator()(void) { return this->u32(); }
34
41 template<typename T_>
43 T_ range(T_ base_, T_ size_) {
44 // Use double parameters if you need a bigger size. An emulated
45 // floating point multiply is faster and more stable than integer modulo.
46 hxassertf(static_cast<float>(size_) < float{0x01000000u},
47 "low_precision %f", static_cast<float>(size_)); // 0x1p24f
48 return base_ + static_cast<T_>(static_cast<float>(size_) * this->f01());
49 }
50
53 double range(double base_, double size_) {
54 // Use `uint64_t` parameters if you need a bigger size. An emulated
55 // floating point multiply is faster and more stable than integer modulo.
56 hxassertf(size_ < double{0x20000000000000ll}, "low_precision %f", size_); // 0x1p53
57 return base_ + size_ * this->d01();
58 }
59
62 int64_t range(int64_t base_, int64_t size_) {
63 hxassertf(size_ > 0, "bad_range %zd", static_cast<hxsize_t>(size_));
64 return base_ + static_cast<int64_t>(this->u64() % static_cast<uint64_t>(size_));
65 }
66
69 uint64_t range(uint64_t base_, uint64_t size_) {
70 hxassertf(size_ != 0u, "bad_range");
71 return base_ + this->u64() % size_;
72 }
73
77 hxinline void read(void* bytes_, hxsize_t count_) hxattr_nonnull(2) {
78 uint8_t* chars_ = static_cast<uint8_t*>(bytes_);
79 while (count_ >= 4) {
80 const uint32_t x_ = this->u32();
81 ::memcpy(chars_, &x_, 4u);
82 chars_ += 4;
83 count_ -= 4;
84 }
85 if (count_ > 0) {
86 const uint32_t x_ = this->u32();
87 ::memcpy(chars_, &x_, static_cast<size_t>(count_));
88 }
89 }
90
93 uint8_t u8(void) {
94 return static_cast<uint8_t>(this->u32());
95 }
96
99 uint16_t u16(void) {
100 return static_cast<uint16_t>(this->u32());
101 }
102
105 uint32_t u32(void) {
106 m_state_ = uint64_t{0x5851f42d4c957f2dull} * m_state_ + uint64_t{0x14057b7ef767814full};
107
108 // MODIFICATION: Use the 4 msb bits as a random 0..15 bit variable shift
109 // control. Ignores the low 13 bits because they are low quality.
110 // Returns 32 bits chosen at a random offset starting between the 13th
111 // and 28th bits. 4 bits shift control + 32 returned + up to 15 shifted
112 // off + 13 always discarded = 64 bits.
113 const uint32_t result_ = static_cast<uint32_t>(m_state_ >> ((m_state_ >> 60) + 13u));
114 return result_;
115 }
116
119 uint64_t u64(void) {
120 const uint64_t result_ = this->u32() | (static_cast<uint64_t>(this->u32()) << 32);
121 return result_;
122 }
123
127 float f01(void) {
128 // Shift avoids rounding up.
129 return static_cast<float>(this->u32() >> 8) * (1.0f / 16777216.0f); // 0x1p-24f
130 }
131
135 double d01(void) {
136 // Shift avoids rounding up.
137 return static_cast<double>(this->u64() >> 11) * (1.0 / 9007199254740992.0); // 0x1p-53
138 }
139
140private:
141 uint64_t m_state_;
142};
143
144HX_NS_END_
constexpr uint32_t operator()(void)
Returns [0..2^32).
Definition hxrandom.hpp:33
constexpr uint64_t range(uint64_t base_, uint64_t size_)
uint64_t version. Zero size is undefined.
Definition hxrandom.hpp:69
constexpr double d01(void)
Returns a double between [0..1).
Definition hxrandom.hpp:135
constexpr uint8_t u8(void)
Returns [0..2^8).
Definition hxrandom.hpp:93
constexpr uint64_t u64(void)
Returns [0..2^64).
Definition hxrandom.hpp:119
constexpr double range(double base_, double size_)
double version.
Definition hxrandom.hpp:53
constexpr uint16_t u16(void)
Returns [0..2^16).
Definition hxrandom.hpp:99
constexpr T range(T base_, T size_)
Returns a random number in the range [base..base+range).
Definition hxrandom.hpp:43
void read(void *bytes_, hxsize_t count_)
Reads a specified number of random bytes into the provided buffer.
Definition hxrandom.hpp:77
constexpr uint32_t u32(void)
Returns [0..2^32).
Definition hxrandom.hpp:105
constexpr float f01(void)
Returns a float between [0..1).
Definition hxrandom.hpp:127
constexpr int64_t range(int64_t base_, int64_t size_)
int64_t version. Negative or zero size is undefined.
Definition hxrandom.hpp:62
constexpr hxrandom(uint64_t stream_=31u)
Constructor to initialize the random number generator.
Definition hxrandom.hpp:29
#define hxinline
hxinline - Force a function to be inlined into its callers.
Definition hxsettings.h:125
#define hxattr_nonnull(...)
hxattr_nonnull - Indicates that a function has args that should not be null.
Definition hxsettings.h:106
#define hxattr_nodiscard
hxattr_nodiscard - Indicates the caller should not discard the return value.
Definition hxsettings.h:98
#define hxconstexpr
hxconstexpr - Enables C++23 compatable constexpr usage for functions as that has support for destruct...
Definition hxsettings.h:266
Provides core macros, memory management and feature detection.
#define hxassertf(x_,...)
hxassertf(bool x, ...) - Logs an error and terminates execution if x is false.
Definition libhatchet.h:101
ptrdiff_t hxsize_t
hxsize_t - A signed size type, same as ssize_t or ptrdiff_t.
Definition libhatchet.h:207