惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
量子位
M
MIT News - Artificial intelligence
Y
Y Combinator Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Google DeepMind News
Google DeepMind News
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
雷峰网
雷峰网
I
InfoQ
罗磊的独立博客
博客园 - 聂微东
酷 壳 – CoolShell
酷 壳 – CoolShell
大猫的无限游戏
大猫的无限游戏
D
Docker
H
Hackread – Cybersecurity News, Data Breaches, AI and More
腾讯CDC
博客园 - 三生石上(FineUI控件)
The GitHub Blog
The GitHub Blog
K
Kaspersky official blog
P
Privacy & Cybersecurity Law Blog
S
SegmentFault 最新的问题
T
Threat Research - Cisco Blogs
H
Help Net Security
小众软件
小众软件
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
C
CERT Recently Published Vulnerability Notes
WordPress大学
WordPress大学
T
Tenable Blog
T
The Blog of Author Tim Ferriss
C
Cisco Blogs
Simon Willison's Weblog
Simon Willison's Weblog
博客园 - Franky
A
Arctic Wolf
T
Threatpost
Scott Helme
Scott Helme
C
Cybersecurity and Infrastructure Security Agency CISA
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
The Exploit Database - CXSecurity.com
G
GRAHAM CLULEY
Security Latest
Security Latest
Spread Privacy
Spread Privacy
L
LINUX DO - 热门话题
V
Vulnerabilities – Threatpost
P
Privacy International News Feed
S
Schneier on Security
Latest news
Latest news
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Cyber Attacks, Cyber Crime and Cyber Security
C
CXSECURITY Database RSS Feed - CXSecurity.com

I'm OWenT

