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

Tim Behrens's avatar
Tim Behrens committed
    Mark Jenkinson & Mark Woolrich & Christian Beckmann & Tim Behrens, FMRIB Image Analysis Group
Christian Beckmann's avatar
Christian Beckmann committed

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

/*  CCOPYRIGHT  */

// Miscellaneous maths functions

#define NOMINMAX

#include <cstdlib>
#include <cmath>
Christian Beckmann's avatar
Christian Beckmann committed
#include "miscmaths.h"
Mark Woolrich's avatar
Mark Woolrich committed
#include "miscprob.h"
Christian Beckmann's avatar
Christian Beckmann committed
#include "stdlib.h"
#include "newmatio.h"
Christian Beckmann's avatar
Christian Beckmann committed
namespace MISCMATHS {

  // The following lines are ignored by the current SGI compiler
  //  (version egcs-2.91.57)
  // A temporary fix of including the std:: in front of all abs() etc
  //  has been done for now
Christian Beckmann's avatar
Christian Beckmann committed
  using std::abs;
  using std::sqrt;
  using std::exp;
  using std::log;
  //  using std::pow;
  using std::atan2;
Mark Jenkinson's avatar
Mark Jenkinson committed

  string size(const Matrix& mat)
  {
    string str = num2str(mat.Nrows())+"*"+num2str(mat.Ncols());
        
    return str;
  }



Mark Jenkinson's avatar
Mark Jenkinson committed
  float Sinc(const float x) {
    if (fabs(x)<1e-9) {
      return 1-x*x*M_PI*M_PI/6.0;
    } else {
      return sin(M_PI*x)/(M_PI*x);
    }
  }

  double Sinc(const double x) {
    if (fabs(x)<1e-9) {
      return 1-x*x*M_PI*M_PI/6.0;
    } else {
      return sin(M_PI*x)/(M_PI*x);
    }
  }


Christian Beckmann's avatar
Christian Beckmann committed
  // General string/IO functions

  bool isnum(const string& str)
  {
    // assumes that initial whitespace has been removed
    if (isdigit(str[0])) return true;
    if ( (str[0]=='-') || (str[0]=='+') || (str[0]=='.') )  return true;
    return false;
  }
    
  string skip_alpha(ifstream& fs) 
  {
    string cline;
    while (!fs.eof()) {
      getline(fs,cline);
      cline += " "; // force extra entry in parsing
      istringstream ss(cline.c_str());
Christian Beckmann's avatar
Christian Beckmann committed
      string cc="";
      ss >> cc;
      if (isnum(cc)) {
	fs.seekg(-((int)cline.size()),ios::cur);
	return cline;
      }
    }
    return "";
  }

  ReturnMatrix read_ascii_matrix(int nrows, int ncols, const string& filename)
  {
    return read_ascii_matrix(filename,nrows,ncols);
  }


  ReturnMatrix read_ascii_matrix(const string& filename, int nrows, int ncols)
  {
    Matrix mat(nrows,ncols);
    mat = 0.0;
  
    if ( filename.size()<1 ) return mat;
    ifstream fs(filename.c_str());
    if (!fs) { 
      cerr << "Could not open matrix file " << filename << endl;
      return mat;
    }
    mat = read_ascii_matrix(fs,nrows,ncols);
    fs.close();
    mat.Release();
    return mat;
  }

  ReturnMatrix read_ascii_matrix(int nrows, int ncols, ifstream& fs)
  {
    return read_ascii_matrix(fs, nrows, ncols);
  }

  ReturnMatrix read_ascii_matrix(ifstream& fs, int nrows, int ncols)
  {
    Matrix mat(nrows,ncols);
    mat = 0.0;
    string ss="";
  
    ss = skip_alpha(fs);
    for (int r=1; r<=nrows; r++) {
      for (int c=1; c<=ncols; c++) {
	if (!fs.eof()) {
	  fs >> ss;
	  while ( !isnum(ss) && !fs.eof() ) {
	    fs >> ss;
	  }
Christian Beckmann's avatar
Christian Beckmann committed
	}
      }
    }
    mat.Release();
    return mat;
  }

  
  ReturnMatrix read_ascii_matrix(const string& filename)
  {
    Matrix mat;
    if ( filename.size()<1 ) return mat;
    ifstream fs(filename.c_str());
    if (!fs) { 
      cerr << "Could not open matrix file " << filename << endl;
      mat.Release();
      return mat;
    }
    mat = read_ascii_matrix(fs);
    fs.close();
    mat.Release();
    return mat;
  }


