Compare commits

..

2 Commits

Author SHA1 Message Date
Avril 2458a2b969
Added skeleton for new RNG type: Lorenz Attractor.
2 years ago
Avril 295da7df02
Started branch "progress", for working on timed-out progress indicator. Current build succeeds but does not use progress indicators at all.
2 years ago

@ -0,0 +1,36 @@
#ifndef _ERROR_H
#define _ERROR_H
#ifndef $PASTE
# define $_PASTE(x,y) x ## y
# define $PASTE(x,y) $_PASTE(x,y)
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
constexpr inline bool is_noexcept=
#if __cpp_exceptions
#define EXCEPT 1
//#define try try
//#define catch(...) catch(__VA_ARGS__)
false
#else
#define EXCEPT 0
#define NOEXCEPT
//#define catch(...) __try {} catch(__VA_ARGS__)
//#define try if constexpr(!is_noexcept)
//#define throw (void)0
true
#endif
;
#endif
#endif /* _ERROR_H */

@ -4,6 +4,7 @@
#include "shuffle3.h" #include "shuffle3.h"
#ifdef __cplusplus #ifdef __cplusplus
#include "rng/impl.hpp"
extern "C" { extern "C" {
#endif #endif
@ -11,8 +12,12 @@ enum rng_kind {
RNG_KIND_FRNG, RNG_KIND_FRNG,
RNG_KIND_DRNG, RNG_KIND_DRNG,
RNG_KIND_XORNG, RNG_KIND_XORNG,
RNG_KIND_LORENZ,
}; };
typedef long double rng_st_lorenz_t;
typedef _Complex long double rng_lorenz_t;
typedef struct rng_init typedef struct rng_init
{ {
enum rng_kind kind; enum rng_kind kind;
@ -26,6 +31,11 @@ typedef struct rng_init
struct { struct {
uint64_t state[2]; uint64_t state[2];
} xorng; } xorng;
struct {
rng_lorenz_t point;
const rng_st_lorenz_t (* _UNIQUE state)[5];
uint64_t iter;
} lorenz;
} init; } init;
} rng_init_opt; } rng_init_opt;
@ -38,14 +48,15 @@ void rng_free(rng_t ptr);
// Tests // Tests
extern void rng_test(); extern void rng_test();
extern void rng_test_spec(rng_t rng); extern void rng_test_spec(rng_t rng) __attribute__((nonnull(1)));
#ifdef __cplusplus #ifdef __cplusplus
} }
// RNG interfaces // RNG interfaces
#include <rng/frng.hpp> #include "rng/xoroshiro128plus.hpp"
#include <rng/drng.hpp> #include "rng/frng.hpp"
#include <rng/xoroshiro128plus.hpp> #include "rng/drng.hpp"
#include "rng/lorenz.hpp"
namespace rng { namespace rng {
void test_algo(RNG&& rng); void test_algo(RNG&& rng);

@ -34,6 +34,7 @@ namespace rng
inline constexpr frng(const std::array<double, 2>& ar) : state(ar){P} inline constexpr frng(const std::array<double, 2>& ar) : state(ar){P}
inline constexpr frng(std::array<double, 2>&& ar) : state(ar){P} inline constexpr frng(std::array<double, 2>&& ar) : state(ar){P}
inline constexpr frng(const double (&ar)[2]) : state({ar[0], ar[1]}) {P} inline constexpr frng(const double (&ar)[2]) : state({ar[0], ar[1]}) {P}
constexpr virtual ~frng() = default;
#undef P #undef P
inline constexpr double next_double() override { return sample(); } inline constexpr double next_double() override { return sample(); }
inline constexpr float next_float() override { return (float)sample(); } inline constexpr float next_float() override { return (float)sample(); }

@ -6,6 +6,8 @@
/// Base class for RNG impls /// Base class for RNG impls
struct RNG { struct RNG {
constexpr RNG() noexcept = default;
virtual unsigned char byte(); virtual unsigned char byte();
virtual void bytes(unsigned char* ptr, std::size_t len); virtual void bytes(unsigned char* ptr, std::size_t len);
@ -29,7 +31,12 @@ struct RNG {
inline virtual float next_float() { return (float)sample(); } inline virtual float next_float() { return (float)sample(); }
inline virtual double next_double() { return sample(); } inline virtual double next_double() { return sample(); }
virtual ~RNG() = default; constexpr virtual ~RNG() = default;
//explicit operator rng_t() const noexcept;
//friend operator RNG*(rng_t) noexcept;
protected: protected:
virtual double sample() = 0; virtual double sample() = 0;
//private:
//struct rng_impl* _UNIQUE _held = nullptr;
}; };

@ -0,0 +1,2 @@
#pragma once

@ -9,10 +9,11 @@ namespace rng
{ {
using State = std::array<std::uint64_t, 2>; using State = std::array<std::uint64_t, 2>;
#define P D_dprintf("xorng: seeded with (%lu, %lu)", state[0], state[1]); #define P D_dprintf("xorng: seeded with (%lu, %lu)", state[0], state[1]);
inline constexpr xoroshiro128plus(std::uint64_t s0, std::uint64_t s1) : state({s0, s1}){P} inline constexpr xoroshiro128plus(std::uint64_t s0, std::uint64_t s1) : RNG(), state({s0, s1}){P}
inline constexpr xoroshiro128plus(std::array<std::uint64_t, 2>&& ar) : state(ar){P} inline constexpr xoroshiro128plus(std::array<std::uint64_t, 2>&& ar) : RNG(), state(ar){P}
inline constexpr xoroshiro128plus(const std::array<std::uint64_t, 2>& ar) : state(ar){P} inline constexpr xoroshiro128plus(const std::array<std::uint64_t, 2>& ar) : RNG(), state(ar){P}
inline constexpr xoroshiro128plus(const std::uint64_t (&ar)[2]) : state({ar[0], ar[1]}){P} inline constexpr xoroshiro128plus(const std::uint64_t (&ar)[2]) : RNG(), state({ar[0], ar[1]}){P}
inline virtual ~xoroshiro128plus() {}
#undef P #undef P
std::uint64_t next_ulong(); std::uint64_t next_ulong();
using RNG::next_long; using RNG::next_long;
@ -25,5 +26,6 @@ namespace rng
private: private:
State state; State state;
}; };
static_assert(std::derived_from<xoroshiro128plus, RNG>, "Wtf???");
} }

@ -4,63 +4,22 @@
#include <reinterpret.h> #include <reinterpret.h>
#include <algorithm> #include <algorithm>
#include <iostream> #include <iostream>
#include <chrono>
#include <fmt/format.h>
#include <fsvec.hpp> #include <fsvec.hpp>
#include <perc.h>
#include <shuffle3.h> #include <shuffle3.h>
namespace rng { namespace rng {
namespace details [[gnu::visibility("hidden")]] {
static inline auto make_prog(FILE* to = stdout) noexcept
{
if(isatty(fileno(to))) return pr::make_dyn(pr::Progress{to});
else return pr::make_dyn(pr::disable);
}
template<bool Create, bool UseNanos=false>
static inline decltype(auto) clock(auto&... last) noexcept {
using namespace std::chrono;
if constexpr(Create) return steady_clock::now();
else {
constexpr auto take_first = [] (auto& one, auto&...) { return std::forward<decltype(one)>(one); };
time_point end = steady_clock::now();
auto& last = take_first(std::forward<decltype(last)>(last)...); //TODO: Expand this....
auto duration = end - last;
last = end;
if constexpr(UseNanos)
return duration_cast<nanoseconds>(duration).count();
else return duration_cast<milliseconds>(duration).count();
}
}
}
template<typename T, typename R> template<typename T, typename R>
inline void shuffle(R& rng, span<T> span) inline void shuffle(R& rng, span<T> span)
{ {
if(!span.size()) return; if(!span.size()) return;
//pr::Progress prog{stdout};
#define MS_OKAY 100
auto prog = details::make_prog();
auto timer = clock<true>();
std::cout << " -> shuffling " << span.size() << " objects..." << std::flush; std::cout << " -> shuffling " << span.size() << " objects..." << std::flush;
prog->spin(0);
for(std::size_t i=span.size()-1;i>0;i--) for(std::size_t i=span.size()-1;i>0;i--)
{ {
auto j = rng.next_long(i); auto j = rng.next_long(i);
std::swap(span[i], span[j]); std::swap(span[i], span[j]);
if(clock<false>(timer) >= MS_OKAY) {
prog->aux(fmt::format("{} <-> {}, {} / {}", i, j, span.size() - i, span.size()));
prog->spin(double(span.size() - i) / double(span.size()));
}
} }
prog->spin(1);
std::cout << " OK" << std::endl; std::cout << " OK" << std::endl;
} }

@ -1,8 +1,53 @@
#include <stdexcept>
#include <iostream> #include <iostream>
#include <cmath> #include <cmath>
#include <sys/types.h>
#include <rng/impl.hpp> #include <rng/impl.hpp>
#include <error.h>
#include <panic.h>
//#define IMPORT_ONE(NS, NAME) using NAME = NS :: NAME
//IMPORT_ONE(std, ssize_t);
template<typename To, typename T, typename Unit=unsigned char>
static inline To* offset_ptr(T* ptr, ssize_t by) noexcept
{
return reinterpret_cast<To*>(reinterpret_cast<Unit*>(ptr)+by);
}
/*
template<typename To, typename Unit>
offset_ptr(auto* p, std::ssize_t by) -> offset_ptr<To, decltype(p), Unit>;
template<typename To>
offset_ptr(auto* p, std::ssize_t by) -> offset_ptr<To, decltype(p)>;
*/
#ifdef FT_PT_OPERATORS
inline operator RNG*(rng_t ptr) noexcept
{
if(__builtin_expect(!ptr, false)) return nullptr;
#ifdef DEBUG
RNG* op =
#else
return
#endif
reinterpret_cast<RNG*>(offset_ptr<RNG>(ptr, -static_cast<ssize_t>(offsetof(RNG, _held))));
#ifdef DEBUG
if(__builtin_expect(!op, false)) return nullptr;
if(__builtin_expect(op->_held, false)) panic("Invalid rng_t -> RNG conversion");
return ptr;
#endif
}
RNG::operator rng_t() const noexcept
{
return reinterpret_cast<rng_t>(static_cast<RNG*>(this)->_held);
}
#endif
inline unsigned char RNG::byte() inline unsigned char RNG::byte()
{ {
return (unsigned char)next_int(255); return (unsigned char)next_int(255);
@ -48,14 +93,21 @@ std::int64_t RNG::next_long()
} }
#include <rng.h> #include <rng.h>
#include <panic.h>
namespace { // C interface namespace { // C interface
using namespace std; using namespace std;
#define extract_ptr(ptr) ((RNG*)(ptr)) [[gnu::always_inline, gnu::gnu_inline]]
static inline RNG* extract_ptr(rng_t ptr)
{ return reinterpret_cast<RNG*> (ptr); }
static inline RNG& extract_ref(rng_t rng) static inline RNG& extract_ref(rng_t rng)
{ {
return *extract_ptr(rng); return *extract_ptr(rng);
} }
template<std::derived_from<RNG> T>
static inline rng_t wrap_ptr(T* ptr) noexcept
{
if(__builtin_expect(!ptr, false)) return nullptr;
return reinterpret_cast<rng_t>(static_cast<RNG*>(ptr));
}
template<typename T> template<typename T>
static inline T* extract_downcast_ptr(rng_t rng) static inline T* extract_downcast_ptr(rng_t rng)
{ {
@ -64,29 +116,50 @@ namespace { // C interface
extern "C" extern "C"
{ {
rng_t rng_new(rng_init_opt opt) rng_t rng_new(rng_init_opt opt)
{ {
switch(opt.kind) switch(opt.kind)
{ {
case RNG_KIND_FRNG: return (rng_t) new rng::frng(opt.init.frng.state); case RNG_KIND_FRNG: return wrap_ptr( new rng::frng(opt.init.frng.state) );
case RNG_KIND_DRNG: return (rng_t) new rng::drng(opt.init.drng.state); case RNG_KIND_DRNG: return wrap_ptr( new rng::drng(opt.init.drng.state) );
case RNG_KIND_XORNG: return (rng_t) new rng::xoroshiro128plus(opt.init.xorng.state); case RNG_KIND_XORNG: return wrap_ptr( new rng::xoroshiro128plus(opt.init.xorng.state) );
//case RNG_KIND_LORENX: return static_cast<rng_t>( new rng::lorenzAttractor(opt.init.lorenz); );
default: panic("Unknown RNG init opt: %d", opt.kind); default: panic("Unknown RNG init opt: %d", opt.kind);
__builtin_unreachable();
} }
return nullptr; return nullptr;
} }
void rng_free(rng_t rng) void rng_free(rng_t rng)
{ {
RNG* ptr = (RNG*)rng; RNG* ptr = extract_ptr(rng);
delete ptr; delete ptr;
} }
[[gnu::nonnull(1)]]
void rng_test_spec(rng_t rng) void rng_test_spec(rng_t rng)
{ {
cout << "rng_test_spec:" << endl; auto& ref = extract_ref(rng);
rng::test_algo(std::move(extract_ref(rng))); cout << "rng_test_spec (" << typeid(ref).name() << ")..." << std::flush;
if constexpr(!is_noexcept) {
#if EXCEPT
try {
rng::test_algo(std::move(ref));
}
catch(const std::exception& except) {
cout << "\r\r\r\tERROR: " << (except.what() ?: typeid(except).name()) << endl;
rng_free(rng);
throw;
} catch(...) {
cout << "\r\r\r\tERROR" << endl;
rng_free(rng);
throw;
}
#endif
} else rng::test_algo(std::move(ref));
cout << "\r\r\r\tOK" << endl;
rng_free(rng);
} }
} }
} }

Loading…
Cancel
Save