国产大模型(GLM 5.1、Kimi K2.6)真实场景效果和 Coding Plan 额度测试 新版本libatapp的连接管理——从etcd服务发现到拓扑驱动的自动重连 新版本libatbus的设计变更——从树形路由到拓扑驱动 Protobuf又一坑 - C++标准和ABI兼容性 AI真好用-给Blog主题统一加mermaid,chart.js,excalidraw,draw.io的多种引入方式支持 给内网部署Squid-通用HTTP下载缓存 UE使用CodeChecker和clang-tidy生成静态分析报告 找出UE的循环依赖 C++小协程栈和临时变量及作用域的栈溢出问题分析 游戏服务的可观测性能力建设(C++生态) 指标上报的多线程优化和多拉取源点优化 协程(libcopp)的Channel功能和CPU命中率优化 通用RPC代码生成器 实现strong_rc_ptr(比shared_ptr更快的引用计数智能指针) 手夯一个STL allocator和对象内存分析组件 std::condition_variable 的信号丢失问题 踩坑一处(GCC)STL std::async 实现BUG导致的crash问题 GCC 14的一个warning to error BUG 给xresloader(Excel导表工具)增强UE读表支持(包含蓝图,Blueprint) Opentelemetry社区在gRPC的几个链接问题(静态库和动态库混用,musl工具链,符号裁剪) Excel转表工具(xresloader)的新验证器(验证外部Excel和文本数据,唯一性和自定义规则) protobuf v22和gRPC v1.55版本升级的依赖变化和upb适配 关于protobuf近期版本(v20/v3.20+)和 gRPC v1.54版本在某些编译环境下的一些链接和编译问题 xresloader-Excel导表工具链的近期变更汇总 打通游戏服务端框架的C++20协程改造的最后一环 Opentelemetry-cpp的Logs模块标准更新(涉及近期版本:1.8-1.9的BREAK CHANGES) 给cmake-toolset和工具链(curl等)加HTTP/2和HTTP/3支持 又开新坑之 coredns 插件: nftables和filter 关于opentelemetry-cpp社区对于C++ Head Only组件单例和符号可见性的讨论小记 填个转表工具 xresloader 去年的坑(数组尾部裁剪) 集成 upb 和 lua binding 的踩坑小记 libcopp对C++20协程的接入和接口设计 再度优化GCC、LLVM、Clang、libc++、libc++abi等套件的构建脚本 游戏服务的分布式事务优化(二)- 事务管理 游戏服务的分布式事务优化(一)- Write Ahead Log(WAL) 模块 记录一些bazel适配用编译选项 测试现代化硬件C++浮点数性能和一致性 适配Boringssl和OpenSSL 3.0 近期cmake-toolset的一些适配问题 C++20 Text Formatting/fmtlib 适配问题小记 再次重构LLVM+Clang+libcxx+libc++abi+其他相关工具的构建流程 重构基于CMake的构建工具链 新版GCC和LLVM+Clang终于Release啦 折腾一下nftables下的双拨 [C++20] Module partitions和符号交叉引用(声明和实现分离) [Rust] 实现一个线程安全且迭代器可以保存的链表 基于protobuf的代码生成 几个使用protobuf中C++接口的Arena的坑 Amazon Aurora DB存储引擎论文阅读小记 近期对libatapp的一些优化调整(增加服务发现和连接管理,支持yaml等) xresloader转表工具链增加了一些新功能(map,oneof支持,输出矩阵,基于模板引擎的加载代码生成等) 在游戏服务器中使用分布式事务 libcopp接入C++20 Coroutine和一些过渡期的设计 libatbus 的大幅优化 nftables初体验 容器配置开发环境小计 PALM Tree - 适合多核并发架构的B+树 - 论文阅读小记 跨平台协程库 - libcopp 简介 C++20 Coroutine 性能测试 (附带和libcopp/libco/libgo/goroutine/linux ucontext对比) 尝鲜Github Action 一些xresloader(转表工具)的改进 protobuf、flatbuffer、msgpack 针对小数据包的简单对比 协程框架(libcopp) 小幅优化 Excel转表工具(xresloader) 增加protobuf插件功能和集成 UnrealEngine 支持 Anna(支持任意扩展和超高性能的KV数据库系统)阅读笔记 C++20 Coroutine libcopp merge boost.context 1.69.0 Google去中心化分布式系统论文三件套(Percolator、Spanner、F1)读后感 Rust玩具-企业微信机器人通用服务 使用ELK辅助监控开发测试环境服务质量和问题定位 Webpack+vue+boostrap+ejs构建Web版GM工具 Rust的第二次接触-写个小服务器程序 理解和适配AEAD加密套件 atsf4g-co的进化:协程框架v2、对象路由系统和一些其他细节优化 协程框架(libcopp)v2优化、自适应栈池和同类库的Benchmark对比 可执行文件压缩 初识Rust 使用restructedtext编写xresloader文档 atframework的etcd模块化重构 C++的backtrace ECDH椭圆双曲线(比DH快10倍的密钥交换)算法简介和封装 protobuf-net的动态Message实现 pbc的proto3接入 atgateway内置协议流程优化-加密、算法协商和ECDH 整理一波软件源镜像同步工具+DevOps工具 Blog切换到Hugo libcopp v2的第一波优化完成 libcopp(v2) vs goroutine性能测试 libcopp的线程安全、栈池和merge boost.context 1.64.0 GCC 7和LLVM+Clang+libc++abi 4.0的构建脚本 libatbus的几个藏得很深的bug 用cmake交叉编译到iOS和Android 开源项目得一些小维护 atapp的c binding和c#适配 对象路由系统设计 2016年总结 近期的一个协程流程BUG 重写了llvm+clang+libc++和libc++abi的构建脚本 atsf4g完整游戏工程示例|I'm OWenT atframework基本框架已经完成|I'm OWenT
2018年的新通用伪随机数算法(xoshiro / xoroshiro)的C++(head only)实现
owent · 2018-10-18 · via I'm OWenT

前段时间看到说Lua 5.4用了一种新的通用随机数算法,替换掉本来内部使用的CRT的随机数引擎。我看了一下大致的实现,CPU和空间复杂度任然保持了一个较低的水平,并且循环节和说是随机性都还不错。我们游戏项目中原本对大量随机数场景的随机数算法使用的是基于线性同余的TAUS88,但是使用过程中发现这个算法分布上还是有一些不是很理想,所以就想把这个新的科研成果也用进我们项目中试试看效果。

/**
 * @file random_xor_combine_core.h
 * @brief 伪随机数生成器  - xoshiro算法核心
 * @see http://xoshiro.di.unimi.it
 * @note 2018年的新型的全功能型伪随机数算法,也是lua 5.4内建的伪随机数算法
 *
 * Licensed under the MIT licenses.
 * @version 1.0
 * @author OWenT
 * @date 2018年09月30日
 *
 * @history
 *
 */