  ReturnMatrix read_ascii_matrix(ifstream& fs)
  {
    int rcount=0, cmax=0;
    string cline;
    // skip initial non-numeric lines
    //  and count the number of columns in the first numeric line
    cline = skip_alpha(fs);
    cline += " ";
    {
      istringstream ss(cline.c_str());
Christian Beckmann's avatar
Christian Beckmann committed
      string cc="";
      while (!ss.eof()) {
	cmax++;
	ss >> cc;
      }
    }
    cmax--;

Christian Beckmann's avatar
Christian Beckmann committed
      getline(fs,cline);
      cline += " "; // force extra entry in parsing
      istringstream ss(cline.c_str());
Christian Beckmann's avatar
Christian Beckmann committed
      string cc="";
      ss >> cc;
      if (!isnum(cc)) break;  // stop processing when non-numeric line found
      rcount++;  // add new row to matrix
    // now know the size of matrix
    fs.clear();
    fs.seekg(0,ios::beg);    
    return read_ascii_matrix(fs,rcount,cmax);

Christian Beckmann's avatar
Christian Beckmann committed
  }

#define BINFLAG 42

  ReturnMatrix read_binary_matrix(const string& filename)
  {
    Matrix mat;
    if ( filename.size()<1 ) return mat;
    ifstream fs(filename.c_str(), ios::in | ios::binary);
    if (!fs) { 
      cerr << "Could not open matrix file " << filename << endl;
Christian Beckmann's avatar
Christian Beckmann committed
      return mat;
    }
    mat = read_binary_matrix(fs);
    fs.close();
    mat.Release();
    return mat;
  }


  ReturnMatrix read_binary_matrix(ifstream& fs)
  {
    bool swapbytes = false;
    unsigned int testval;
Christian Beckmann's avatar
Christian Beckmann committed
    // test for byte swapping
    fs.read((char*)&testval,sizeof(testval));
    if (testval!=BINFLAG) {
      swapbytes = true;
      Swap_Nbytes(1,sizeof(testval),&testval);
      if (testval!=BINFLAG) { 
	cerr << "Unrecognised binary matrix file format" << endl;
	Matrix mres;
	mres.Release();
	return mres;
      }
Christian Beckmann's avatar
Christian Beckmann committed
    }

    // read matrix dimensions (num rows x num cols)
Christian Beckmann's avatar
Christian Beckmann committed
    fs.read((char*)&ival,sizeof(ival));
    // ignore the padding (reserved for future use)
    fs.read((char*)&ival,sizeof(ival));
    if (swapbytes) Swap_Nbytes(1,sizeof(ival),&ival);
Christian Beckmann's avatar
Christian Beckmann committed
    nx = ival;
    fs.read((char*)&ival,sizeof(ival));
    if (swapbytes) Swap_Nbytes(1,sizeof(ival),&ival);
Christian Beckmann's avatar
Christian Beckmann committed
    ny = ival;

    // set up and read matrix (rows fast, cols slow)
Christian Beckmann's avatar
Christian Beckmann committed
    Matrix mres(nx,ny);
    for (unsigned int y=1; y<=ny; y++) {
      for (unsigned int x=1; x<=nx; x++) {
Christian Beckmann's avatar
Christian Beckmann committed
	fs.read((char*)&val,sizeof(val));
	if (swapbytes) Swap_Nbytes(1,sizeof(val),&val);
Christian Beckmann's avatar
Christian Beckmann committed
	mres(x,y)=val;
      }
    }
    
    mres.Release();
    return mres;
  }


  // WRITE FUNCTIONS //


  int write_ascii_matrix(const string& filename, const Matrix& mat, 
			 int precision)
  {
    return write_ascii_matrix(mat, filename, precision);
  }

