diff --git a/Makefile b/Makefile
index 4a24c07a30161264ac5d90da4ec81964124e2b6f..40e5696794c08517424f92677213d4585cd3cf9b 100644
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@ PROJNAME = miscmaths
 USRINCFLAGS = -I${INC_NEWMAT} -I${INC_PROB}
 USRLDFLAGS = -L${LIB_NEWMAT} -L${LIB_PROB}
 
-OBJS = miscmaths.o optimise.o miscprob.o kernel.o histogram.o base2z.o t2z.o f2z.o volume.o volumeseries.o minimize.o
+OBJS = miscmaths.o optimise.o miscprob.o kernel.o histogram.o base2z.o t2z.o f2z.o volume.o volumeseries.o minimize.o cspline.o
 
 LIBS = -lutils -lnewmat -lprob -lm
 
diff --git a/cspline.cc b/cspline.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f3a4e7efa4d9732cac7d10561076dfd5421814b0
--- /dev/null
+++ b/cspline.cc
@@ -0,0 +1,303 @@
+/*  cspline
+   
+    Cubic spline fitting and interpolation
+    
+    Tim Behrens, FMRIB Image Analysis Group
+
+    Copyright (C) 1999-2000 University of Oxford  */
+
+/*  CCOPYRIGHT  */
+
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <unistd.h>
+
+#include "newmatap.h"
+#include "newmatio.h"
+#include "miscmaths/miscmaths.h"
+#include "cspline.h"
+
+#define WANT_STREAM
+#define WANT_MATH
+
+using namespace NEWMAT;
+using namespace std;
+
+///////////////////////////////////////////////////////
+
+
+
+namespace MISCMATHS{
+
+  //  void Cspline::Cspline(){}
+  
+  void Cspline::set(ColumnVector& pnodes,ColumnVector& pvals){
+    nodes=pnodes;vals=pvals;
+    fitted=false;
+    n=vals.Nrows();
+  }
+  void Cspline::set(ColumnVector& pnodes, Matrix& pcoefs){
+    nodes=pnodes;coefs=pcoefs;
+    fitted=false;
+    n=vals.Nrows();
+  }
+  
+  void Cspline::diff(const ColumnVector& x, ColumnVector& dx ){
+    // dx should be of length length(x)-1
+    dx.ReSize(x.Nrows()-1);
+    for(int i=2;i<=x.Nrows();i++){
+      dx(i-1)=x(i)-x(i-1);
+    }						    
+  }
+  
+  
+  void Cspline::fit(){
+    if(vals.Nrows()<4){
+      cerr<<"Cspline::fit - You have less than 4 data pts for spline fitting."<<endl;
+      exit(-1);
+    }
+    if(nodes.Nrows()!=vals.Nrows()){
+      cerr<<"Nodes and VALS must be the same length in your spline"<<endl;
+      exit(-1);
+    }
+    int n=vals.Nrows();
+    ColumnVector s(n);
+    ColumnVector dx,dy,dydx(n-1);
+    diff(nodes,dx);
+    diff(vals,dy);
+    
+    for(int i=1;i<=n-1;i++){
+      dydx(i)=dy(i)/dx(i);
+    }
+    ColumnVector b(n);
+    b=0;
+    for(int i=2;i<=b.Nrows()-1;i++){
+      b(i)=3*(dx(i)*dydx(i-1)+dx(i-1)*dydx(i));
+    }
+    
+    float x31=nodes(3)-nodes(1),xn=nodes(n)-nodes(n-2);
+    b(1)=((dx(1)+2*x31)*dx(2)*dydx(1)+dx(1)*dx(1)*dydx(2))/x31;
+    b(n)=(dx(n-1)*dx(n-1)*dydx(n-2)+(2*xn+dx(n-1))*dx(n-2)*dydx(n-1))/xn;
+    
+    Matrix tridiag(n,n);
+    tridiag=0;
+    ColumnVector  y3(n);
+    for(int j=2;j<=n-1;j++){
+      tridiag(j,j-1)=dx(j);
+      tridiag(j,j)=2*(dx(j)+dx(j-1));
+      tridiag(j,j+1)=dx(j-1);
+    }
+    tridiag(1,1)=dx(2);tridiag(1,2)=x31;
+    tridiag(n,n-1)=xn;tridiag(n,n)=dx(n-2);
+    s=tridiag.i()*b; 
+    
+    
+    ColumnVector d(n-1),c(n-1);
+    for(int j=1;j<n;j++){
+      d(j)=(s(j)+s(j+1)-2*dydx(j))/dx(j);
+      c(j)=(dydx(j)-s(j))/dx(j)-d(j);
+    }
+    
+    coefs.ReSize(n-1,4);
+    for(int j=1;j<n;j++){
+      coefs(j,1)=vals(j);
+      coefs(j,2)=s(j);
+      coefs(j,3)=c(j);
+      coefs(j,4)=d(j)/dx(j);
+    }
+    cerr<<coefs<<endl;
+ }
+  
+ 
+  float Cspline::interpolate(float xx) const{
+    // nodes must be monotonically increasing. I don't check this. 
+    // On your head be it if you don't.
+    if(nodes.Nrows()!=vals.Nrows()){
+      cerr<<"Cspline:interpolate: Nodes and Vals should be the same length"<<endl;
+      exit(-1);
+    }
+
+    float ret;
+    if(!fitted){
+      cerr<<"Cspline::interpolate - Cspline has not been fitted"<<endl;
+      exit(-1);
+    }
+    else{
+      
+      bool stop=false;
+      int ind=0;
+      
+      if(xx<nodes(1)){
+	ind=1;
+      }
+      else if(xx>nodes(nodes.Nrows())){
+	ind=nodes.Nrows()-1;
+      }
+      else{
+	for(int i=1;i<nodes.Nrows();i++){
+	  if(!stop){
+	    if( (nodes(i)<=xx) && (nodes(i+1)>xx) ){
+	      ind=i;
+	      stop=true;
+	    }
+	  }
+	}
+      }
+      
+       float a=coefs(ind,1);
+      float b=coefs(ind,2);
+      float c=coefs(ind,3);
+      float d=coefs(ind,4);
+      float t=xx-nodes(ind);
+      ret=a+b*t+c*t*t+d*t*t*t;
+      
+    }
+    return ret;  
+}
+
+  float Cspline::interpolate(float xx, int ind) const{
+    float ret;
+    if(!fitted){
+      cerr<<"Cspline::interpolate - Cspline has not been fitted"<<endl;
+      exit(-1);
+    }
+    else{
+      if(ind>n-1){
+	cerr<<"Cspline::interpolate - segment index is greater than number of segments - exiting"<<endl;
+	exit(-1);
+      }
+      else if(ind<1){
+      	cerr<<"Cspline::interpolate - segment index is less than 1 - exiting"<<endl;
+	exit(-1);
+      }
+      float a=coefs(ind,1);
+      float b=coefs(ind,2);
+      float c=coefs(ind,3);
+      float d=coefs(ind,4);
+      float t=xx-nodes(ind);
+      ret=a+b*t+c*t*t+d*t*t*t;
+    }
+    return ret;
+  }
+
+
+  ColumnVector Cspline::interpolate(const ColumnVector& x) const{
+    // nodes must be monotonically increasing. I don't check this. 
+    // On your head be it if you don't.
+    
+    if(nodes.Nrows()!=vals.Nrows()){
+      cerr<<"Cspline::interpolate -  Nodes and Vals should be the same length"<<endl;
+      exit(-1);
+    }
+    
+    ColumnVector ret(x.Nrows());  
+
+    if(!fitted){
+      cerr<<"Cspline::interpolate - Cspline has not been fitted"<<endl;
+      exit(-1);
+    }
+    else{
+
+      for(int xnum=1;xnum<=x.Nrows();xnum++){
+	
+	float xx=x(xnum);
+	
+	bool stop=false;
+	int ind=0;
+	
+	if(xx<nodes(1)){
+	  ind=1;
+	}
+	else if(xx>=nodes(nodes.Nrows())){
+	  ind=nodes.Nrows()-1;
+	}
+	else{
+	  for(int i=1;i<nodes.Nrows();i++){
+	    if(!stop){
+	      if( (nodes(i)<=xx) && (nodes(i+1)>xx) ){
+		ind=i;
+		stop=true;
+	      }
+	    }
+	  }
+	}
+
+	float a=coefs(ind,1);
+	float b=coefs(ind,2);
+	float c=coefs(ind,3);
+	float d=coefs(ind,4);
+	float t=xx-nodes(ind);
+	ret(xnum)=a+b*t+c*t*t+d*t*t*t;
+      }
+    }
+    return ret;   
+  }
+  
+ 
+  ColumnVector Cspline::interpolate(const ColumnVector& x,const ColumnVector& indvec) const{
+    // nodes must be monotonically increasing. I don't check this. 
+    // On your head be it if you don't.
+    
+    if(nodes.Nrows()!=vals.Nrows()){
+      cerr<<"Cspline::interpolate - Nodes and Vals should be the same length"<<endl;
+      exit(-1);
+    }
+    
+    ColumnVector ret(x.Nrows());  
+
+    if(!fitted){
+      cerr<<"Cspline::interpolate - Cspline has not been fitted"<<endl;
+      exit(-1);
+    }
+    else{
+      for(int xnum=1;xnum<=x.Nrows();xnum++){
+	
+	float xx=x(xnum);
+	
+	int ind=int(indvec(xnum));
+
+	float a=coefs(ind,1);
+	float b=coefs(ind,2);
+	float c=coefs(ind,3);
+	float d=coefs(ind,4);
+	float t=xx-nodes(ind);
+	ret(xnum)=a+b*t+c*t*t+d*t*t*t;
+      }
+    }
+    return ret;   
+  }
+  
+
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cspline.h b/cspline.h
new file mode 100644
index 0000000000000000000000000000000000000000..5c231f258feb94da4a26a58f95f1e9a3c782c94c
--- /dev/null
+++ b/cspline.h
@@ -0,0 +1,74 @@
+/*  cspline
+    
+    Cubic spline fitting and interpolation
+    Tim Behrens, FMRIB Image Analysis Group
+
+    Copyright (C) 1999-2000 University of Oxford  */
+
+/*  CCOPYRIGHT  */
+#if !defined(__cspline_h)
+#define __cspline_h
+
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <unistd.h>
+
+#include "newmatap.h"
+#include "newmatio.h"
+#include "miscmaths/miscmaths.h"
+
+#define WANT_STREAM
+#define WANT_MATH
+
+using namespace NEWMAT;
+using namespace std;
+///////////////////////////////////////////////////////
+
+
+namespace MISCMATHS { 
+  class Cspline{
+  public: 
+    Cspline();
+    Cspline(ColumnVector& pnodes,ColumnVector& pvals):
+      nodes(pnodes),
+      vals(pvals),
+      n(nodes.Nrows())
+    {
+      fit();
+      fitted=true;
+    }
+
+    Cspline(ColumnVector& pnodes, Matrix& pcoefs) : 
+      nodes(pnodes),
+      coefs(pcoefs),
+      n(nodes.Nrows())
+    { fitted=true;}
+
+    ~Cspline(){
+      fitted=false;
+    };
+    
+    void set(ColumnVector& pnodes,ColumnVector& pvals);
+    void set(ColumnVector& pnodes, Matrix& pcoefs);
+    
+    void fit();
+    float interpolate(float xx) const;
+    float interpolate(float xx,int ind) const;
+    ColumnVector interpolate(const ColumnVector& x) const;
+    ColumnVector interpolate(const ColumnVector& x, const ColumnVector& indvec) const;
+    
+  protected:
+
+    bool fitted;
+    ColumnVector nodes;
+    ColumnVector vals;
+    Matrix coefs;
+    int n;
+    void diff(const ColumnVector& x, ColumnVector& dx );
+
+  };
+}
+
+
+#endif