#ifndef UTIL_RANDOM_XOSHIRO_CORE_H
#define UTIL_RANDOM_XOSHIRO_CORE_H

// #pragma once

#include <stdint.h>
#include <cstddef>

namespace util {
    namespace random {
        namespace core {
            /**
             * @breif just for
             *          xoshiro256**
             *          xoshiro256+
             *          xoroshiro128**
             *          xoroshiro128+
             * @note not support for xoroshiro64** 、xoroshiro64*、xoroshiro512** 、xoroshiro512*、xoroshiro1024** 、xoroshiro1024*
             */
            template <typename UIntType, bool is_plus, int iidx, int n1, int n2>
            class xoshinro_engine {
            public:
                typedef UIntType    result_type;
                typedef result_type seed_type[4];

            private:
                /// \endcond
                seed_type xoshinro_seed_;

                static inline result_type rotl(const result_type x, int k) {
                    return (x << k) | (x >> ((sizeof(result_type) * 8) - static_cast<result_type>(k)));
                }

                template <typename, bool>
                struct next_init;

                template <typename T>
                struct next_init<T, true> {
                    static inline result_type call(seed_type &s) { return s[0] + s[3]; }
                };

                template <typename T>
                struct next_init<T, false> {
                    static inline result_type call(seed_type &s) { return rotl(s[iidx] * 5, 7) * 9; }
                };

            protected:
                result_type next() {
                    const result_type ret = next_init<UIntType, is_plus>::call(xoshinro_seed_);
                    const result_type t   = xoshinro_seed_[1] << n1;

                    xoshinro_seed_[2] ^= xoshinro_seed_[0];
                    xoshinro_seed_[3] ^= xoshinro_seed_[1];
                    xoshinro_seed_[1] ^= xoshinro_seed_[2];
                    xoshinro_seed_[0] ^= xoshinro_seed_[3];

                    xoshinro_seed_[2] ^= t;
                    xoshinro_seed_[3] = rotl(xoshinro_seed_[3], n2);

                    return ret;
                }

                void jump(const seed_type &JUMP) {
                    result_type s0 = 0;
                    result_type s1 = 0;
                    result_type s2 = 0;
                    result_type s3 = 0;
                    for (size_t i = 0; i < sizeof(JUMP) / sizeof(JUMP[0]); i++) {
                        for (size_t b = 0; b < sizeof(result_type) * 8; b++) {
                            if (JUMP[i] & result_type(1) << b) {
                                s0 ^= xoshinro_seed_[0];
                                s1 ^= xoshinro_seed_[1];
                                s2 ^= xoshinro_seed_[2];
                                s3 ^= xoshinro_seed_[3];
                            }
                            next();
                        }
                    }

                    xoshinro_seed_[0] = s0;
                    xoshinro_seed_[1] = s1;
                    xoshinro_seed_[2] = s2;
                    xoshinro_seed_[3] = s3;
                }

            public:
                xoshinro_engine() {
                    xoshinro_seed_[0] = 0;
                    xoshinro_seed_[1] = 0;
                    xoshinro_seed_[2] = 0;
                    xoshinro_seed_[3] = 0;
                }
                xoshinro_engine(result_type s) {
                    xoshinro_seed_[0] = 0;
                    xoshinro_seed_[1] = 0;
                    xoshinro_seed_[2] = 0;
                    xoshinro_seed_[3] = 0;
                    init_seed(s);
                }

                void init_seed(result_type s) {
                    xoshinro_seed_[0] = s;
                    xoshinro_seed_[1] = 0xff;
                    xoshinro_seed_[2] = 0;
                    xoshinro_seed_[3] = 0;

                    // just like in lua 5.4
                    for (int i = 0; i < 16; ++i) {
                        next();
                    }
                }

                template <typename It>
                void init_seed(It &first, It last) {
                    It begin = first;
                    for (int i = 0; i < 4; ++i) {
                        if (begin != last) {
                            xoshinro_seed_[i] = *begin;
                            ++begin;
                        } else {
                            xoshinro_seed_[i] = 0;
                        }
                    }

                    // just like in lua 5.4
                    for (int i = 0; i < 16; ++i) {
                        next();
                    }
                }

                result_type random() { return next(); }

                result_type operator()() { return random(); }

                inline const seed_type &get_seed() const { return xoshinro_seed_; }
            };

