This commit is contained in:
74
include/utils/arc.hpp
Normal file
74
include/utils/arc.hpp
Normal file
@@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
|
||||
namespace kuiper
|
||||
{
|
||||
|
||||
/// Atomically reference counted type
|
||||
template<typename T>
|
||||
class arc {
|
||||
public:
|
||||
/// Argument-forwarding constructor
|
||||
template<typename... Args>
|
||||
explicit arc(Args&&... args)
|
||||
: m_inner(std::forward<Args>(args)...) {}
|
||||
|
||||
/// Default constructor (no args.)
|
||||
arc()
|
||||
: m_inner() {}
|
||||
|
||||
/// Destructor
|
||||
~arc() {
|
||||
if (m_ref_count.load() > 0)
|
||||
return;
|
||||
}
|
||||
|
||||
/// Copy constructor
|
||||
arc(const arc& other)
|
||||
: m_inner(other.m_inner), m_ref_count(other.m_ref_count.load() + 1) {}
|
||||
|
||||
/// Copy assignment constructor
|
||||
arc& operator=(const arc& other) {
|
||||
m_inner = other.m_inner;
|
||||
m_ref_count = other.m_ref_count.load() + 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Move constructor
|
||||
arc(arc&& other) noexcept
|
||||
: m_inner(std::move(other.m_inner)), m_ref_count(other.m_ref_count.load()) {};
|
||||
|
||||
/// Move assignment constructor
|
||||
arc& operator=(arc&& other) noexcept {
|
||||
*this = std::move(other);
|
||||
return *this;
|
||||
};
|
||||
|
||||
// Inner type access
|
||||
|
||||
/// Reference to the type contained in the `arc`
|
||||
T& inner() noexcept {
|
||||
return m_inner;
|
||||
}
|
||||
|
||||
/// Read-only reference to the type contained in the `arc`
|
||||
const T& const_inner() const noexcept {
|
||||
return m_inner;
|
||||
}
|
||||
|
||||
// Reference count
|
||||
|
||||
std::size_t ref_count() const noexcept {
|
||||
return m_ref_count.load();
|
||||
}
|
||||
|
||||
private:
|
||||
T m_inner;
|
||||
|
||||
std::atomic_size_t m_ref_count = 0;
|
||||
};
|
||||
|
||||
} // namespace kuiper
|
||||
25
include/utils/assert.hpp
Normal file
25
include/utils/assert.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdlib>
|
||||
#include <print>
|
||||
#include <stacktrace>
|
||||
#include <string>
|
||||
|
||||
namespace kuiper
|
||||
{
|
||||
|
||||
#define KUIPER_ASSERT(cond) \
|
||||
if (!(cond)) { \
|
||||
std::println(stderr, "Assertion failed at: {}", __PRETTY_FUNCTION__); \
|
||||
std::abort(); \
|
||||
}
|
||||
|
||||
#define KUIPER_ASSERT_STACKTRACE(cond) \
|
||||
if (!(cond)) { \
|
||||
const auto trace = std::stacktrace::current(); \
|
||||
std::println(stderr, "Assertion failed at: {}", __PRETTY_FUNCTION__); \
|
||||
std::println(stderr, "{}", std::to_string(trace)); \
|
||||
std::abort(); \
|
||||
}
|
||||
|
||||
} // namespace kuiper
|
||||
35
include/utils/bytes.hpp
Normal file
35
include/utils/bytes.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <bit>
|
||||
#include <concepts>
|
||||
#include <cstdint>
|
||||
|
||||
namespace kuiper
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
namespace bits
|
||||
{
|
||||
template<typename T>
|
||||
requires std::integral<T>
|
||||
inline T set_bit_n(T value, std::uint8_t bit_n) {
|
||||
return value | (static_cast<T>(0b00000001) << (bit_n - 1));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
requires std::integral<T>
|
||||
inline T unset_bit_n(T value, std::uint8_t bit_n) {
|
||||
return value & ~(static_cast<T>(0b00000001) << (bit_n - 1));
|
||||
}
|
||||
} // namespace bits
|
||||
|
||||
namespace bytes
|
||||
{
|
||||
template<typename T>
|
||||
inline constexpr std::array<std::uint8_t, sizeof(T)> as_byte_array(T value) {
|
||||
return std::bit_cast<std::array<std::uint8_t, sizeof(T)>, T>(value);
|
||||
}
|
||||
} // namespace bytes
|
||||
} // namespace utils
|
||||
} // namespace kuiper
|
||||
17
include/utils/colours.hpp
Normal file
17
include/utils/colours.hpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <glm/vec4.hpp>
|
||||
|
||||
namespace kuiper
|
||||
{
|
||||
|
||||
namespace colours
|
||||
{
|
||||
constexpr const glm::vec4 middle_grey(0.737254901961f, 0.737254901961f, 0.737254901961f, 1.0f);
|
||||
constexpr const glm::vec4 dark_grey(0.1337f, 0.1337f, 0.1337f, 1.0f);
|
||||
constexpr const glm::vec4 very_dark_grey(0.05f, 0.05f, 0.05f, 1.0f);
|
||||
constexpr const glm::vec4 black(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
constexpr const glm::vec4 nothing(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
} // namespace colours
|
||||
|
||||
} // namespace kuiper
|
||||
15
include/utils/constants.hpp
Normal file
15
include/utils/constants.hpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
namespace kuiper
|
||||
{
|
||||
|
||||
namespace constants
|
||||
{
|
||||
constexpr const char* kuiper_engine_str = "Kuiper Engine";
|
||||
constexpr const char8_t* kuiper_engine_u8str = u8"Kuiper Engine";
|
||||
constexpr const char* author_str = "Adam Macdonald";
|
||||
constexpr const char8_t* author_u8str = u8"Adam Macdonald";
|
||||
|
||||
} // namespace constants
|
||||
|
||||
} // namespace kuiper
|
||||
73
include/utils/rc.hpp
Normal file
73
include/utils/rc.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
|
||||
namespace kuiper
|
||||
{
|
||||
|
||||
/// Reference counted type
|
||||
template<typename T>
|
||||
class rc {
|
||||
public:
|
||||
/// Argument-forwarding constructor
|
||||
template<typename... Args>
|
||||
explicit rc(Args&&... args)
|
||||
: m_inner(std::forward<Args>(args)...) {}
|
||||
|
||||
/// Default constructor (no args.)
|
||||
rc()
|
||||
: m_inner() {}
|
||||
|
||||
/// Destructor
|
||||
~rc() {
|
||||
if (m_ref_count > 0)
|
||||
return;
|
||||
}
|
||||
|
||||
/// Copy constructor
|
||||
rc(const rc& other)
|
||||
: m_inner(other.m_inner), m_ref_count(other.m_ref_count + 1) {}
|
||||
|
||||
/// Copy assignment constructor
|
||||
rc& operator=(const rc& other) {
|
||||
m_inner = other.m_inner;
|
||||
m_ref_count = other.m_ref_count + 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Move constructor
|
||||
rc(rc&& other) noexcept
|
||||
: m_inner(std::move(other.m_inner)), m_ref_count(other.m_ref_count) {};
|
||||
|
||||
/// Move assignment constructor
|
||||
rc& operator=(rc&& other) noexcept {
|
||||
*this = std::move(other);
|
||||
return *this;
|
||||
};
|
||||
|
||||
// Inner type access
|
||||
|
||||
/// Reference to the type contained in the `rc`
|
||||
T& inner() noexcept {
|
||||
return m_inner;
|
||||
}
|
||||
|
||||
/// Read-only reference to the type contained in the `rc`
|
||||
const T& const_inner() const noexcept {
|
||||
return m_inner;
|
||||
}
|
||||
|
||||
// Reference count
|
||||
|
||||
std::size_t ref_count() const noexcept {
|
||||
return m_ref_count;
|
||||
}
|
||||
|
||||
private:
|
||||
T m_inner;
|
||||
|
||||
std::size_t m_ref_count = 0;
|
||||
};
|
||||
|
||||
} // namespace kuiper
|
||||
39
include/utils/uuid.hpp
Normal file
39
include/utils/uuid.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include "random/random.hpp"
|
||||
|
||||
#include <cstddef> // For size_t
|
||||
#include <cstdint> // For uint64_t
|
||||
|
||||
namespace kuiper
|
||||
{
|
||||
|
||||
class UUID {
|
||||
public:
|
||||
UUID()
|
||||
: m_uuid(Random::Instance().next_u64()) {}
|
||||
UUID(const std::uint64_t uuid)
|
||||
: m_uuid(uuid) {}
|
||||
UUID(const UUID&) = default;
|
||||
|
||||
operator std::uint64_t() const {
|
||||
return m_uuid;
|
||||
}
|
||||
|
||||
private:
|
||||
std::uint64_t m_uuid = 0;
|
||||
};
|
||||
|
||||
} // namespace kuiper
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<typename T> struct hash;
|
||||
|
||||
template<> struct hash<kuiper::UUID> {
|
||||
std::size_t operator()(const kuiper::UUID& uuid) const {
|
||||
// SURELY there won't be too many collisions with 2^64 possible combinations :^)
|
||||
return static_cast<uint64_t>(uuid);
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
148
include/utils/xoshiro256plusplus.hpp
Normal file
148
include/utils/xoshiro256plusplus.hpp
Normal file
@@ -0,0 +1,148 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <random>
|
||||
|
||||
namespace kuiper::random
|
||||
{
|
||||
|
||||
class xoshiro256pp {
|
||||
public:
|
||||
xoshiro256pp(const std::array<std::uint64_t, 4>& state)
|
||||
: s(state) {}
|
||||
|
||||
static xoshiro256pp from_random_device() {
|
||||
std::random_device rd {};
|
||||
|
||||
static_assert(sizeof(std::random_device::result_type) == 4);
|
||||
|
||||
const std::uint64_t a = static_cast<std::uint64_t>(rd()) << 32 | static_cast<std::uint64_t>(rd());
|
||||
const std::uint64_t b = static_cast<std::uint64_t>(rd()) << 32 | static_cast<std::uint64_t>(rd());
|
||||
const std::uint64_t c = static_cast<std::uint64_t>(rd()) << 32 | static_cast<std::uint64_t>(rd());
|
||||
const std::uint64_t d = static_cast<std::uint64_t>(rd()) << 32 | static_cast<std::uint64_t>(rd());
|
||||
|
||||
return {{{a, b, c, d}}};
|
||||
}
|
||||
|
||||
public:
|
||||
std::uint64_t next() noexcept {
|
||||
const std::uint64_t result = rotl(s[0] + s[3], 23) + s[0];
|
||||
|
||||
const std::uint64_t t = s[1] << 17;
|
||||
|
||||
s[2] ^= s[0];
|
||||
s[3] ^= s[1];
|
||||
s[1] ^= s[2];
|
||||
s[0] ^= s[3];
|
||||
|
||||
s[2] ^= t;
|
||||
|
||||
s[3] = rotl(s[3], 45);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::uint64_t operator()(void) noexcept {
|
||||
return next();
|
||||
}
|
||||
|
||||
private:
|
||||
/* This is the jump function for the generator. It is equivalent
|
||||
to 2^128 calls to next(); it can be used to generate 2^128
|
||||
non-overlapping subsequences for parallel computations. */
|
||||
|
||||
void jump() noexcept {
|
||||
static constexpr std::array<std::uint64_t, 4> JUMP = {
|
||||
0x180ec6d33cfd0aba, 0xd5a61266f0c9392c, 0xa9582618e03fc9aa, 0x39abdc4529b1661c};
|
||||
|
||||
std::uint64_t s0 = 0;
|
||||
std::uint64_t s1 = 0;
|
||||
std::uint64_t s2 = 0;
|
||||
std::uint64_t s3 = 0;
|
||||
for (int i = 0; i < JUMP.size() / sizeof(std::uint64_t); i++)
|
||||
for (int b = 0; b < 64; b++) {
|
||||
if (JUMP[i] & UINT64_C(1) << b) {
|
||||
s0 ^= s[0];
|
||||
s1 ^= s[1];
|
||||
s2 ^= s[2];
|
||||
s3 ^= s[3];
|
||||
}
|
||||
next();
|
||||
}
|
||||
|
||||
s[0] = s0;
|
||||
s[1] = s1;
|
||||
s[2] = s2;
|
||||
s[3] = s3;
|
||||
}
|
||||
|
||||
/* This is the long-jump function for the generator. It is equivalent to
|
||||
2^192 calls to next(); it can be used to generate 2^64 starting points,
|
||||
from each of which jump() will generate 2^64 non-overlapping
|
||||
subsequences for parallel distributed computations. */
|
||||
|
||||
void long_jump() {
|
||||
static constexpr std::array<std::uint64_t, 4> LONG_JUMP = {
|
||||
0x76e15d3efefdcbbf, 0xc5004e441c522fb3, 0x77710069854ee241, 0x39109bb02acbe635};
|
||||
|
||||
std::uint64_t s0 = 0;
|
||||
std::uint64_t s1 = 0;
|
||||
std::uint64_t s2 = 0;
|
||||
std::uint64_t s3 = 0;
|
||||
for (int i = 0; i < LONG_JUMP.size() / sizeof(std::uint64_t); i++)
|
||||
for (int b = 0; b < 64; b++) {
|
||||
if (LONG_JUMP[i] & UINT64_C(1) << b) {
|
||||
s0 ^= s[0];
|
||||
s1 ^= s[1];
|
||||
s2 ^= s[2];
|
||||
s3 ^= s[3];
|
||||
}
|
||||
next();
|
||||
}
|
||||
|
||||
s[0] = s0;
|
||||
s[1] = s1;
|
||||
s[2] = s2;
|
||||
s[3] = s3;
|
||||
}
|
||||
|
||||
inline std::uint64_t rotl(const std::uint64_t x, int k) {
|
||||
return (x << k) | (x >> (64 - k));
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<std::uint64_t, 4> s {};
|
||||
};
|
||||
|
||||
// Original license & preface:
|
||||
|
||||
/* Written in 2019 by David Blackman and Sebastiano Vigna (vigna@acm.org)
|
||||
|
||||
To the extent possible under law, the author has dedicated all copyright
|
||||
and related and neighboring rights to this software to the public domain
|
||||
worldwide.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
/* This is xoshiro256++ 1.0, one of our all-purpose, rock-solid generators.
|
||||
It has excellent (sub-ns) speed, a state (256 bits) that is large
|
||||
enough for any parallel application, and it passes all tests we are
|
||||
aware of.
|
||||
|
||||
For generating just floating-point numbers, xoshiro256+ is even faster.
|
||||
|
||||
The state must be seeded so that it is not everywhere zero. If you have
|
||||
a 64-bit seed, we suggest to seed a splitmix64 generator and use its
|
||||
output to fill s. */
|
||||
|
||||
} // namespace kuiper::random
|
||||
Reference in New Issue
Block a user