Skip to content
Snippets Groups Projects
miscprob.cc 5.88 KiB
Newer Older
Christian Beckmann's avatar
Christian Beckmann committed
/*  miscprob.cc

    Christian Beckmann & Mark Woolrich, FMRIB Image Analysis Group

    Copyright (C) 1999-2000 University of Oxford  */

/*  CCOPYRIGHT  */

// Miscellaneous maths functions that rely on libprob

#include "miscprob.h"
#include "stdlib.h"
#include "newmatio.h"
#include <iostream>
Christian Beckmann's avatar
Christian Beckmann committed

using namespace NEWMAT;

namespace MISCMATHS {

ReturnMatrix unifrnd(const int dim1, const int dim2, const float start, const float end)
{
  int tdim = dim2;
  double tmpD=1.0;
  if(tdim<0){tdim=dim1;}
  Matrix res(dim1,tdim);
  for (int mc=1; mc<=res.Ncols(); mc++) {
    for (int mr=1; mr<=res.Nrows(); mr++) {
      tmpD = (rand()+1)/double(RAND_MAX+2.0);
      res(mr,mc)=(tmpD)*(end-start)+start;
      //drand(&tmpD);
      //res(mr,mc)=(tmpD-1)*(end-start)+start;
Christian Beckmann's avatar
Christian Beckmann committed
    }
  }

  res.Release();
  return res;
}