            template <bool is_plus>
            class xoshinro_engine_128 : public xoshinro_engine<uint32_t, is_plus, 0, 9, 11> {
            public:
                typedef xoshinro_engine<uint32_t, is_plus, 0, 9, 11> base_type;
                typedef typename base_type::result_type              result_type;
                typedef typename base_type::seed_type                seed_type;

            public:
                xoshinro_engine_128() {}
                xoshinro_engine_128(result_type s) : base_type(s) {}

                using base_type::jump;

                /**
                 * @brief just like call next() for 2^64 times
                 */
                void jump() {
                    static const result_type jump_params[4] = {0x8764000b, 0xf542d2d3, 0x6fa035c3, 0x77f2db5b};
                    jump(jump_params);
                }
            };

            template <bool is_plus>
            class xoshinro_engine_256 : public xoshinro_engine<uint64_t, is_plus, 1, 17, 45> {
            public:
                typedef xoshinro_engine<uint64_t, is_plus, 1, 17, 45> base_type;
                typedef typename base_type::result_type               result_type;
                typedef typename base_type::seed_type                 seed_type;

            public:
                xoshinro_engine_256() {}
                xoshinro_engine_256(result_type s) : base_type(s) {}

                using base_type::jump;

                /**
                 * @brief just like call next() for 2^128 times
                 */
                void jump() {
                    static const result_type jump_params[4] = {0x180ec6d33cfd0aba, 0xd5a61266f0c9392c, 0xa9582618e03fc9aa,
                                                               0x39abdc4529b1661c};
                    jump(jump_params);
                }

                /**
                 * @brief just like call next() for 2^192 times
                 */
                void long_jump() {
                    static const result_type jump_params[4] = {0x76e15d3efefdcbbf, 0xc5004e441c522fb3, 0x77710069854ee241,
                                                               0x39109bb02acbe635};
                    jump(jump_params);
                }
            };
        } // namespace core
    }     // namespace random
} // namespace util


#endif /* UTIL_RANDOM_XOSHIRO_CORE_H */

// ============================ 随机数引擎封装 ================================
/**
 * @file random_generator.h
 * @brief 伪随机数生成器
 *
 * Licensed under the MIT licenses.
 * @version 1.0
 * @author OWenT
 * @date 2018年09月30日
 *
 * @history
 *
 */

#ifndef UTIL_RANDOM_GENERATOR_H
#define UTIL_RANDOM_GENERATOR_H

// #pragma once

#include <limits>
#include <numeric>
#include <ctime>

// #include "random_mt_core.h"
// #include "random_xor_combine_core.h"
// #include "random_xoshiro_core.h"

namespace util {
    namespace random {
        /**
         * 随机数包装类,用以提供高级功能
         */
        template <typename CoreType>
        class random_manager_wrapper {
        public:
            typedef CoreType                        core_type;
            typedef typename core_type::result_type result_type;

        private:
            core_type core_;

        public:
            random_manager_wrapper() {}
            random_manager_wrapper(result_type rd_seed) : core_(rd_seed) {}

            inline core_type &      get_core() { return core_; }
            inline const core_type &get_core() const { return core_; }

            /**
             * 初始化随机数种子
             * @param [in] rd_seed 随机数种子
             */
            void init_seed(result_type rd_seed) { core_.init_seed(rd_seed); }

            /**
             * 初始化随机数种子
             * @note 取值范围为 [first, last)
             * @param [in] first 随机数种子散列值起始位置
             * @param [in] last 随机数种子散列值结束位置
             */
            template <typename It>
            void init_seed(It &first, It last) {
                core_.init_seed(first, last);
            }

            /**
             * 产生一个随机数
             * @return 产生的随机数
             */
            result_type random() { return core_(); }

            /**
             * 产生一个随机数
             * @return 产生的随机数
             */
            result_type operator()() { return random(); }

            /**
             * 产生一个随机数
             * @param [in] lowest 下限
             * @param [in] highest 上限(必须大于lowest)
             * @note 取值范围 [lowest, highest)
             * @return 产生的随机数
             */
            template <typename ResaultType>
            ResaultType random_between(ResaultType lowest, ResaultType highest) {
                if (highest <= lowest) {
                    return lowest;
                }
                result_type res = (*this)();
                return static_cast<ResaultType>(res % static_cast<result_type>(highest - lowest)) + lowest;
            }
        };