  int write_ascii_matrix(const Matrix& mat, const string& filename, 
			 int precision)
  {
    Tracer tr("write_ascii_matrix");
    if ( (filename.size()<1) ) return -1;
    ofstream fs(filename.c_str());
    if (!fs) { 
      cerr << "Could not open file " << filename << " for writing" << endl;
      return -1;
    }
    int retval = write_ascii_matrix(mat,fs,precision);
    fs.close();
    return retval;
  }

  int write_ascii_matrix(ofstream& fs, const Matrix& mat, 
			 int precision)
  {
    return write_ascii_matrix(mat, fs, precision);
  }
  
  int write_ascii_matrix(const Matrix& mat, ofstream& fs, int precision)
  {
    for (int i=1; i<=mat.Nrows(); i++) {
      for (int j=1; j<=mat.Ncols(); j++) {
	if (precision>0)  { 
	  fs.setf(ios::scientific | ios::showpos); 
	  fs.precision(precision+7);  
	  fs.precision(precision); } 
	fs << mat(i,j) << "  ";
      }
      fs << endl;
    }
    return 0;
  }
  
  int write_vest(string p_fname, const Matrix& x, int precision)
     { return write_vest(x,p_fname,precision); } 

  int write_vest(const Matrix& x, string p_fname, int precision)
  {
    ofstream out;
    out.open(p_fname.c_str(), ios::out);
    
    if(!out)
      {
	cerr << "Unable to open " << p_fname << endl;
	return -1;
      }

    out << "! VEST-Waveform File" << endl;
    out << "/NumWaves\t" << x.Ncols() << endl;
    out << "/NumPoints\t" << x.Nrows() << endl;
    out << "/Skip" << endl;
    out << endl << "/Matrix" << endl;

    int retval = write_ascii_matrix(x, out, precision);

    out.close();

    return retval;
  }


  int write_binary_matrix(const Matrix& mat, const string& filename)
  {
    Tracer tr("write_binary_matrix");
    if ( (filename.size()<1) ) return -1;
    ofstream fs(filename.c_str(), ios::out | ios::binary);
    if (!fs) { 
      cerr << "Could not open file " << filename << " for writing" << endl;
      return -1;
    }
    int retval = write_binary_matrix(mat,fs);
    fs.close();
    return retval;
  }


  int write_binary_matrix(const Matrix& mat, ofstream& fs)
  {
Christian Beckmann's avatar
Christian Beckmann committed

    ival = BINFLAG;
    fs.write((char*)&ival,sizeof(ival));
    ival = 0;  // padding (reserved for future use)
    fs.write((char*)&ival,sizeof(ival));
Christian Beckmann's avatar
Christian Beckmann committed
    ival = mat.Nrows();
    fs.write((char*)&ival,sizeof(ival));
    ival = mat.Ncols();
    fs.write((char*)&ival,sizeof(ival));

    nx = mat.Nrows();
    ny = mat.Ncols();

    double val;
    for (unsigned int y=1; y<=ny; y++) {
      for (unsigned int x=1; x<=nx; x++) {
Christian Beckmann's avatar
Christian Beckmann committed
	val = mat(x,y);
	fs.write((char*)&val,sizeof(val));
      }
    }

    return 0;
  }


  // General mathematical functions

  int round(int x) { return x; }

  int round(float x) 
    { 
      if (x>0.0) return ((int) (x+0.5));
      else       return ((int) (x-0.5));
    }

