Skip to content

Commit

Permalink
Moved helper functions to utils + moved detB closer to where it's used.
Browse files Browse the repository at this point in the history
  • Loading branch information
martinberoiz committed Dec 28, 2019
1 parent cae107b commit 5b8fb6e
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 144 deletions.
156 changes: 12 additions & 144 deletions automix.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,26 +53,10 @@

#define NMODELS_MAX 15
#define Lkmaxmax 30
#define tpi 6.283185307179586477
#define pi 3.141592653589793238
#define logrtpi 0.5 * log(tpi)
#define logrtpi 0.3990899342 // 0.5 * log(2.0 * pi)

/* --- Internal functions (described below) ----------------- */

void gauss(double *z, int n);

void rt(double *z, int n, int dof);

void chol(int n, double **B);

void perm(double *work, int n);

double ltprob(int dof, double z);

double lnormprob(int n, int l, double **mu_k, double ***B_k, double *datai);

double det(int n, int l, double ***B_k);

int read_mixture_params(char *fname, int kmax, int *model_dims, double **sig,
int *Lk, double **lambda, double ***mu, double ****B);

Expand Down Expand Up @@ -206,14 +190,12 @@ int main(int argc, char *argv[]) {
double **lambda = (double **)malloc(nmodels * sizeof(double *));
double ***mu = (double ***)malloc(nmodels * sizeof(double **));
double ****B = (double ****)malloc(nmodels * sizeof(double ***));
double **detB = (double **)malloc(nmodels * sizeof(double *));
double **sig = (double **)malloc(nmodels * sizeof(double *));
for (int k = 0; k < nmodels; k++) {
int mdim = model_dims[k];
lambda[k] = (double *)malloc(Lkmaxmax * sizeof(double));
mu[k] = (double **)malloc(Lkmaxmax * sizeof(double *));
B[k] = (double ***)malloc(Lkmaxmax * sizeof(double **));
detB[k] = (double *)malloc(Lkmaxmax * sizeof(double));
sig[k] = (double *)malloc(mdim * sizeof(double));
for (int i = 0; i < Lkmaxmax; i++) {
mu[k][i] = (double *)malloc(mdim * sizeof(double));
Expand Down Expand Up @@ -311,7 +293,6 @@ int main(int argc, char *argv[]) {
}
fprintf(fpl, "\n");
}
detB[k1][l1] = det(mdim, l1, B[k1]);
}
}
fflush(NULL);
Expand Down Expand Up @@ -359,6 +340,17 @@ int main(int argc, char *argv[]) {
double *Znkk = (double *)malloc(mdim_max * sizeof(double));
double *propk = (double *)malloc(nmodels * sizeof(double));
double *pk = (double *)malloc(nmodels * sizeof(double));
double **detB = (double **)malloc(nmodels * sizeof(double *));
for (int k = 0; k < nmodels; k++) {
detB[k] = (double *)malloc(Lkmaxmax * sizeof(double));
}
for (int k1 = 0; k1 < nmodels; k1++) {
int Lkk = Lk[k1];
int mdim = model_dims[k1];
for (int l1 = 0; l1 < Lkk; l1++) {
detB[k1][l1] = det(mdim, l1, B[k1]);
}
}

get_rwm_init(k, mdim, theta);

Expand Down Expand Up @@ -695,130 +687,6 @@ int main(int argc, char *argv[]) {
return 0;
}

void gauss(double *z, int n) {
/* Uses Box mueller method to simulate n N(0,1) variables and stores them
in z */

int n1;
double u, v;

n1 = n - 1;
for (int i = 0; i < n1; i += 2) {
u = sqrt(-2.0 * log(sdrand()));
v = tpi * sdrand();
z[i] = u * sin(v);
z[i + 1] = u * cos(v);
}
if (fmod(n, 2) < 0.5) {
return;
} else {
u = sqrt(-2.0 * log(sdrand()));
v = tpi * sdrand();
z[n - 1] = u * sin(v);
}
return;
}

void rt(double *z, int n, int dof) {
/* Simulates n random t variable with dof degrees of freedom
by simulating standard normals and chi-squared random variables.
Chi-squared rvs simulated by rgamma function that simulates random gamma
variables (see gammafns file for details).
If dof is 0 return n gaussian random variables instead.
*/

gauss(z, n);
if (dof > 0) {
double s = 0.5 * dof;
double denom = sqrt(rgamma(s) / s);
for (int j1 = 0; j1 < n; j1++) {
z[j1] /= denom;
}
}
return;
}

void chol(int n, double **A) {
/* Performs cholesky decompositon of A and returns result in the
same matrix - adapted from PJG Fortran function*/

for (int j1 = 0; j1 < n; j1++) {
double sum = A[j1][j1];
for (int j2 = 0; j2 < j1; j2++) {
sum -= pow(A[j1][j2], 2);
}
A[j1][j1] = sqrt(sum);

for (int j2 = j1 + 1; j2 < n; j2++) {
sum = A[j2][j1];
for (int j3 = 0; j3 < j1; j3++) {
sum -= A[j2][j3] * A[j1][j3];
}
A[j2][j1] = sum / A[j1][j1];
}
}
}

void perm(double *work, int n) {
/* Randomly permutes the n-dim work vector */

for (int i = 0; i < (n - 1); i++) {
int j = i + (int)((n - i) * sdrand());
if (j != i) {
double temp = work[j];
work[j] = work[i];
work[i] = temp;
}
}
return;
}

double ltprob(int dof, double z) {
/* Evaluates the log of p.d.f. of a t variable with dof degrees of freedom
at point z */

double constt =
loggamma(0.5 * (dof + 1)) - loggamma(0.5 * dof) - 0.5 * log(dof * pi);
double out = constt - 0.5 * (dof + 1) * log(1.0 + pow(z, 2.0) / dof);
return out;
}

double lnormprob(int n, int l, double **mu_k, double ***B_k, double *datai) {
/* Evaluates log of p.d.f. for a multivariate normal for model
k, of dimension n, component l. The summary of means and
sqrt of cov matrices (for all models and all component)
are supplied in mu and B */

double work[n];

for (int i = 0; i < n; i++) {
work[i] = datai[i] - mu_k[l][i];
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < i; j++) {
(work[i]) -= B_k[l][i][j] * work[j];
}
(work[i]) /= B_k[l][i][i];
}
double out = 0.0;
for (int i = 0; i < n; i++) {
out += (work[i] * work[i]);
}
out = -0.5 * out - (n / 2.0) * log(tpi) - log(det(n, l, B_k));
return out;
}

