Re implemented incomplete gamma
This commit is contained in:
parent
015c069462
commit
74cc9d37da
@ -17,7 +17,7 @@ TEST_CASE("igam function"){
|
|||||||
std::cout << " Splat CodeTests\n";
|
std::cout << " Splat CodeTests\n";
|
||||||
|
|
||||||
auto igamtest = [](double a, double x, double req) {
|
auto igamtest = [](double a, double x, double req) {
|
||||||
REQUIRE(igam(a,x)== doctest::Approx(req).epsilon(0.00000000000001));
|
REQUIRE(igam(a,x)== doctest::Approx(req).epsilon(0.00000000001));
|
||||||
};
|
};
|
||||||
{
|
{
|
||||||
igamtest(0.5, 0.0, 0.0);
|
igamtest(0.5, 0.0, 0.0);
|
||||||
|
4
main.cpp
4
main.cpp
@ -58,10 +58,10 @@ namespace splat {
|
|||||||
|
|
||||||
int main(int argc, const char * argv[]) {
|
int main(int argc, const char * argv[]) {
|
||||||
|
|
||||||
int seed = 13928981231238123;
|
int seed = 9472161;
|
||||||
int blocksgenerated = 1000000;
|
int blocksgenerated = 1000000;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<splat::PRNG>> generators = splat::getAllGenerators(1238124);
|
std::vector<std::unique_ptr<splat::PRNG>> generators = splat::getAllGenerators(seed);
|
||||||
|
|
||||||
for(const std::unique_ptr<splat::PRNG> &generator : generators){
|
for(const std::unique_ptr<splat::PRNG> &generator : generators){
|
||||||
std::cout << generator->getName() << ": \n";
|
std::cout << generator->getName() << ": \n";
|
||||||
|
@ -1,113 +1,103 @@
|
|||||||
#include "../rng.h"
|
#include "../rng.h"
|
||||||
#include "./incomplete_gamma.h"
|
#include "./incomplete_gamma.h"
|
||||||
|
#include <iostream>
|
||||||
|
#define PI 3.1415926535897932384626433832795028841971693993751
|
||||||
|
|
||||||
double igam(double a, double x) {
|
// using the power series proves to be very fast and very accurate.
|
||||||
double maxlog = 7.09782712893383996732E2;
|
double igam(double s, double z){
|
||||||
double machep = 1.11022302462515654042E-16;
|
|
||||||
double big = 4.503599627370496e15;
|
|
||||||
double biginv = 2.22044604925031308085e-16;
|
|
||||||
|
|
||||||
double ans, ax, c, r;
|
|
||||||
|
if( (s<=0 || z<=0)){
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rounds = 50;
|
||||||
|
|
||||||
|
double sum = 0;
|
||||||
|
|
||||||
|
for(int k=0; k<rounds; k++){
|
||||||
|
double toadd = (std::pow(z,s)*std::exp(-z)*std::pow(z,k));
|
||||||
|
for(int i=0; i<=k; i++){
|
||||||
|
toadd/=(s+i);
|
||||||
|
}
|
||||||
|
sum+=toadd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return sum / std::tgamma(s);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// because we are dealing with regularized incomplete gamma function, we can minus one from the lower
|
||||||
|
double igamc(double s, double z){
|
||||||
|
return 1-igam(s,z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// alternative expansion found on wikipedia
|
||||||
|
double igam_chg(double a, double x){
|
||||||
|
|
||||||
|
if( (x<=0 || a<=0)){
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double sum = 0;
|
||||||
|
|
||||||
|
int rounds = 10000000;
|
||||||
|
|
||||||
|
for(int i=0; i<rounds; i++){
|
||||||
|
sum+=(std::pow(-1,i)/std::tgamma(i+1))*(std::pow(x,a+i)/(a+i));
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// This uses simpsons composite rule and passed at a 0.01 accuracy test but I want better.
|
||||||
|
double igam_simpsons(double a, double x){
|
||||||
|
if( (x<=0 || a<=0)){
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
int parts = 10000000;
|
||||||
|
|
||||||
|
double sum = 0;
|
||||||
|
|
||||||
|
auto func = [a](double t) {
|
||||||
|
double ret = std::pow(t, a-1) * std::exp(-t);
|
||||||
|
if(std::isinf(ret)) ret=0;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
double h = x/parts;
|
||||||
|
for(int i=1; i<=parts/2; ++i){
|
||||||
|
sum+= (func((2*i-2)*h) + 4*func(((2*i)-1)*h) + func((2*i)*h));
|
||||||
|
}
|
||||||
|
return (sum*h)/(std::tgamma(a)*3.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This uses the trapezium approximation which is less accurate and slower
|
||||||
|
double igam_trapezoid(double a, double x){
|
||||||
|
|
||||||
if( (x<=0 || a<=0)){
|
if( (x<=0 || a<=0)){
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
double parts = 100000000;
|
||||||
|
|
||||||
// if (x>1.0 && x>a){
|
// reimann sum the lower incomplete gamma function
|
||||||
// return 1.0 - igamc(a,x);
|
double sum = 0;
|
||||||
// }
|
auto func = [a](double t) {
|
||||||
|
double ret = std::pow(t, a-1) * std::exp(-t);
|
||||||
|
if(std::isinf(ret)) ret=0;
|
||||||
|
// std::cout << std::format("func({}) -> {}", t,ret);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
ax = a * std::log(x) - x - std::lgamma(a);
|
|
||||||
|
|
||||||
if (ax < -maxlog){
|
sum+=func(0);
|
||||||
// std::cout << "max log error on incomplete gamma function\n";
|
sum+=func(x);
|
||||||
return 0.0;
|
for(int i=1; i<parts; i++){
|
||||||
}
|
sum+=2*func((x/parts)*i);
|
||||||
|
}
|
||||||
|
double ans = ((x/parts)/2)*sum;
|
||||||
|
|
||||||
ax = std::exp(ax);
|
return (1/std::tgamma(a))*ans;
|
||||||
|
|
||||||
r = a;
|
|
||||||
c = 1.0;
|
|
||||||
ans = 1.0;
|
|
||||||
do {
|
|
||||||
r+=1;
|
|
||||||
c*= x/r;
|
|
||||||
ans +=c;
|
|
||||||
}while(c/ans > machep);
|
|
||||||
|
|
||||||
return ans * ax/a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// regularized left tail of incomplete gamma
|
|
||||||
// Q(s, x) = \frac{1}{\Gamma(s)} \int_x^\infty t^{s-1} e^{-t} \, dt
|
|
||||||
double igamc(double a, double x){
|
|
||||||
return 1-igam(a,x);
|
|
||||||
// double maxlog = 7.09782712893383996732E2;
|
|
||||||
// double machep = 1.11022302462515654042E-16;
|
|
||||||
// double big = 4.503599627370496e15;
|
|
||||||
// double biginv = 2.22044604925031308085e-16;
|
|
||||||
|
|
||||||
|
|
||||||
// if(x<=0 || a<=0){
|
|
||||||
// return 1.0;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if( (x < 1.0 ) || ( x < a)){
|
|
||||||
// std::cout << "bad\n";
|
|
||||||
// return 1.0 - igam(a,x);
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// double ax = a * std::log(x) - std::lgamma(a);
|
|
||||||
|
|
||||||
// // maxlog?
|
|
||||||
// if(ax < -maxlog){
|
|
||||||
// std::cout << "max log error on incomplete gamma function\n";
|
|
||||||
// return 0.0;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// ax = std::exp(ax);
|
|
||||||
|
|
||||||
// double y = 1.0 - a;
|
|
||||||
// double z = x + y + 1.0;
|
|
||||||
// double c = 0.0;
|
|
||||||
// double pkm2 = 1.0;
|
|
||||||
// double qkm2 = x;
|
|
||||||
// double pkm1 = x + 1.0;
|
|
||||||
// double qkm1 = z * x;
|
|
||||||
// double ans = pkm1/qkm1;
|
|
||||||
|
|
||||||
// double pk,qk,r,t,yc;
|
|
||||||
|
|
||||||
// t = 1.0;
|
|
||||||
|
|
||||||
// do {
|
|
||||||
// c+=1.0;
|
|
||||||
// y+=1.0;
|
|
||||||
// z+=2.0;
|
|
||||||
// yc = y*c;
|
|
||||||
// pk = pkm1 * z - pkm2 * yc;
|
|
||||||
// qk = qkm1 * z - qkm2 * yc;
|
|
||||||
// if (qk !=0){
|
|
||||||
// r = pk/qk;
|
|
||||||
// t = std::fabs((ans-r)/r);
|
|
||||||
// ans = r;
|
|
||||||
// }else{
|
|
||||||
// t = 1.0;
|
|
||||||
// }
|
|
||||||
// pkm2 = pkm1;
|
|
||||||
// pkm1 = pk;
|
|
||||||
// qkm2 = qkm1;
|
|
||||||
// qkm1 = qk;
|
|
||||||
// if(std::fabs(pk) > big){
|
|
||||||
// pkm2 *= biginv;
|
|
||||||
// pkm1 *= biginv;
|
|
||||||
// qkm2 *= biginv;
|
|
||||||
// qkm1 *= biginv;
|
|
||||||
// }
|
|
||||||
// std::cout << ans << "-\n";
|
|
||||||
// } while (t>machep);
|
|
||||||
|
|
||||||
// return ans * ax;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -39,11 +39,11 @@ namespace splat {
|
|||||||
|
|
||||||
|
|
||||||
double x2obs = 0;
|
double x2obs = 0;
|
||||||
std::cout << "debug: "<< counts[0] << ","<<counts[1]<<","<<counts[2]<<"\n";
|
// std::cout << "debug: "<< counts[0] << ","<<counts[1]<<","<<counts[2]<<"\n";
|
||||||
x2obs += std::pow((counts[0]-(0.2888*num_matrices)),2)/(0.2888*num_matrices);
|
x2obs += std::pow((counts[0]-(0.2888*num_matrices)),2)/(0.2888*num_matrices);
|
||||||
x2obs += std::pow((counts[1]-(0.5776*num_matrices)),2)/(0.5776*num_matrices);
|
x2obs += std::pow((counts[1]-(0.5776*num_matrices)),2)/(0.5776*num_matrices);
|
||||||
x2obs += std::pow((counts[2]-(0.1336*num_matrices)),2)/(0.1336*num_matrices);
|
x2obs += std::pow((counts[2]-(0.1336*num_matrices)),2)/(0.1336*num_matrices);
|
||||||
std::cout << "debug: "<<x2obs << "\n";
|
//std::cout << "debug: "<<x2obs << "\n";
|
||||||
return igam(1, x2obs/2);
|
return igam(1, x2obs/2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
17
randomness_tests/discrete_fourier.h
Normal file
17
randomness_tests/discrete_fourier.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../rng.h"
|
||||||
|
#include "./rngtest.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace splat {
|
||||||
|
|
||||||
|
class discrete_fourier : public RNGTEST {
|
||||||
|
public:
|
||||||
|
discrete_fourier(std::vector<std::bitset<32>> &testData);
|
||||||
|
std::string getName() override;
|
||||||
|
double runTest(std::vector<std::bitset<32>> &data) override;
|
||||||
|
};
|
||||||
|
}
|
BIN
splat_test
BIN
splat_test
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user