        // ============== 随机数生成器 - xoshiro 算法(比梅森旋转算法消耗更少的内存,但是循环节更小,随机性比taus好) ==============
        // @see http://xoshiro.di.unimi.it
        // 循环节: 2^128 − 1
        typedef random_manager_wrapper<core::xoshinro_engine_128<false> > xoroshiro128_starstar;
        // 循环节: 2^128 − 1,少一次旋转,更快一点点
        typedef random_manager_wrapper<core::xoshinro_engine_128<true> > xoroshiro128_plus;
        // 循环节: 2^256 − 1
        typedef random_manager_wrapper<core::xoshinro_engine_256<false> > xoshiro256_starstar;
        // 循环节: 2^256 − 1,少一次旋转,更快一点点
        typedef random_manager_wrapper<core::xoshinro_engine_256<true> > xoshiro256_plus;
    } // namespace random
} // namespace util

#endif /* _UTIL_RANDOM_GENERATOR_H_ */


// ================================= 简易单元测试 =================================
#include <cstring>
#include <iostream>
#include <list>

#ifdef max
#undef max
#endif

// #include "random/random_generator.h"

// ===================== 这里是单元测试组件的简化版 =====================
#define test_case_func_name(test_name, case_name) test_func_test_##test_name##_case_##case_name
#define test_case_obj_name(test_name, case_name) test_obj_test_##test_name##_case_##case_name##_obj