double det(int n, int l, double ***B_k) {

/* Evaluates the determinant of a matrix in B corresponding to model k,
component l. */
double out = 1.0;
for (int i = 0; i < n; i++) {
out *= B_k[l][i][i];
}
return out;
}

int read_mixture_params(char *fname, int nmodels, int *model_dims, double **sig,
int *Lk, double **lambda, double ***mu, double ****B) {
/* Check user has supplied mixture parameters if trying to use mode 1.
Expand Down
127 changes: 127 additions & 0 deletions utils.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#include "utils.h"
#include <math.h>
#define DOUB
/* Combined congruential and Tauseworthe generators from SuperDuper
* package. Should work on machines with unsigned long of at least 32
* bits. JC and JT must be initialized to values with 0 < JC < 2^32 and
Expand Down Expand Up @@ -803,3 +806,127 @@ double rgamma(double s) {

return out;
}

void gauss(double *z, int n) {
/* Uses Box mueller method to simulate n N(0,1) variables and stores them
in z */

int n1;
double u, v;

n1 = n - 1;
for (int i = 0; i < n1; i += 2) {
u = sqrt(-2.0 * log(sdrand()));
v = 2.0 * M_PI * sdrand();
z[i] = u * sin(v);
z[i + 1] = u * cos(v);
}
if (fmod(n, 2) < 0.5) {
return;
} else {
u = sqrt(-2.0 * log(sdrand()));
v = 2.0 * M_PI * sdrand();
z[n - 1] = u * sin(v);
}
return;
}