   int round(double x) 
   { 
     if (x>0.0) return ((int) (x+0.5));
     else       return ((int) (x-0.5));
Tim Behrens's avatar
Tim Behrens committed
  
  double rounddouble(double x){
    return ( floor(x+0.5));
  }
Christian Beckmann's avatar
Christian Beckmann committed
  int periodicclamp(int x, int x1, int x2)
   {
     if (x2<x1) return periodicclamp(x,x2,x1);
     int d = x2-x1+1;
     int xp = x-x1;
     if (xp>=0) {
       return (xp % d) + x1;
     } else {
       xp = xp + d + std::abs(xp/d)*d;
       assert(xp>0);
       return periodicclamp(xp + d + std::abs(xp/d)*d,x1,x2);
     }
   }

  ColumnVector cross(const ColumnVector& a, const ColumnVector& b)
    {
      Tracer tr("cross");
      ColumnVector ans(3);
      ans(1) = a(2)*b(3) - a(3)*b(2);
      ans(2) = a(3)*b(1) - a(1)*b(3);
      ans(3) = a(1)*b(2) - a(2)*b(1);
      return ans;
    }


  ColumnVector cross(const Real *a, const Real *b)
    {
      Tracer tr("cross");
      ColumnVector a1(3), b1(3);
      a1 << a;
      b1 << b;
      return cross(a1,b1);
    }


  double norm2(const ColumnVector& x)
    {
      return std::sqrt(x.SumSquare());
    }

  double norm2(double a, double b, double c)
    {
	return a*a + b*b + c*c;
    }

  float norm2(float a, float b, float c)
    {
	return a*a + b*b + c*c;
    }
Christian Beckmann's avatar
Christian Beckmann committed

  int Identity(Matrix& m)
    {
      Tracer tr("Identity");
      m=0.0;
      for (int j=1; j<=m.Nrows(); j++)
	m(j,j)=1.0;
      return 0;
    }

  ReturnMatrix Identity(int num)
    {
      Tracer tr("Identity");
      Matrix eye(num,num);
      Identity(eye);
      eye.Release();
      return eye;
    }


  int diag(Matrix& m, const float diagvals[])
    {
      Tracer tr("diag");
      m=0.0;
      for (int j=1; j<=m.Nrows(); j++)
	m(j,j)=diagvals[j-1];
      return 0;
    }


Mark Woolrich's avatar
Mark Woolrich committed
  int diag(DiagonalMatrix& m, const ColumnVector& diagvals)
    {
      Tracer tr("diag");

      m.ReSize(diagvals.Nrows());
      m=0.0;
      for (int j=1; j<=diagvals.Nrows(); j++)
	m(j)=diagvals(j);
      return 0;
    }

Christian Beckmann's avatar
Christian Beckmann committed
  int diag(Matrix& m, const ColumnVector& diagvals)
    {
      Tracer tr("diag");
Mark Woolrich's avatar
Mark Woolrich committed
      
      m.ReSize(diagvals.Nrows(),diagvals.Nrows());
Christian Beckmann's avatar
Christian Beckmann committed
      m=0.0;
Mark Woolrich's avatar
Mark Woolrich committed
      for (int j=1; j<=diagvals.Nrows(); j++)
Christian Beckmann's avatar
Christian Beckmann committed
	m(j,j)=diagvals(j);
      return 0;
    }

  ReturnMatrix diag(const Matrix& Mat)
    {
      Tracer tr("diag");
      if(Mat.Ncols()==1){
	Matrix retmat(Mat.Nrows(),Mat.Nrows());
	diag(retmat,Mat);
	retmat.Release();
	return retmat;}
      else{
	int mindim = Min(Mat.Ncols(),Mat.Nrows());
	Matrix retmat(mindim,1);
	for(int ctr=1; ctr<=mindim;ctr++){
	  retmat(ctr,1)=Mat(ctr,ctr);
	}
	retmat.Release();
	return retmat;
      }
    }

  ReturnMatrix pinv(const Matrix& mat)
    {
      // calculates the psuedo-inverse using SVD
      // note that the right-pinv(x') = pinv(x).t()
Christian Beckmann's avatar
Christian Beckmann committed
      Tracer tr("pinv");
      DiagonalMatrix D;
      Matrix U, V;
      SVD(mat,D,U,V);
      float tol;
      tol = MaximumAbsoluteValue(D) * Max(mat.Nrows(),mat.Ncols()) * 1e-16;
      for (int n=1; n<=D.Nrows(); n++) {
	if (fabs(D(n,n))>tol)  D(n,n) = 1.0/D(n,n);
      }
      Matrix pinv = V * D * U.t();
      pinv.Release();
      return pinv;
    }

Loading
Loading full blame...