#include "misc.h" #include #include /* for size_t */ int isclose(double a, double b, double rel_tol, double abs_tol) { /* Returns 1 if a and b are "close". This algorithm is taken from Python's * math.isclose() function. * * See https://www.python.org/dev/peps/pep-0485/. */ return fabs(a-b) <= fmax(rel_tol*fmax(fabs(a),fabs(b)),abs_tol); } int allclose(double *a, double *b, size_t n, double rel_tol, double abs_tol) { /* Returns 1 if all the elements of a and b are "close". This algorithm is * taken from Python's math.isclose() function. * * See https://www.python.org/dev/peps/pep-0485/. */ size_t i; for (i = 0; i < n; i++) { if (!isclose(a[i],b[i],rel_tol,abs_tol)) return 0; } return 1; } double logsumexp(double *a, size_t n) { /* Returns the log of the sum of the exponentials of the array `a`. * * This function is designed to reduce underflow when the exponentials of * `a` are very small, for example when computing probabilities. */ size_t i; double amax, sum; amax = a[0]; for (i = 0; i < n; i++) { if (a[i] > amax) amax = a[i]; } sum = 0.0; for (i = 0; i < n; i++) { sum += exp(a[i]-amax); } sum = log(sum); return amax + sum; } double norm(double x, double mu, double sigma) { /* Returns the PDF for a gaussian random variable with mean `mu` and * standard deviation `sigma`. */ return exp(-pow(x-mu,2)/(2*pow(sigma,2)))/(sqrt(2*M_PI)*sigma); } double norm_cdf(double x, double mu, double sigma) { /* Returns the CDF for a gaussian random variable with mean `mu` and * standard deviation `sigma`. */ return erfc(-(x-mu)/(sqrt(2)*sigma))/2.0; }