parent
497d34a4af
commit
c81720e7a9
@ -1,3 +1,5 @@ |
||||
# magic_stats |
||||
|
||||
A simple bit of code in multiple languages that lets you calculate useful statistics without storing every sample. |
||||
|
||||
Look in cpp/ for a C++ version. More to come. |
||||
|
||||
@ -0,0 +1 @@ |
||||
set makeprg=meson\ compile\ -C\ . |
||||
@ -0,0 +1,42 @@ |
||||
all: build |
||||
|
||||
reset: |
||||
ifeq '$(OS)' 'Windows_NT' |
||||
powershell -executionpolicy bypass .\scripts\reset_build.ps1
|
||||
else |
||||
sh -x ./scripts/reset_build.sh
|
||||
endif |
||||
|
||||
build: |
||||
meson compile -j 10 -C builddir
|
||||
|
||||
release_build: |
||||
meson --wipe builddir -Db_ndebug=true --buildtype release
|
||||
meson compile -j 10 -C builddir
|
||||
|
||||
debug_build: |
||||
meson setup --wipe builddir -Db_ndebug=true --buildtype debugoptimized
|
||||
meson compile -j 10 -C builddir
|
||||
|
||||
test: build |
||||
./builddir/fuc2it
|
||||
|
||||
run: build test |
||||
ifeq '$(OS)' 'Windows_NT' |
||||
powershell "cp ./builddir/fuc2it.exe ."
|
||||
./fuc2it
|
||||
else |
||||
./builddir/fuc2it
|
||||
endif |
||||
|
||||
debug: build |
||||
gdb --nx -x .gdbinit --ex run --args builddir/fuc2it
|
||||
|
||||
debug_run: build |
||||
gdb --nx -x .gdbinit --batch --ex run --ex bt --ex q --args builddir/fuc2it
|
||||
|
||||
clean: |
||||
meson compile --clean -C builddir
|
||||
|
||||
debug_test: build |
||||
gdb --nx -x .gdbinit --ex run --args builddir/fuc2it -e
|
||||
@ -0,0 +1,38 @@ |
||||
project('sol2_test', 'cpp', |
||||
version: '0.1.0', |
||||
default_options: [ |
||||
'cpp_std=c++23', |
||||
# 'cpp_args=-D_GLIBCXX_DEBUG=1 -D_GLIBCXX_DEBUG_PEDANTIC=1', |
||||
]) |
||||
|
||||
# use this for common options only for our executables |
||||
cpp_args=[ |
||||
'-Wno-unused-parameter', |
||||
'-Wno-unused-function', |
||||
'-Wno-unused-variable', |
||||
'-Wno-unused-but-set-variable', |
||||
'-Wno-deprecated-declarations', |
||||
'-Wno-maybe-uninitialized', # only because of error in release_build |
||||
] |
||||
link_args=[] |
||||
# these are passed as override_defaults |
||||
exe_defaults = [ 'warning_level=2', 'werror=false'] |
||||
|
||||
fmt = subproject('fmt').get_variable('fmt_dep') |
||||
fuc2 = subproject('fuc2').get_variable('fuc2_dep') |
||||
|
||||
dependencies = [fmt, fuc2] |
||||
|
||||
sources = [ |
||||
] |
||||
|
||||
executable('fuc2it', [ |
||||
'src/stats.cpp', |
||||
'tests/stats_tests.cpp', |
||||
'tests/main.cpp', |
||||
], |
||||
cpp_args: cpp_args, |
||||
link_args: link_args, |
||||
include_directories: include_directories('src'), |
||||
override_options: exe_defaults, |
||||
dependencies: dependencies) |
||||
@ -0,0 +1,7 @@ |
||||
mv .\subprojects\packagecache . |
||||
rm -recurse -force .\subprojects\,.\builddir\ |
||||
mkdir subprojects |
||||
mv .\packagecache .\subprojects\ |
||||
mkdir builddir |
||||
cp wraps\*.wrap subprojects\ |
||||
meson setup --default-library=static --prefer-static builddir |
||||
@ -0,0 +1,10 @@ |
||||
#!/usr/bin/env bash |
||||
|
||||
mv -f ./subprojects/packagecache . |
||||
rm -rf subprojects builddir |
||||
mkdir subprojects |
||||
mv -f packagecache ./subprojects/ && true |
||||
mkdir builddir |
||||
cp wraps/*.wrap subprojects/ |
||||
# on OSX you can't do this with static |
||||
meson setup --default-library=static --prefer-static builddir |
||||
@ -0,0 +1,41 @@ |
||||
#include "stats.hpp" |
||||
#include <fmt/core.h> |
||||
#include <numeric> |
||||
#include <numbers> |
||||
|
||||
void Stats::dump(std::string msg) |
||||
{ |
||||
fmt::println("{}: sum: {}, sumsq: {}, n: {}, " |
||||
"min: {}, max: {}, mean: {}, stddev: {}", |
||||
msg, sum, sumsq, n, min, max, mean(), |
||||
stddev()); |
||||
} |
||||
|
||||
// WARNING: got this code from google AI. PROBABLY BULLSHIT
|
||||
void Stats::t_test(Stats& other) { |
||||
double n1 = this->n; |
||||
double n2 = other.n; |
||||
|
||||
double mean1 = this->mean(); |
||||
double mean2 = other.mean(); |
||||
|
||||
double var1 = this->variance(); |
||||
double var2 = other.variance(); |
||||
|
||||
// calculate t-stat
|
||||
double delta_mean = mean1 - mean2; |
||||
double pooled_se = std::sqrt((var1 / n1) + (var2 / n2)); |
||||
double t_stat = delta_mean / pooled_se; |
||||
|
||||
// calculate degrees of freedom
|
||||
double num = std::pow((var1 / n1) + (var2 / n2), 2); |
||||
double den = (std::pow(var1 / n1, 2) / (n1 - 1)) + (std::pow(var2 / n2, 2) / (n2 - 1)); |
||||
double df = num / den; |
||||
|
||||
double x = df / (df + t_stat * t_stat); |
||||
|
||||
double p_val = std::tgamma((df + 1.0) / 2.0) / (std::sqrt(df * std::numbers::pi) * std::tgamma(df / 2.0)) * std::pow(1.0 + (t_stat * t_stat) / df, -(df + 1.0) / 2.0); |
||||
|
||||
fmt::println("t_stat={}, df={}, p_val={}", |
||||
t_stat, df, p_val); |
||||
} |
||||
@ -0,0 +1,65 @@ |
||||
#pragma once |
||||
#include <cmath> |
||||
#include <chrono> |
||||
|
||||
struct Stats { |
||||
using TimeBullshit = std::chrono::time_point<std::chrono::high_resolution_clock>; |
||||
|
||||
double sum = 0.0; |
||||
double sumsq = 0.0; |
||||
double n = 0.0; |
||||
double min = 0.0; |
||||
double max = 0.0; |
||||
|
||||
inline void reset() { |
||||
sum = 0.0; |
||||
sumsq = 0.0; |
||||
n = 0.0; |
||||
min = 0.0; |
||||
max = 0.0; |
||||
} |
||||
|
||||
inline double mean() { |
||||
return sum / n; |
||||
} |
||||
|
||||
inline double stddev() { |
||||
return std::sqrt(variance()); |
||||
} |
||||
|
||||
inline double variance() { |
||||
return (sumsq - (sum * sum / n)) / (n - 1); |
||||
} |
||||
|
||||
inline void sample(double s) { |
||||
sum += s; |
||||
sumsq += s * s; |
||||
|
||||
if (n == 0) { |
||||
min = s; |
||||
max = s; |
||||
} else { |
||||
if (min > s) min = s; |
||||
if (max < s) max = s; |
||||
} |
||||
|
||||
n += 1; |
||||
} |
||||
|
||||
inline TimeBullshit time_start() { |
||||
return std::chrono::high_resolution_clock::now(); |
||||
} |
||||
|
||||
inline void sample_time(TimeBullshit start) { |
||||
auto end = std::chrono::high_resolution_clock::now(); |
||||
auto elapsed = std::chrono::duration<double>(end - start); |
||||
|
||||
if(elapsed.count() > 0.0) { |
||||
sample(1.0/elapsed.count()); |
||||
} |
||||
} |
||||
|
||||
void dump(std::string msg=""); |
||||
|
||||
void t_test(Stats& other); |
||||
}; |
||||
@ -0,0 +1,13 @@ |
||||
#include <fuc2/run.hpp> |
||||
|
||||
TEST_SET(stats_tests); |
||||
|
||||
using namespace fuc2; |
||||
|
||||
int main(int argc, char* argv[]) { |
||||
std::vector<fuc2::Set> tests{ |
||||
stats_tests::TESTS, |
||||
}; |
||||
|
||||
return run_tests(tests, argc, argv); |
||||
} |
||||
@ -0,0 +1,20 @@ |
||||
#include <fmt/core.h> |
||||
#include <deque> |
||||
#include <string> |
||||
#include <fuc2/testing.hpp> |
||||
|
||||
using namespace fuc2; |
||||
|
||||
namespace stats_tests { |
||||
|
||||
void test_stats_stuff() { |
||||
CHECK(1 == 1); |
||||
} |
||||
|
||||
fuc2::Set TESTS{ |
||||
.name="stats", |
||||
.tests={ |
||||
TEST(test_stats_stuff), |
||||
} |
||||
}; |
||||
} |
||||
@ -0,0 +1,13 @@ |
||||
[wrap-file] |
||||
directory = fmt-12.0.0 |
||||
source_url = https://github.com/fmtlib/fmt/archive/12.0.0.tar.gz |
||||
source_filename = fmt-12.0.0.tar.gz |
||||
source_hash = aa3e8fbb6a0066c03454434add1f1fc23299e85758ceec0d7d2d974431481e40 |
||||
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/fmt_12.0.0-1/fmt-12.0.0.tar.gz |
||||
patch_filename = fmt_12.0.0-1_patch.zip |
||||
patch_url = https://wrapdb.mesonbuild.com/v2/fmt_12.0.0-1/get_patch |
||||
patch_hash = 307f288ebf3850abf2f0c50ac1fb07de97df9538d39146d802f3c0d6cada8998 |
||||
wrapdb_version = 12.0.0-1 |
||||
|
||||
[provide] |
||||
dependency_names = fmt |
||||
@ -0,0 +1,9 @@ |
||||
[wrap-git] |
||||
directory=fuc2-0.1.0 |
||||
url=https://lcthw.dev/cpp/fuc2.git |
||||
revision=HEAD |
||||
depth=1 |
||||
method=meson |
||||
|
||||
[provide] |
||||
fuc2 = fuc2_dep |
||||
Loading…
Reference in new issue