void rt(double *z, int n, int dof) {
/* Simulates n random t variable with dof degrees of freedom
by simulating standard normals and chi-squared random variables.
Chi-squared rvs simulated by rgamma function that simulates random gamma
variables (see gammafns file for details).
If dof is 0 return n gaussian random variables instead.
*/

gauss(z, n);
if (dof > 0) {
double s = 0.5 * dof;
double denom = sqrt(rgamma(s) / s);
for (int j1 = 0; j1 < n; j1++) {
z[j1] /= denom;
}
}
return;
}

void chol(int n, double **A) {
/* Performs cholesky decompositon of A and returns result in the
same matrix - adapted from PJG Fortran function*/

for (int j1 = 0; j1 < n; j1++) {
double sum = A[j1][j1];
for (int j2 = 0; j2 < j1; j2++) {
sum -= pow(A[j1][j2], 2);
}
A[j1][j1] = sqrt(sum);

for (int j2 = j1 + 1; j2 < n; j2++) {
sum = A[j2][j1];
for (int j3 = 0; j3 < j1; j3++) {
sum -= A[j2][j3] * A[j1][j3];
}
A[j2][j1] = sum / A[j1][j1];
}
}
}

void perm(double *work, int n) {
/* Randomly permutes the n-dim work vector */

for (int i = 0; i < (n - 1); i++) {
int j = i + (int)((n - i) * sdrand());
if (j != i) {
double temp = work[j];
work[j] = work[i];
work[i] = temp;
}
}
return;
}

double ltprob(int dof, double z) {
/* Evaluates the log of p.d.f. of a t variable with dof degrees of freedom
at point z */

double constt =
loggamma(0.5 * (dof + 1)) - loggamma(0.5 * dof) - 0.5 * log(dof * M_PI);
double out = constt - 0.5 * (dof + 1) * log(1.0 + pow(z, 2.0) / dof);
return out;
}

double lnormprob(int n, int l, double **mu_k, double ***B_k, double *datai) {
/* Evaluates log of p.d.f. for a multivariate normal for model
k, of dimension n, component l. The summary of means and
sqrt of cov matrices (for all models and all component)
are supplied in mu and B */

double work[n];

for (int i = 0; i < n; i++) {
work[i] = datai[i] - mu_k[l][i];
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < i; j++) {
(work[i]) -= B_k[l][i][j] * work[j];
}
(work[i]) /= B_k[l][i][i];
}
double out = 0.0;
for (int i = 0; i < n; i++) {
out += (work[i] * work[i]);
}
out = -0.5 * out - (n / 2.0) * log(2.0 * M_PI) - log(det(n, l, B_k));
return out;
}

double det(int n, int l, double ***B_k) {

/* Evaluates the determinant of a matrix in B corresponding to model k,
component l. */
double out = 1.0;
for (int i = 0; i < n; i++) {
out *= B_k[l][i][i];
}
return out;
}
7 changes: 7 additions & 0 deletions utils.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
void gauss(double *z, int n);
void rt(double *z, int n, int dof);
void chol(int n, double **B);
void perm(double *work, int n);
double ltprob(int dof, double z);
double lnormprob(int n, int l, double **mu_k, double ***B_k, double *datai);
double det(int n, int l, double ***B_k);
/* Combined congruential and Tauseworthe generators from SuperDuper
* package. Should work on machines with unsigned long of at least 32
* bits. JC and JT must be initialized to values with 0 < JC < 2^32 and
Expand Down

0 comments on commit 5b8fb6e

Please sign in to comment.