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";
|
||||
|
||||
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);
|
||||
|
4
main.cpp
4
main.cpp
@ -58,10 +58,10 @@ namespace splat {
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
|
||||
int seed = 13928981231238123;
|
||||
int seed = 9472161;
|
||||
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){
|
||||
std::cout << generator->getName() << ": \n";
|
||||
|
@ -1,113 +1,103 @@
|
||||
#include "../rng.h"
|
||||
#include "./incomplete_gamma.h"
|
||||
#include <iostream>
|
||||
#define PI 3.1415926535897932384626433832795028841971693993751
|
||||
|
||||
double igam(double a, double x) {
|
||||
double maxlog = 7.09782712893383996732E2;
|
||||
double machep = 1.11022302462515654042E-16;
|
||||
double big = 4.503599627370496e15;
|
||||
double biginv = 2.22044604925031308085e-16;
|
||||
// using the power series proves to be very fast and very accurate.
|
||||
double igam(double s, double z){
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// if (x>1.0 && x>a){
|
||||
// return 1.0 - igamc(a,x);
|
||||
// }
|
||||
double sum = 0;
|
||||
|
||||
ax = a * std::log(x) - x - std::lgamma(a);
|
||||
int rounds = 10000000;
|
||||
|
||||
if (ax < -maxlog){
|
||||
// std::cout << "max log error on incomplete gamma function\n";
|
||||
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;
|
||||
|
||||
ax = std::exp(ax);
|
||||
double sum = 0;
|
||||
|
||||
r = a;
|
||||
c = 1.0;
|
||||
ans = 1.0;
|
||||
do {
|
||||
r+=1;
|
||||
c*= x/r;
|
||||
ans +=c;
|
||||
}while(c/ans > machep);
|
||||
auto func = [a](double t) {
|
||||
double ret = std::pow(t, a-1) * std::exp(-t);
|
||||
if(std::isinf(ret)) ret=0;
|
||||
return ret;
|
||||
};
|
||||
|
||||
return ans * ax/a;
|
||||
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);
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
// This uses the trapezium approximation which is less accurate and slower
|
||||
double igam_trapezoid(double a, double x){
|
||||
|
||||
// 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;
|
||||
if( (x<=0 || a<=0)){
|
||||
return 0.0;
|
||||
}
|
||||
double parts = 100000000;
|
||||
|
||||
// reimann sum the lower incomplete gamma function
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
sum+=func(0);
|
||||
sum+=func(x);
|
||||
for(int i=1; i<parts; i++){
|
||||
sum+=2*func((x/parts)*i);
|
||||
}
|
||||
double ans = ((x/parts)/2)*sum;
|
||||
|
||||
return (1/std::tgamma(a))*ans;
|
||||
}
|
||||
|
@ -39,11 +39,11 @@ namespace splat {
|
||||
|
||||
|
||||
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[1]-(0.5776*num_matrices)),2)/(0.5776*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);
|
||||
}
|
||||
}
|
||||
|
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