#define CASE_TEST(test_name, case_name) \
static void test_case_func_name(test_name, case_name) (); \
static test_case_base test_case_obj_name(test_name, case_name) (#test_name, #case_name, test_case_func_name(test_name, case_name)); \
void test_case_func_name(test_name, case_name) ()

struct test_case_base;
static std::list<test_case_base*> g_all_tests;
static test_case_base* g_current_test;
static size_t g_success_count = 0;
static size_t g_failed_count = 0;

struct test_case_base {
    typedef void (*fn_t)();
    test_case_base(const char* test_name, const char* case_name, fn_t fn): test_name_(test_name), case_name_(case_name), fn_(fn) {
        g_all_tests.push_back(this);
    }

    const char* test_name_;
    const char* case_name_;
    fn_t fn_;
};

#define CASE_EXPECT_EQ(L, R) \
if ((L) == (R)) { \
    ++ g_success_count; \
} else {\
    ++ g_failed_count; \
    std::cerr<< "Expect Failed: "<< #L<< " == " << #R<< " @"<< __FILE__<< ":"<< __LINE__<< std::endl; \
}

#define CASE_EXPECT_NE(L, R) \
if ((L) != (R)) { \
    ++ g_success_count; \
} else {\
    ++ g_failed_count; \
    std::cerr<< "Expect Failed: "<< #L<< " != " << #R<< " @"<< __FILE__<< ":"<< __LINE__<< std::endl; \
}

#define CASE_EXPECT_TRUE(EXPR) \
if ((EXPR)) { \
    ++ g_success_count; \
} else {\
    ++ g_failed_count; \
    std::cerr<< "Expect True Failed: "<< #EXPR<< " @"<< __FILE__<< ":"<< __LINE__<< std::endl; \
}

// ---------------------- 这里是单元测试组件的简化版 ----------------------

CASE_TEST(random_test, xoroshiro128_starstar) {
    util::random::xoroshiro128_starstar gen1;
    gen1.init_seed(0x12345678);

    uint32_t checked1[] = {0x6baaab3a, 0x9385fdbb, 0x99ae85fe, 0x88e2358c, 0x6592b0ce,
                           0x20eadc84, 0x6a8d80b7, 0xa676abb7, 0x726ef19a, 0xd4e33183};

    for (size_t i = 0; i < sizeof(checked1) / sizeof(checked1[0]); ++i) {
        CASE_EXPECT_EQ(gen1.random(), checked1[i]);
    }

    gen1.get_core().jump();
    uint32_t checked2[] = {0xb40ef1a3, 0xeaf5f926, 0xdaedd531, 0xd75a0342, 0xf5cd493d,
                           0x4081f259, 0x92a08a09, 0x8e7856ff, 0x3eecdb2,  0x34cd820c};

    for (size_t i = 0; i < sizeof(checked2) / sizeof(checked2[0]); ++i) {
        CASE_EXPECT_EQ(gen1.random(), checked2[i]);
    }


    uint32_t  arr_seeds[] = {0x01, 0x02, 0x03, 0x04};
    uint32_t *ptr_seeds   = &arr_seeds[0];
    gen1.init_seed(ptr_seeds, ptr_seeds + 4);

    uint32_t checked3[] = {0x483919e4, 0xa90f4ce8, 0xe55d1499, 0x17c2185e, 0xdb11c3f7,
                           0x63557f98, 0xc7ad6874, 0x4a4a45ca, 0x74dec471, 0xf7e82f2a};

    for (size_t i = 0; i < sizeof(checked3) / sizeof(checked3[0]); ++i) {
        CASE_EXPECT_EQ(gen1.random(), checked3[i]);
    }

    gen1.get_core().jump();
    uint32_t checked4[] = {0xf30187c0, 0xe533ff68, 0x628920df, 0xa998b9e7, 0xcac83081,
                           0xe23e175b, 0x8aef7f7a, 0x43e56ba2, 0x59dc108b, 0x35b5536c};

    for (size_t i = 0; i < sizeof(checked4) / sizeof(checked4[0]); ++i) {
        CASE_EXPECT_EQ(gen1.random(), checked4[i]);
    }
}

CASE_TEST(random_test, xoroshiro128_plus) {
    util::random::xoroshiro128_plus gen1;
    gen1.init_seed(0x12345678);

    uint32_t checked1[] = {0xf1c950fb, 0x3c9b4647, 0x212ab3fb, 0x9930ad20, 0xe891a595,
                           0x5f3d9875, 0x264dd138, 0xb23b09e7, 0xb351ccd6, 0xf6342d85};

    for (size_t i = 0; i < sizeof(checked1) / sizeof(checked1[0]); ++i) {
        CASE_EXPECT_EQ(gen1.random(), checked1[i]);
    }

    gen1.get_core().jump();
    uint32_t checked2[] = {0x65981904, 0x2d406a8b, 0xf722cc27, 0xd93f4e0,  0xc8c324e,
                           0x47adc6fc, 0x2e331b89, 0x2de59177, 0x68298f16, 0x3c1f786};

    for (size_t i = 0; i < sizeof(checked2) / sizeof(checked2[0]); ++i) {
        CASE_EXPECT_EQ(gen1.random(), checked2[i]);
    }


    uint32_t  arr_seeds[] = {0x01, 0x02, 0x03, 0x04};
    uint32_t *ptr_seeds   = &arr_seeds[0];
    gen1.init_seed(ptr_seeds, ptr_seeds + 4);

    uint32_t checked3[] = {0x6ba5dc24, 0x1f1d11fa, 0xfa4932ff, 0x86a802af, 0x784c234,
                           0xbabe3a02, 0x77ad7d11, 0x7ebe938,  0x44211069, 0x2a5ba899};

    for (size_t i = 0; i < sizeof(checked3) / sizeof(checked3[0]); ++i) {
        CASE_EXPECT_EQ(gen1.random(), checked3[i]);
    }

    gen1.get_core().jump();
    uint32_t checked4[] = {0x4956e25b, 0x1637a896, 0xc303f2ef, 0x9f3f6ac7, 0x8048281d,
                           0xfd181cdb, 0xd50c6ccb, 0xa1e5dc16, 0xe2e6feed, 0xe8901128};

    for (size_t i = 0; i < sizeof(checked4) / sizeof(checked4[0]); ++i) {
        CASE_EXPECT_EQ(gen1.random(), checked4[i]);
    }
}


CASE_TEST(random_test, xoshiro256_starstar) {
    util::random::xoshiro256_starstar gen1;
    gen1.init_seed(0x12345678);

    uint64_t checked1[] = {0x83ea18ca6bf49f0c, 0xca24436623484287, 0xe7965c078396b9dc, 0xb9036864adb81725, 0x5c35ba435d92ab9b,
                           0x45202e3b4085a2cc, 0xa1e9410f7f528e4e, 0x48eb35365566f0b2, 0x90412e6e9ae131c3, 0xba4a1df61ca0b237};

    for (size_t i = 0; i < sizeof(checked1) / sizeof(checked1[0]); ++i) {
        CASE_EXPECT_EQ(gen1.random(), checked1[i]);
    }

    gen1.get_core().jump();
    uint64_t checked2[] = {0x555e786541686a07, 0x6b5e064426c7dce4, 0x63a8537c3e2de537, 0x1b1eb7c6ef11c6c,  0x9d6eaac62ce6a4f4,
                           0x8b2cb439dc19fadd, 0xb749c288597ceac4, 0x92da83e146fdff1d, 0x110d38c051cededc, 0xadab1aacca67bd98};

    for (size_t i = 0; i < sizeof(checked2) / sizeof(checked2[0]); ++i) {
        CASE_EXPECT_EQ(gen1.random(), checked2[i]);
    }

    gen1.get_core().long_jump();
    uint64_t checked3[] = {0x855835566240e421, 0xef37ac417209f23c, 0x27d0b120fbc1263b, 0x3acf06c9c8bebcfc, 0x8e4c39858e961d77,
                           0x54ef99ad7133b336, 0x507e39520e592971, 0xf17538afb5568bf2, 0x9b12bf7bc0ad1cb,  0xe30b952ddb0edc22};

    for (size_t i = 0; i < sizeof(checked3) / sizeof(checked3[0]); ++i) {
        CASE_EXPECT_EQ(gen1.random(), checked3[i]);
    }


    uint64_t  arr_seeds[] = {0x01, 0x02, 0x03, 0x04};
    uint64_t *ptr_seeds   = &arr_seeds[0];
    gen1.init_seed(ptr_seeds, ptr_seeds + 4);

    uint64_t checked4[] = {0x167894d082017430, 0x38b95133d3ac9e80, 0x1f5b58670bd33b,   0xa72aa9c1f3c234dc, 0xa369742bfe107109,
                           0xa10057c6cbaaf5b7, 0xed9d205bdc0671c4, 0x36379ae97a7e84fc, 0x68a4d0807b200c28, 0x1178895e2d328ef3};

    for (size_t i = 0; i < sizeof(checked4) / sizeof(checked4[0]); ++i) {
        CASE_EXPECT_EQ(gen1.random(), checked4[i]);
    }

    gen1.get_core().jump();
    uint64_t checked5[] = {0x6892346243ec2224, 0x721f3bb7498cd45b, 0x4706ddfc3ac5a535, 0x1833b360cae1f78f, 0x49c783132a986f0f,
                           0x228581842db7c171, 0x575b41c3f6bafa53, 0xd54e667c5bdc8331, 0xd16f385b2194a5ee, 0xd35320c4a01add19};

    for (size_t i = 0; i < sizeof(checked5) / sizeof(checked5[0]); ++i) {
        CASE_EXPECT_EQ(gen1.random(), checked5[i]);
    }

    gen1.get_core().long_jump();
    uint64_t checked6[] = {0xfc07bbe2a0ff49e3, 0x25b74d3c3e1395a4, 0x66c3b4e434a41253, 0xeef93c334db407df, 0xcbe33255433c267a,
                           0x1aeb5a580f8b97f7, 0xee0b16ebb05cc830, 0x1951fff956477d9e, 0xd586fc5de6068234, 0xb77c43707de92854};

    for (size_t i = 0; i < sizeof(checked6) / sizeof(checked6[0]); ++i) {
        CASE_EXPECT_EQ(gen1.random(), checked6[i]);
    }
}


CASE_TEST(random_test, xoshiro256_plus) {
    util::random::xoshiro256_plus gen1;
    gen1.init_seed(0x12345678);

    uint64_t checked1[] = {0xa6766515ded04cf7, 0x8b8ef459334146d2, 0xa5e132765ffaea1b, 0x42a32c7899960f6,  0xb55425c32b032ae,
                           0x4f5b510e66ed35c3, 0x86364d228b55294e, 0x15fee24568b9f2e4, 0x79172607cb7639c8, 0x380558a4c62a5df3};

    for (size_t i = 0; i < sizeof(checked1) / sizeof(checked1[0]); ++i) {
        CASE_EXPECT_EQ(gen1.random(), checked1[i]);
    }

    gen1.get_core().jump();
    uint64_t checked2[] = {0x65e286c2682c7ede, 0x6fd589cda019d6da, 0x74ca58c461d9116,  0xaf78ff6a0b528fa,  0x532d4519bc355dff,
                           0x4fd9664f92848fd0, 0xe871531860e04f51, 0x9f66375cd3511195, 0xedb2c3bd1fad482d, 0xabd051255c4a95a4};

    for (size_t i = 0; i < sizeof(checked2) / sizeof(checked2[0]); ++i) {
        CASE_EXPECT_EQ(gen1.random(), checked2[i]);
    }

    gen1.get_core().long_jump();
    uint64_t checked3[] = {0x823dc8ffe9ec3044, 0x2282021c3619f998, 0x58b7e7b6e4bf12c2, 0xba93e7ae8ffd60be, 0x7c5604182a5e5c,
                           0xfe2b1a4e6cc03509, 0x3cc13d59418b58b6, 0xee043f7276571ff3, 0xb0cefcacf43f423d, 0x2c06bd7d4b2a7b61};

    for (size_t i = 0; i < sizeof(checked3) / sizeof(checked3[0]); ++i) {
        CASE_EXPECT_EQ(gen1.random(), checked3[i]);
    }


    uint64_t  arr_seeds[] = {0x01, 0x02, 0x03, 0x04};
    uint64_t *ptr_seeds   = &arr_seeds[0];
    gen1.init_seed(ptr_seeds, ptr_seeds + 4);

    uint64_t checked4[] = {0xf7d9f594a5851eca, 0x1554ccd2906e61d5, 0xf1a8da801e3b1052, 0xbf31cf72a94cc91b, 0x1a8b65873ac842c9,
                           0xd15befe036b53136, 0x8f8ff0898e5cca09, 0xf287e57ae52130ec, 0x4b93d1235a7a9687, 0x4a1e76c36a3f44f9};

    for (size_t i = 0; i < sizeof(checked4) / sizeof(checked4[0]); ++i) {
        CASE_EXPECT_EQ(gen1.random(), checked4[i]);
    }

    gen1.get_core().jump();
    uint64_t checked5[] = {0x5ab99b574ab79179, 0x9dd72e9427eecf2d, 0x847348252d253c3a, 0x45e4172e49119e02, 0xfef4edb4819f165e,
                           0xecd2f9db3f6911a3, 0xaa21cb67c76ca6cf, 0x26a7e2345c58b741, 0xaf507d5180f1070c, 0x5c635df444a4f1};

    for (size_t i = 0; i < sizeof(checked5) / sizeof(checked5[0]); ++i) {
        CASE_EXPECT_EQ(gen1.random(), checked5[i]);
    }

    gen1.get_core().long_jump();
    uint64_t checked6[] = {0x7f463ee9f76cdf70, 0xc0a587ad5ee6ec85, 0xb42e076175295e3a, 0x96d379025346fa5b, 0xa4de52d9b1d5e2e5,
                           0xa8790f06ce0d31de, 0x5d0eb9a768b4700f, 0xa4fbadd2392670bd, 0xc7b31a2f3b7819ee, 0xcca74cb594188bcd};

    for (size_t i = 0; i < sizeof(checked6) / sizeof(checked6[0]); ++i) {
        CASE_EXPECT_EQ(gen1.random(), checked6[i]);
    }
}


int main() {
    size_t success_count = 0;
    size_t failed_count = 0;
    
    for(std::list<test_case_base*>::iterator iter = g_all_tests.begin(); iter != g_all_tests.end(); ++ iter) {
        g_current_test = *iter;
        size_t old_fail = g_failed_count;
        size_t old_succ = g_success_count;
        std::cout<< "Start Test: "<< g_current_test->test_name_<< "."<< g_current_test->case_name_<< std::endl;
        g_current_test->fn_();
        if (old_fail < g_failed_count) {
            ++ failed_count;
            std::cerr<< "Test Failed: "<< g_current_test->test_name_<< "."<< g_current_test->case_name_<< " with "<< 
                (g_failed_count - old_fail)<< " failed test(s) and "<< 
                (g_success_count - old_succ)<< " passed test(s)"<< std::endl;
        } else {
            ++ success_count;
            std::cout<< "Test Passed: "<< g_current_test->test_name_<< "."<< g_current_test->case_name_<< " with "<< 
                (g_success_count - old_succ)<< " passed test(s)"<< std::endl;
        }
    }

    std::cout<< "All test case(s) finished, success: "<< success_count<< ", failed: "<< failed_count<< std::endl;
    return 0;
}