Added matrix utilities
This commit is contained in:
parent
5603c7dc0f
commit
bbed86f19d
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
.DS_Store
|
31
Makefile
Normal file
31
Makefile
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
# Recursive wildcard function (properly defined)
|
||||
rwildcard = $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))
|
||||
|
||||
CXX = g++
|
||||
CXXFLAGS = -Wall -std=c++20
|
||||
|
||||
# Use $(call ...) not ${call ...}
|
||||
ALL_LIBS = $(call rwildcard,math/,*.cpp) $(call rwildcard,generators/,*.cpp) $(call rwildcard,randomness_tests/,*.cpp)
|
||||
|
||||
# Expand wildcard properly for current directory
|
||||
SRCS = main.cpp $(ALL_LIBS)
|
||||
|
||||
TEST_SRCS = code_tests/test.cpp $(ALL_LIBS)
|
||||
|
||||
TARGET = splat
|
||||
TEST_TARGET = splat_test
|
||||
|
||||
.PHONY: all main test clean
|
||||
all: $(TARGET) ${TEST_TARGET}
|
||||
$(TARGET): $(SRCS)
|
||||
$(CXX) $(CXXFLAGS) -o $@ $^
|
||||
|
||||
test: $(TEST_TARGET)
|
||||
|
||||
$(TEST_TARGET): $(TEST_SRCS)
|
||||
$(CXX) $(CXXFLAGS) -o $@ $^
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET) $(TEST_TARGET) *.o
|
||||
|
@ -1,7 +1,9 @@
|
||||
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
||||
#include "./doctest.h"
|
||||
|
||||
#include "../math/incomplete_gamma.cpp"
|
||||
#include "../math/incomplete_gamma.h"
|
||||
#include "../math/matrix.h"
|
||||
#include <iostream>
|
||||
|
||||
TEST_CASE("igam function"){
|
||||
|
||||
@ -12,6 +14,7 @@ TEST_CASE("igam function"){
|
||||
// for ii in range(20):
|
||||
// print(f"igamtest({i/2}, {ii/2}, {scipy.special.gammainc(i/2,ii/2)});")
|
||||
|
||||
std::cout << " Splat CodeTests\n";
|
||||
|
||||
auto igamtest = [](double a, double x, double req) {
|
||||
REQUIRE(igam(a,x)== doctest::Approx(req).epsilon(0.00000000000001));
|
||||
@ -198,4 +201,22 @@ TEST_CASE("igam function"){
|
||||
igamtest(4.5, 9.0, 0.9648264605330151);
|
||||
igamtest(4.5, 9.5, 0.974807104918331);
|
||||
}
|
||||
}
|
||||
}
|
||||
TEST_CASE("Matrix utilities"){
|
||||
splat::matrix<3> testMatrix = {
|
||||
std::bitset<3>("010"),
|
||||
std::bitset<3>("110"),
|
||||
std::bitset<3>("010")
|
||||
};
|
||||
|
||||
splat::matrix<3> testMatrix2 = {
|
||||
std::bitset<3>("010"),
|
||||
std::bitset<3>("101"),
|
||||
std::bitset<3>("011")
|
||||
};
|
||||
|
||||
|
||||
REQUIRE(splat::getRank(testMatrix) == 2);
|
||||
REQUIRE(splat::getRank(testMatrix2) == 3);
|
||||
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
g++ -std=c++11 code_tests/test.cpp -o testcode.o
|
||||
g++ -std=c++11 math/matrix.cpp code_tests/test.cpp -o testcode.o
|
||||
./testcode.o
|
||||
rm testcode.o
|
||||
rm testcode.o
|
||||
|
||||
|
@ -7,25 +7,22 @@
|
||||
|
||||
#include "../../rng.h"
|
||||
#include "../generator.h"
|
||||
#include "./lehmer.h"
|
||||
|
||||
// parameters recommended by Nakazawa & Nakazawa
|
||||
// https://en.wikipedia.org/wiki/Lehmer_random_number_generator
|
||||
|
||||
namespace splat {
|
||||
class lehmer_generator : public PRNG {
|
||||
public:
|
||||
lehmer_generator(uint32_t genSeed) : PRNG(genSeed) {
|
||||
seed = genSeed;
|
||||
}
|
||||
uint32_t generate() override {
|
||||
seed = (a * seed) % m;
|
||||
return seed;
|
||||
}
|
||||
std::string getName() override {
|
||||
return "lehmer";
|
||||
}
|
||||
private:
|
||||
uint64_t a = 7759097958782935LL;
|
||||
uint64_t m = 18055400005099021LL;
|
||||
};
|
||||
}
|
||||
lehmer_generator::lehmer_generator(uint32_t genSeed) : PRNG(genSeed) {
|
||||
seed = genSeed;
|
||||
}
|
||||
|
||||
uint32_t lehmer_generator::generate() {
|
||||
seed = (a * seed) % m;
|
||||
return seed;
|
||||
}
|
||||
|
||||
std::string lehmer_generator::getName() {
|
||||
return "lehmer";
|
||||
}
|
||||
}
|
||||
|
16
generators/LCG/lehmer.h
Normal file
16
generators/LCG/lehmer.h
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
#pragma once
|
||||
#include "../generator.h"
|
||||
#include <cstdint>
|
||||
|
||||
namespace splat {
|
||||
class lehmer_generator : public PRNG {
|
||||
public:
|
||||
lehmer_generator(uint32_t genSeed);
|
||||
uint32_t generate() override;
|
||||
std::string getName() override;
|
||||
private:
|
||||
static const uint64_t a = 7759097958782935LL;
|
||||
static const uint64_t m = 18055400005099021LL;
|
||||
};
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
#include "../rng.h"
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../rng.h"
|
||||
|
||||
|
||||
namespace splat {
|
||||
class PRNG {
|
||||
public:
|
||||
|
@ -89,38 +89,8 @@ namespace splat {
|
||||
}
|
||||
|
||||
std::string mt19937_generator::getName() {
|
||||
return "mt19937-32 test";
|
||||
return "mt19937-32";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// namespace splat {
|
||||
// class mt19937_generator : public PRNG {
|
||||
// public:
|
||||
// mt19937_generator(uint32_t genSeed) : PRNG(genSeed) {
|
||||
// state = mt19937_init(seed);
|
||||
// nextblock();
|
||||
// }
|
||||
// uint32_t generate() override {
|
||||
// uint32_t generated = random_values[position];
|
||||
// position++;
|
||||
// if(position>=624){
|
||||
// nextblock();
|
||||
// }
|
||||
// return generated;
|
||||
// }
|
||||
// std::string getName() override {
|
||||
// return "mt19937-32";
|
||||
// }
|
||||
// private:
|
||||
// std::array<uint32_t,624> state;
|
||||
// std::array<uint32_t,624> random_values;
|
||||
// int position;
|
||||
// // goes to next block of 624 values
|
||||
// void nextblock() {
|
||||
// state = mt19937_twist(state);
|
||||
// random_values = mt19937_temper(state);
|
||||
// position = 0;
|
||||
// }
|
||||
// };
|
||||
// }
|
@ -1,25 +1,22 @@
|
||||
#include "../rng.h"
|
||||
#include "./generator.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include "./xorshift.h"
|
||||
// parameters recommended by Nakazawa & Nakazawa
|
||||
// https://en.wikipedia.org/wiki/Lehmer_random_number_generator
|
||||
|
||||
namespace splat {
|
||||
class xorshift32 : public PRNG {
|
||||
public:
|
||||
xorshift32(uint32_t genSeed) : PRNG(genSeed) {
|
||||
state = genSeed;
|
||||
}
|
||||
uint32_t generate() override {
|
||||
state ^= state << 13;
|
||||
state ^= state >> 17;
|
||||
state ^= state << 5;
|
||||
return state;
|
||||
}
|
||||
std::string getName() override {
|
||||
return "xorshift32";
|
||||
}
|
||||
private:
|
||||
uint32_t state;
|
||||
};
|
||||
}
|
||||
|
||||
xorshift32_generator::xorshift32_generator(uint32_t genSeed) : PRNG(genSeed) {
|
||||
state = genSeed;
|
||||
}
|
||||
u_int32_t xorshift32_generator::generate() {
|
||||
state ^= state << 13;
|
||||
state ^= state >> 17;
|
||||
state ^= state << 5;
|
||||
return state;
|
||||
}
|
||||
std::string xorshift32_generator::getName() {
|
||||
return "xorshift32";
|
||||
}
|
||||
}
|
||||
|
14
generators/xorshift.h
Normal file
14
generators/xorshift.h
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
#pragma once
|
||||
#include "generator.h"
|
||||
|
||||
namespace splat {
|
||||
class xorshift32_generator : public PRNG {
|
||||
public:
|
||||
xorshift32_generator(uint32_t genSeed);
|
||||
uint32_t generate() override;
|
||||
std::string getName() override;
|
||||
private:
|
||||
uint32_t state;
|
||||
};
|
||||
}
|
16
main.cpp
16
main.cpp
@ -6,13 +6,13 @@
|
||||
//
|
||||
|
||||
#include "rng.h"
|
||||
#include "generators/LCG/lehmer.cpp"
|
||||
#include "generators/mt19937.cpp"
|
||||
#include "generators/xorshift.cpp"
|
||||
#include "randomness_tests/frequency_monobit.cpp"
|
||||
#include "randomness_tests/frequency_block.cpp"
|
||||
#include "randomness_tests/runs.cpp"
|
||||
#include "randomness_tests/runs_ones.cpp"
|
||||
#include "generators/LCG/lehmer.h"
|
||||
#include "generators/mt19937.h"
|
||||
#include "generators/xorshift.h"
|
||||
#include "randomness_tests/frequency_monobit.h"
|
||||
#include "randomness_tests/frequency_block.h"
|
||||
#include "randomness_tests/runs.h"
|
||||
#include "randomness_tests/runs_ones.h"
|
||||
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@ namespace splat {
|
||||
// add generators here
|
||||
addGen<mt19937_generator>(generators, seed);
|
||||
addGen<lehmer_generator>(generators, seed);
|
||||
addGen<xorshift32>(generators,seed);
|
||||
addGen<xorshift32_generator>(generators,seed);
|
||||
|
||||
return generators;
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "../rng.h"
|
||||
|
||||
#pragma once
|
||||
#include "./incomplete_gamma.h"
|
||||
|
||||
double igam(double a, double x) {
|
||||
double maxlog = 7.09782712893383996732E2;
|
||||
|
4
math/incomplete_gamma.h
Normal file
4
math/incomplete_gamma.h
Normal file
@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
double igam(double a, double x);
|
||||
double igamc(double a, double x);
|
87
math/matrix.cpp
Normal file
87
math/matrix.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
#include <bitset>
|
||||
#include <iostream>
|
||||
#include <cstdint>
|
||||
#include "matrix.h"
|
||||
|
||||
namespace splat {
|
||||
template <int S>
|
||||
std::bitset<S>& matrix<S>::operator[](int i){
|
||||
return bits[i];
|
||||
}
|
||||
|
||||
template <int S>
|
||||
const std::bitset<S>& matrix<S>::operator[](int i) const {
|
||||
return bits[i];
|
||||
}
|
||||
|
||||
|
||||
template <int S>
|
||||
const bool matrix<S>::get(int row, int column) const {
|
||||
return bits[row][S-column-1];
|
||||
}
|
||||
|
||||
|
||||
template <int S>
|
||||
void matrix<S>::debug() {
|
||||
for(int i=0; i<S; i++){
|
||||
for(int ii=0; ii<S; ii++){
|
||||
std::cout << get(i,ii);
|
||||
}
|
||||
std::cout << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <int S>
|
||||
void gaussianElimination(matrix<S>& matrix){
|
||||
int top = 0;
|
||||
for(int column=0; column<S; column++){
|
||||
// get the position of the first one (pivot)
|
||||
int firstOnePosition = -1;
|
||||
for(int row=top; row<S; row++){
|
||||
if(matrix.get(row, column)){
|
||||
firstOnePosition = row;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if there was no one, we move on
|
||||
if(firstOnePosition==-1){
|
||||
top++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// now swap the pivot row with the relative top row
|
||||
if(firstOnePosition!=top){
|
||||
std::bitset<S> temp = matrix[top];
|
||||
matrix[top] = matrix[firstOnePosition];
|
||||
matrix[firstOnePosition] = temp;
|
||||
}
|
||||
|
||||
// now we XOR all the rows below our pivot with the pivot row
|
||||
for(int row = firstOnePosition+1; row<S; row++){
|
||||
if(matrix.get(row,column)){
|
||||
matrix[row]^=matrix[top];
|
||||
}
|
||||
}
|
||||
top++;
|
||||
}
|
||||
}
|
||||
|
||||
template <int S>
|
||||
int getRank(matrix<S>& matrix){
|
||||
gaussianElimination(matrix);
|
||||
int rank = 0;
|
||||
for(int i=0; i<S; i++){
|
||||
if(matrix[i]!=std::bitset<S>(0)){
|
||||
rank++;
|
||||
}
|
||||
}
|
||||
return rank;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template int getRank<3>(matrix<3>&);
|
||||
template int getRank<32>(matrix<32>&);
|
||||
}
|
28
math/matrix.h
Normal file
28
math/matrix.h
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
#pragma once
|
||||
#include <bitset>
|
||||
#include <iostream>
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
|
||||
namespace splat {
|
||||
template <int S>
|
||||
struct matrix {
|
||||
std::bitset<S> bits[S];
|
||||
std::bitset<S>& operator[](int i);
|
||||
|
||||
const std::bitset<S>& operator[](int i) const;
|
||||
|
||||
const bool get(int row, int column) const;
|
||||
|
||||
void debug();
|
||||
};
|
||||
|
||||
template <int S>
|
||||
void gaussianElimination(matrix<S>& matrix);
|
||||
|
||||
template <int S>
|
||||
int getRank(matrix<S>& matrix);
|
||||
}
|
||||
|
21
randomness_tests/binary_matrix.cpp
Normal file
21
randomness_tests/binary_matrix.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include "./binary_matrix.h"
|
||||
#include "./rngtest.h"
|
||||
|
||||
|
||||
namespace splat {
|
||||
|
||||
binary_matrix_test::binary_matrix_test(std::vector<std::bitset<32>> &testData) : RNGTEST(testData){
|
||||
testPValue = runTest(data);
|
||||
testPassed = testPValue > 0.01;
|
||||
}
|
||||
|
||||
std::string binary_matrix_test::getName() {
|
||||
return "Binary Matrix Rank Test";
|
||||
}
|
||||
|
||||
// We will use matrices of size 32x32 as recommended
|
||||
double binary_matrix_test::runTest(std::vector<std::bitset<32>> &data) {
|
||||
int num_matrices = data.size() / 32;
|
||||
|
||||
}
|
||||
}
|
19
randomness_tests/binary_matrix.h
Normal file
19
randomness_tests/binary_matrix.h
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../rng.h"
|
||||
#include "./rngtest.h"
|
||||
#include "../math/incomplete_gamma.h"
|
||||
#include "../math/matrix.h"
|
||||
|
||||
|
||||
|
||||
namespace splat {
|
||||
|
||||
class binary_matrix_test : public RNGTEST {
|
||||
public:
|
||||
binary_matrix_test(std::vector<std::bitset<32>> &testData);
|
||||
std::string getName() override;
|
||||
double runTest(std::vector<std::bitset<32>> &data) override;
|
||||
};
|
||||
}
|
@ -6,52 +6,46 @@
|
||||
//
|
||||
|
||||
#include "../rng.h"
|
||||
#include "../math/incomplete_gamma.cpp"
|
||||
|
||||
#include "../math/incomplete_gamma.h"
|
||||
#include "./frequency_block.h"
|
||||
#include "./rngtest.h"
|
||||
|
||||
namespace splat {
|
||||
class frequency_block_test : public RNGTEST {
|
||||
public:
|
||||
frequency_block_test(std::vector<std::bitset<32>> &testData) : RNGTEST(testData) {
|
||||
block_size = data.size() * 32 / 150;
|
||||
testPValue = runTest(data);
|
||||
testPassed = testPValue > 0.01;
|
||||
}
|
||||
std::string getName() override {
|
||||
return std::format("Frequency Block [{}]", block_size);
|
||||
}
|
||||
double runTest(std::vector<std::bitset<32>> &data) override {
|
||||
|
||||
// std::cout << "DEBUG: "<<data.size() << "\n";
|
||||
frequency_block_test::frequency_block_test(std::vector<std::bitset<32>> &testData) : RNGTEST(testData) {
|
||||
block_size = data.size() * 32 / 150;
|
||||
testPValue = runTest(data);
|
||||
testPassed = testPValue > 0.01;
|
||||
}
|
||||
|
||||
long long bitcount = data.size() * 32;
|
||||
long long chunks = bitcount / block_size;
|
||||
double frequency_block_test::runTest(std::vector<std::bitset<32>> &data) {
|
||||
|
||||
double x2stat = 0;
|
||||
|
||||
for(int chunkIndex = 0; chunkIndex < chunks; chunkIndex++){
|
||||
// std::cout << "NEWCHUNK: ";
|
||||
double onecount = 0;
|
||||
for(int i=0; i<block_size; i++){
|
||||
int dataIndex = (((chunkIndex * block_size)+i) / 32);
|
||||
int bitIndex = (((chunkIndex * block_size)+i) % 32);
|
||||
onecount += data[dataIndex][bitIndex];
|
||||
// std::cout << data[dataIndex][bitIndex];
|
||||
}
|
||||
double oneproportion = onecount / (double)block_size;
|
||||
long long bitcount = data.size() * 32;
|
||||
long long chunks = bitcount / block_size;
|
||||
|
||||
x2stat += 4*block_size*std::pow((oneproportion - 0.5),2);
|
||||
double x2stat = 0;
|
||||
|
||||
for(int chunkIndex = 0; chunkIndex < chunks; chunkIndex++){
|
||||
// std::cout << "NEWCHUNK: ";
|
||||
double onecount = 0;
|
||||
for(int i=0; i<block_size; i++){
|
||||
int dataIndex = (((chunkIndex * block_size)+i) / 32);
|
||||
int bitIndex = (((chunkIndex * block_size)+i) % 32);
|
||||
onecount += data[dataIndex][bitIndex];
|
||||
// std::cout << data[dataIndex][bitIndex];
|
||||
}
|
||||
double oneproportion = onecount / (double)block_size;
|
||||
|
||||
// std::cout << "\n";
|
||||
}
|
||||
x2stat += 4*block_size*std::pow((oneproportion - 0.5),2);
|
||||
|
||||
// std::cout << "[debug] calling igamc with "<<(chunks/2) <<','<<(x2stat/2) << "\n";
|
||||
double p = igam(chunks/2, x2stat/2);
|
||||
return p;
|
||||
}
|
||||
private:
|
||||
long long block_size;
|
||||
|
||||
};
|
||||
}
|
||||
// std::cout << "\n";
|
||||
}
|
||||
|
||||
// std::cout << "[debug] calling igamc with "<<(chunks/2) <<','<<(x2stat/2) << "\n";
|
||||
double p = igam(chunks/2, x2stat/2);
|
||||
return p;
|
||||
}
|
||||
std::string frequency_block_test::getName() {
|
||||
return std::format("Frequency Block [{}]", block_size);
|
||||
}
|
||||
}
|
||||
|
23
randomness_tests/frequency_block.h
Normal file
23
randomness_tests/frequency_block.h
Normal file
@ -0,0 +1,23 @@
|
||||
//
|
||||
#pragma once
|
||||
// frequency_monobit.cpp
|
||||
// rng
|
||||
//
|
||||
// Created by Asher Falcon on 21/06/2025.
|
||||
//
|
||||
|
||||
#include "../rng.h"
|
||||
|
||||
#include "./rngtest.h"
|
||||
|
||||
namespace splat {
|
||||
class frequency_block_test : public RNGTEST {
|
||||
public:
|
||||
frequency_block_test(std::vector<std::bitset<32>> &testData);
|
||||
std::string getName() override;
|
||||
double runTest(std::vector<std::bitset<32>> &data) override;
|
||||
private:
|
||||
long long block_size;
|
||||
|
||||
};
|
||||
}
|
@ -7,27 +7,26 @@
|
||||
|
||||
#include "../rng.h"
|
||||
#include "./rngtest.h"
|
||||
#include "./frequency_monobit.h"
|
||||
|
||||
namespace splat {
|
||||
class frequency_monobit_test : public RNGTEST {
|
||||
public:
|
||||
frequency_monobit_test(std::vector<std::bitset<32>> &testData) : RNGTEST(testData) {
|
||||
testPValue = runTest(data);
|
||||
testPassed = testPValue > 0.01;
|
||||
}
|
||||
std::string getName() override {
|
||||
return "Frequency Monobit";
|
||||
}
|
||||
double runTest(std::vector<std::bitset<32>> &data) override {
|
||||
long long s = 0;
|
||||
for(auto bitset : data){
|
||||
for(int i=0; i<32; i++){
|
||||
s += (2*bitset[i])-1;
|
||||
}
|
||||
}
|
||||
double sobs = ((double)std::abs(s))/std::sqrt(data.size()*32);
|
||||
double pvalue = std::erfc(sobs/std::sqrt(2));
|
||||
return pvalue;
|
||||
}
|
||||
};
|
||||
}
|
||||
frequency_monobit_test::frequency_monobit_test(std::vector<std::bitset<32>> &testData) : RNGTEST(testData) {
|
||||
testPValue = runTest(data);
|
||||
testPassed = testPValue > 0.01;
|
||||
}
|
||||
|
||||
double frequency_monobit_test::runTest(std::vector<std::bitset<32>> &data) {
|
||||
long long s = 0;
|
||||
for(auto bitset : data){
|
||||
for(int i=0; i<32; i++){
|
||||
s += (2*bitset[i])-1;
|
||||
}
|
||||
}
|
||||
double sobs = ((double)std::abs(s))/std::sqrt(data.size()*32);
|
||||
double pvalue = std::erfc(sobs/std::sqrt(2));
|
||||
return pvalue;
|
||||
}
|
||||
std::string frequency_monobit_test::getName() {
|
||||
return "Frequency Monobit";
|
||||
}
|
||||
}
|
||||
|
22
randomness_tests/frequency_monobit.h
Normal file
22
randomness_tests/frequency_monobit.h
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
#pragma once
|
||||
//
|
||||
// frequency_monobit.cpp
|
||||
// rng
|
||||
//
|
||||
// Created by Asher Falcon on 21/06/2025.
|
||||
//
|
||||
|
||||
#include "../rng.h"
|
||||
#include "./rngtest.h"
|
||||
|
||||
|
||||
|
||||
namespace splat {
|
||||
class frequency_monobit_test : public RNGTEST {
|
||||
public:
|
||||
frequency_monobit_test(std::vector<std::bitset<32>> &testData);
|
||||
std::string getName() override;
|
||||
double runTest(std::vector<std::bitset<32>> &data) override;
|
||||
};
|
||||
}
|
@ -1,7 +1,10 @@
|
||||
#include "../rng.h"
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../rng.h"
|
||||
|
||||
|
||||
|
||||
namespace splat {
|
||||
class RNGTEST {
|
||||
public:
|
||||
|
@ -1,38 +1,38 @@
|
||||
#include "../rng.h"
|
||||
#include "./rngtest.h"
|
||||
#include "./runs.h"
|
||||
|
||||
namespace splat {
|
||||
class runs_test : public RNGTEST {
|
||||
public:
|
||||
runs_test(std::vector<std::bitset<32>> &testData) : RNGTEST(testData) {
|
||||
testPValue = runTest(data);
|
||||
testPassed = testPValue > 0.01;
|
||||
}
|
||||
std::string getName() override {
|
||||
return "Runs";
|
||||
}
|
||||
double runTest(std::vector<std::bitset<32>> &data) override {
|
||||
long long totalSize = data.size() * 32;
|
||||
|
||||
double vnobs = 1;
|
||||
runs_test::runs_test(std::vector<std::bitset<32>> &testData) : RNGTEST(testData) {
|
||||
testPValue = runTest(data);
|
||||
testPassed = testPValue > 0.01;
|
||||
}
|
||||
std::string runs_test::getName(){
|
||||
return "Runs";
|
||||
|
||||
double onesproportion = 0;
|
||||
}
|
||||
double runs_test::runTest(std::vector<std::bitset<32>> &data) {
|
||||
long long totalSize = data.size() * 32;
|
||||
|
||||
for(int i=0; i<totalSize-1; i++){
|
||||
double vnobs = 1;
|
||||
|
||||
if(data[i/32][i%32]!=data[(i+1)/32][(i+1)%32]){
|
||||
vnobs++;
|
||||
}
|
||||
onesproportion+=data[i/32][i%32];
|
||||
}
|
||||
double onesproportion = 0;
|
||||
|
||||
onesproportion/=totalSize;
|
||||
for(int i=0; i<totalSize-1; i++){
|
||||
|
||||
return std::erfc(
|
||||
std::abs(vnobs-(2*totalSize*onesproportion*(1-onesproportion)))
|
||||
/
|
||||
(2*std::sqrt(2*totalSize)*onesproportion*(1-onesproportion))
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
if(data[i/32][i%32]!=data[(i+1)/32][(i+1)%32]){
|
||||
vnobs++;
|
||||
}
|
||||
onesproportion+=data[i/32][i%32];
|
||||
}
|
||||
|
||||
onesproportion/=totalSize;
|
||||
|
||||
return std::erfc(
|
||||
std::abs(vnobs-(2*totalSize*onesproportion*(1-onesproportion)))
|
||||
/
|
||||
(2*std::sqrt(2*totalSize)*onesproportion*(1-onesproportion))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
13
randomness_tests/runs.h
Normal file
13
randomness_tests/runs.h
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
#pragma once
|
||||
#include "../rng.h"
|
||||
#include "./rngtest.h"
|
||||
|
||||
namespace splat {
|
||||
class runs_test : public RNGTEST {
|
||||
public:
|
||||
runs_test(std::vector<std::bitset<32>> &testData);
|
||||
std::string getName() override;
|
||||
double runTest(std::vector<std::bitset<32>> &data) override;
|
||||
};
|
||||
}
|
@ -1,78 +1,76 @@
|
||||
#include "../rng.h"
|
||||
#include "./rngtest.h"
|
||||
#include "../math/incomplete_gamma.cpp"
|
||||
#define vecdebug(list) for(auto vecdebugitem : list){ std::cout << vecdebugitem <<","; }std::cout << "\n";
|
||||
|
||||
#include "../math/incomplete_gamma.h"
|
||||
#include "./runs_ones.h"
|
||||
|
||||
|
||||
namespace splat {
|
||||
class runs_ones_test : public RNGTEST {
|
||||
public:
|
||||
runs_ones_test(std::vector<std::bitset<32>> &testData) : RNGTEST(testData) {
|
||||
testPValue = runTest(data);
|
||||
testPassed = testPValue > 0.01;
|
||||
}
|
||||
std::string getName() override {
|
||||
return "Runs of 1s";
|
||||
}
|
||||
double runTest(std::vector<std::bitset<32>> &data) override {
|
||||
long long totalSize = data.size() * 32;
|
||||
|
||||
if(totalSize < 750000){
|
||||
std::cout << "Error, runs of ones test requires more than 750K bits of input\n";
|
||||
return 0;
|
||||
runs_ones_test::runs_ones_test(std::vector<std::bitset<32>> &testData) : RNGTEST(testData) {
|
||||
testPValue = runTest(data);
|
||||
testPassed = testPValue > 0.01;
|
||||
}
|
||||
std::string runs_ones_test::getName(){
|
||||
return "Runs of 1s";
|
||||
}
|
||||
|
||||
double runs_ones_test::runTest(std::vector<std::bitset<32>> &data) {
|
||||
long long totalSize = data.size() * 32;
|
||||
|
||||
if(totalSize < 750000){
|
||||
std::cout << "Error, runs of ones test requires more than 750K bits of input\n";
|
||||
return 0;
|
||||
}
|
||||
// we do it with M=10^4 here
|
||||
|
||||
std::vector<double> counts(7,0);
|
||||
|
||||
double chunks = totalSize / 10000;
|
||||
|
||||
for(int chunkIndex=0; chunkIndex<chunks; chunkIndex++){
|
||||
|
||||
int longestRun = 0;
|
||||
int ones = 0;
|
||||
|
||||
|
||||
for(int i=0; i<10000; i++){
|
||||
long long index = chunkIndex*10000 + i;
|
||||
int dataIndex = (index / 32);
|
||||
int bitIndex = (index % 32);
|
||||
|
||||
if(data[dataIndex][bitIndex]){
|
||||
ones++;
|
||||
}else{
|
||||
if(ones>longestRun) longestRun = ones;
|
||||
ones = 0;
|
||||
}
|
||||
// we do it with M=10^4 here
|
||||
|
||||
std::vector<double> counts(7,0);
|
||||
|
||||
double chunks = totalSize / 10000;
|
||||
|
||||
for(int chunkIndex=0; chunkIndex<chunks; chunkIndex++){
|
||||
|
||||
int longestRun = 0;
|
||||
|
||||
int ones = 0;
|
||||
|
||||
for(int i=0; i<10000; i++){
|
||||
long long index = chunkIndex*10000 + i;
|
||||
int dataIndex = (index / 32);
|
||||
int bitIndex = (index % 32);
|
||||
|
||||
if(data[dataIndex][bitIndex]){
|
||||
ones++;
|
||||
}else{
|
||||
if(ones>longestRun) longestRun = ones;
|
||||
ones = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(longestRun <=10){
|
||||
counts[0]++;
|
||||
}else if(longestRun>=16){
|
||||
counts[6]++;
|
||||
}else{
|
||||
counts[longestRun-10]++;
|
||||
}
|
||||
}
|
||||
|
||||
double x2 = 0;
|
||||
|
||||
std::vector<double> probabilities = {
|
||||
0.0882,
|
||||
0.2092,
|
||||
0.2483,
|
||||
0.1933,
|
||||
0.1208,
|
||||
0.0675,
|
||||
0.0727
|
||||
};
|
||||
|
||||
for(int i=0; i<7; i++){
|
||||
x2 += std::pow((counts[i] - (chunks * probabilities[i])),2.0) /(chunks * probabilities[i]);
|
||||
|
||||
}
|
||||
return igamc(3, x2/2.0);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if(longestRun <=10){
|
||||
counts[0]++;
|
||||
}else if(longestRun>=16){
|
||||
counts[6]++;
|
||||
}else{
|
||||
counts[longestRun-10]++;
|
||||
}
|
||||
|
||||
}
|
||||
double x2 = 0;
|
||||
|
||||
std::vector<double> probabilities = {
|
||||
0.0882,
|
||||
0.2092,
|
||||
0.2483,
|
||||
0.1933,
|
||||
0.1208,
|
||||
0.0675,
|
||||
0.0727
|
||||
};
|
||||
|
||||
for(int i=0; i<7; i++){
|
||||
x2 += std::pow((counts[i] - (chunks * probabilities[i])),2.0) /(chunks * probabilities[i]);
|
||||
|
||||
}
|
||||
return igamc(3, x2/2.0);
|
||||
}
|
||||
}
|
||||
|
15
randomness_tests/runs_ones.h
Normal file
15
randomness_tests/runs_ones.h
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
#pragma once
|
||||
#include "../rng.h"
|
||||
#include "./rngtest.h"
|
||||
|
||||
|
||||
namespace splat {
|
||||
|
||||
class runs_ones_test : public RNGTEST {
|
||||
public:
|
||||
runs_ones_test(std::vector<std::bitset<32>> &testData);
|
||||
std::string getName() override;
|
||||
double runTest(std::vector<std::bitset<32>> &data) override;
|
||||
};
|
||||
}
|
BIN
splat_test
Executable file
BIN
splat_test
Executable file
Binary file not shown.
@ -1,12 +1 @@
|
||||
# React + Vite
|
||||
|
||||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
||||
|
||||
Currently, two official plugins are available:
|
||||
|
||||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh
|
||||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
||||
|
||||
## Expanding the ESLint configuration
|
||||
|
||||
If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project.
|
||||
This is a web showcase of the Splat library, using emscripten to compile the cpp to webassembly in the 'build_wasm.sh' script
|
@ -7,6 +7,27 @@ function App() {
|
||||
const [randomNum, setRandomNum] = useState(null);
|
||||
const [rng, setRng] = useState(null)
|
||||
|
||||
const [nums, setNums] = useState(null);
|
||||
const [matrixRows, setMatrixRows] = useState(null)
|
||||
const max = (2**32)-1;
|
||||
|
||||
const rows = 500;
|
||||
const cols = 500;
|
||||
|
||||
const newNums = () => {
|
||||
|
||||
const newMatrixRows = []
|
||||
for(let i=0; i<rows; i++){
|
||||
const rowItems = [];
|
||||
for(let ii=0; ii<cols; ii++){
|
||||
rowItems.push(rng.generate()/max);
|
||||
}
|
||||
newMatrixRows.push(rowItems)
|
||||
}
|
||||
setMatrixRows(newMatrixRows)
|
||||
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
createModule().then((module) => {
|
||||
setRng(new module.mt19937(5489))
|
||||
@ -31,15 +52,39 @@ function App() {
|
||||
<span className='text-md'>Loading...</span>
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<div>
|
||||
<div className='flex flex-row justify-center'>
|
||||
<span>{randomNum ? randomNum : "Generate a number below"}</span>
|
||||
</div>
|
||||
<div className='flex flex-row justify-center'>
|
||||
<button onClick={() => {generateRandom()}}>Generate</button>
|
||||
</div>
|
||||
<button onClick={() => {newNums()}}>Generate</button>
|
||||
{matrixRows ?(
|
||||
<div>
|
||||
{matrixRows.map((row) => {
|
||||
return (
|
||||
<div key={row[0]+row[1]} className="flex flex-row">
|
||||
{
|
||||
row.map((item) => {
|
||||
return (
|
||||
<div key={item} className="w-[2px] h-[2px]"
|
||||
style={{
|
||||
backgroundColor: `rgba(0,0,0,${item.toFixed(2)}`
|
||||
}}
|
||||
></div>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
) : (
|
||||
<span>Loading...</span>
|
||||
)
|
||||
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
)}
|
||||
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user