  // SJ. Generates a sample from a distribution given the histogram
int distribrnd(const ColumnVector& histo){
  int res=1;
  ColumnVector cumsum(histo.Nrows());
  float sum=0.0;
  for(int k=1;k<=histo.Nrows();k++){
    sum += histo(k);
    cumsum(k) = sum;
  }
  float U=rand()/float(RAND_MAX);
  U *= sum;
  for(int k=1;k<=histo.Nrows();k++){
    if(U<cumsum(k)){
      res = k;
      break;
    }
  }
  return res;
}

Christian Beckmann's avatar
Christian Beckmann committed
ReturnMatrix normrnd(const int dim1, const int dim2, const float mu, const float sigma)
{
  int tdim = dim2;
  double tmpD=1.0;
  if(tdim<0){tdim=dim1;}
  Matrix res(dim1,tdim);
  for (int mc=1; mc<=res.Ncols(); mc++) {
    for (int mr=1; mr<=res.Nrows(); mr++) {
      tmpD = (rand()+1)/double(RAND_MAX+2.0);
      res(mr,mc)=ndtri(tmpD)*sigma+mu ;
      //drand(&tmpD);
      //res(mr,mc)=ndtri(tmpD-1)*sigma+mu ;
Christian Beckmann's avatar
Christian Beckmann committed
    }
  }

  res.Release();

  return res;
}

Stephen Smith's avatar
Stephen Smith committed
ReturnMatrix normpdf(const RowVector& vals, const float mu, const float var)
Christian Beckmann's avatar
Christian Beckmann committed
{
  RowVector res(vals);
  for (int mc=1; mc<=res.Ncols(); mc++){
Stephen Smith's avatar
Stephen Smith committed
    res(mc) = std::exp(-0.5*(std::pow(vals(mc)-mu,2)/var))*std::pow(2*M_PI*var,-0.5);
Christian Beckmann's avatar
Christian Beckmann committed
  }

  res.Release();
  return res;
}
float normpdf(const ColumnVector& vals, const ColumnVector& mu, const SymmetricMatrix& sigma)
{
  float res;
  LogAndSign ld=(2*M_PI*sigma).LogDeterminant();

  res =  std::exp(-0.5*(
			((vals-mu).t()*sigma.i()*(vals-mu)).AsScalar()
			+ld.LogValue()
			));
  return res;
}
ReturnMatrix normpdf(const Matrix& vals, const ColumnVector& mu, const SymmetricMatrix& sigma)
{
  RowVector res(vals);
  LogAndSign ld = (2*M_PI*sigma).LogDeterminant();
  Matrix isigma = sigma.i();

  for (int mc=1; mc<=res.Ncols(); mc++){
    res(mc) = std::exp( -0.5*(
			      ((vals.Column(mc)-mu).t()*isigma*(vals.Column(mc)-mu)).AsScalar() 
			      +ld.LogValue()
			      ));
  }
  res.Release();
  return res;
}
Christian Beckmann's avatar
Christian Beckmann committed
ReturnMatrix normcdf(const RowVector& vals, const float mu, const float var)
{
  RowVector res(vals);
  RowVector tmp;
  tmp = (vals-mu)/std::sqrt(var);
  for (int mc=1; mc<=res.Ncols(); mc++){
    res(mc) = ndtr(tmp(mc));
  }

  res.Release();
  return res;
}

Stephen Smith's avatar
Stephen Smith committed
ReturnMatrix gammacdf(const RowVector& vals, const float mu, const float var)
Christian Beckmann's avatar
Christian Beckmann committed
{
  RowVector res(vals);
  res=0;
Stephen Smith's avatar
Stephen Smith committed
  if((mu>0)&&(var>0)){
    float b = std::pow(mu,2)/var;
    float a = mu/var;  
Christian Beckmann's avatar
Christian Beckmann committed
    for (int mc=1; mc<=res.Ncols(); mc++){
      if(vals(mc)>0)
	res(mc) = gdtr(a,b,vals(mc));
    }
  }
  res.Release();
  return res;
}

Stephen Smith's avatar
Stephen Smith committed
ReturnMatrix gammapdf(const RowVector& vals, const float mu, const float var)
Christian Beckmann's avatar
Christian Beckmann committed
{
  RowVector res(vals);
  res=0;
Stephen Smith's avatar
Stephen Smith committed
  if((mu>0)&&(var>0.00001)){
    float a = std::pow(mu,2)/var;
    float b = mu/var;
Christian Beckmann's avatar
Christian Beckmann committed
    float c = lgam(a);
    if(std::abs(c) < 150){
      for (int mc=1; mc<=res.Ncols(); mc++){
	if(vals(mc)>0.000001){
	  res(mc) = std::exp(a*std::log(b) + 
			     (a-1) * std::log(vals(mc)) 
			     - b*vals(mc) - c);
	}
      }
    }
  }
  res.Release();
  return res;
}


Stephen Smith's avatar
Stephen Smith committed
ReturnMatrix normpdf(const RowVector& vals, const RowVector& mu, const RowVector& var)
Christian Beckmann's avatar
Christian Beckmann committed
{
  Matrix res(mu.Ncols(),vals.Ncols());
  for (int mc=1; mc<=res.Ncols(); mc++){
    for (int mr=1; mr<=res.Nrows(); mr++){
Stephen Smith's avatar
Stephen Smith committed
      res(mr,mc) = std::exp(-0.5*(std::pow(vals(mc)-mu(mr),2)/var(mr)))*std::pow(2*M_PI*var(mr),-0.5);
Christian Beckmann's avatar
Christian Beckmann committed
    }
  }

  res.Release();
  return res;
}


Mark Woolrich's avatar
Mark Woolrich committed
ReturnMatrix mvnrnd(const RowVector& mu, const SymmetricMatrix& covar, int nsamp) 
Christian Beckmann's avatar
Christian Beckmann committed
{     
//   Matrix eig_vec; 
//   DiagonalMatrix eig_val;
//   EigenValues(covar,eig_val,eig_vec);

//   Matrix ret = ones(nsamp, 1)*mu + dnormrandm(nsamp,mu.Ncols())*sqrt(eig_val)*eig_vec.t();
  Mvnormrandm mvn(mu, covar);

  return mvn.next(nsamp);
}

// Saad: Wishart and inverseWishart Random Generator
ReturnMatrix wishrnd(const SymmetricMatrix& sigma,const int dof){
  // compute cholesky factor for sigma
  LowerTriangularMatrix L = Cholesky(sigma);

  // for small degrees of freedom, use the definition
  int n = sigma.Nrows();
  Matrix X;
  if(dof <= 81+n ){
    X.ReSize(dof,n);
    X = normrnd(dof,n) * L.t();
  }
  // otherwise, use Smith & Hocking procedure
  else{
    X.ReSize(n,n);
    Matrix A(n,n);
    for(int i=1;i<=n;i++){
      Gamma G((dof-i+1)/2);
      G.Set(rand()/float(RAND_MAX));
      for(int j=1;j<=n;j++){
	if     (i>j) { A(i,j) = 0; }
	else if(i<j) { A(i,j) = normrnd(1,1).AsScalar(); }
	else         { A(i,j) = std::sqrt(2*G.Next()); }
      }
    }
    X = A * L.t();
  }

  SymmetricMatrix res(n);
  res << X.t() * X;

  res.Release();
  return res;
}
ReturnMatrix iwishrnd(const SymmetricMatrix& sigma,const int dof){
  // assumes inv-Wishart(sigma.i(),dof)

  SymmetricMatrix res;
  res = wishrnd(sigma,dof);
  res = res.i();

  res.Release();
  return res;
}

ReturnMatrix perms(const int n){
  if(n<=1){
    Matrix P(1,1);
    P << n;
    P.Release();
    return P;
  }
  Matrix Q = perms(n-1);  // recursive calls
  int m = Q.Nrows();
  Matrix P(n*m,n);
  for(int i=1;i<=m;i++){
    P(i,1)=n;
    for(int j=1;j<=Q.Ncols();j++)
      P(i,j+1)=Q(i,j);
  }
  for(int i=n-1;i>=1;i--){
    int jj=1;
    for(int j=(n-i)*m+1;j<=(n-i+1)*m;j++){
      P(j,1)=i;
      for(int k=1;k<=n-1;k++){
	P(j,k+1)= (Q(jj,k)==i) ? n : Q(jj,k);
      }
      jj++;
    } 
  }
  P.Release();
  return P;
}

Christian Beckmann's avatar
Christian Beckmann committed
}