diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..f8fb9f367d39dcbcbe8efb1959f010fc670701a6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+*.nii
+*.BRIK
+*.HEAD
diff --git a/NODDI_toolbox_v1.01/.DS_Store b/NODDI_toolbox_v1.01/.DS_Store
new file mode 100644
index 0000000000000000000000000000000000000000..6b31e7fe961b6f9db30bb31b0b1c2449b3896fe3
Binary files /dev/null and b/NODDI_toolbox_v1.01/.DS_Store differ
diff --git a/NODDI_toolbox_v1.01/LICENSE.txt b/NODDI_toolbox_v1.01/LICENSE.txt
new file mode 100644
index 0000000000000000000000000000000000000000..0961e7bf0c499b21316d2a136fbeb531e6de9dd7
--- /dev/null
+++ b/NODDI_toolbox_v1.01/LICENSE.txt
@@ -0,0 +1,14 @@
+LICENSE for NODDI matlab toolbox:
+
+The Software is made available for use under the Open Source-approved Artistic Licence 2.0. The Owner draws your attention to the fact that the Software has been developed for and is intended for use in a research environment only. No endorsement can be given for other use including, but not limited to, use in a clinical environment.
+
+External tools included in NODDI matlab toolbox:
+
+1. erfi matlab function
+ * By Per Sundqvist, No license specified
+ * Downloaded from http://www.mathworks.com/matlabcentral/fileexchange/18238-erfi-function
+
+2. PARFOR Progress Monitor v2
+ * BSD license
+ * Downloaded from http://www.mathworks.com/matlabcentral/fileexchange/31673-parfor-progress-monitor-v2
+
diff --git a/NODDI_toolbox_v1.01/ParforProgMonv2/ParforProgMon.m b/NODDI_toolbox_v1.01/ParforProgMonv2/ParforProgMon.m
new file mode 100644
index 0000000000000000000000000000000000000000..a1848d23426c68059605aba303187305a8bbe657
--- /dev/null
+++ b/NODDI_toolbox_v1.01/ParforProgMonv2/ParforProgMon.m
@@ -0,0 +1,63 @@
+% Copyright 2009 The MathWorks, Inc.
+
+classdef ParforProgMon < handle
+
+    properties ( GetAccess = private, SetAccess = private )
+        Port
+        HostName
+    end
+    
+    properties (Transient, GetAccess = private, SetAccess = private)
+        JavaBit
+    end
+    
+    methods ( Static )
+        function o = loadobj( X )
+        % Once we've been loaded, we need to reconstruct ourselves correctly as a
+        % worker-side object.
+            o = ParforProgMon( {X.HostName, X.Port} );
+        end
+    end
+    
+    methods
+        function o = ParforProgMon( s, N, progressStepSize, width, height )
+        % ParforProgMon Build a Parfor Progress Monitor
+        % Use the syntax: ParforProgMon( 'Window Title', N, progressStepSize, width, height )
+        % where N is the number of iterations in the PARFOR loop
+        % progressStepSize indicates after how many iterations progress is shown
+        % width indicates the width of the progress window
+        % height indicates the width of the progress window
+        
+            if nargin == 1 && iscell( s )
+                % "Private" constructor used on the workers
+                o.JavaBit   = ParforProgressMonitor.createWorker( s{1}, s{2} );
+                o.Port      = [];
+            elseif nargin == 5
+                % Normal construction
+                o.JavaBit   = ParforProgressMonitor.createServer( s, N, progressStepSize, width, height );
+                o.Port      = double( o.JavaBit.getPort() );
+                % Get the client host name from pctconfig
+                cfg         = pctconfig;
+                o.HostName  = cfg.hostname;
+            else
+                error( 'Public constructor is: ParforProgressMonitor( ''Text'', N, progressStepSize, width, height )' );
+            end
+        end
+        
+        function X = saveobj( o )
+        % Only keep the Port and HostName
+            X.Port     = o.Port;
+            X.HostName = o.HostName;
+        end
+        
+        function increment( o )
+        % Update the UI
+            o.JavaBit.increment();
+        end
+        
+        function delete( o )
+        % Close the UI
+            o.JavaBit.done();
+        end
+    end
+end
diff --git a/NODDI_toolbox_v1.01/ParforProgMonv2/example.m b/NODDI_toolbox_v1.01/ParforProgMonv2/example.m
new file mode 100644
index 0000000000000000000000000000000000000000..93c348f635d4940e21e886fb16eef9e727650145
--- /dev/null
+++ b/NODDI_toolbox_v1.01/ParforProgMonv2/example.m
@@ -0,0 +1,27 @@
+% ParforProgMon - M object to make ParforProgressMonitor objects easier to
+% use. Create one of these on the client outside your PARFOR loop with a
+% name for the window. Pass it in to the PARFOR loop, and have the workers
+% call "increment" at the end of each iteration. This sends notification
+% back to the client which then updates the UI.
+
+% ParforProgMon Build a Parfor Progress Monitor
+% Use the syntax: ParforProgMon( 'Window Title', N, progressStepSize, width, height )
+% where N is the number of iterations in the PARFOR loop
+% progressStepSize indicates after how many iterations progress is shown
+% width indicates the width of the progress window
+% height indicates the width of the progress window
+
+tic
+N = 500000;
+progressStepSize = 100;
+ppm = ParforProgMon('Example: ', N, progressStepSize, 300, 80);
+
+parfor ii=1:N
+    rand(100,100);
+    if mod(ii,progressStepSize)==0
+        ppm.increment();
+    end
+end
+
+ppm.delete()
+toc
\ No newline at end of file
diff --git a/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$1.class b/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..abc01f9e56564e2bfb9e468e1bddbb8e2751f3f5
Binary files /dev/null and b/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$1.class differ
diff --git a/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgServer$1.class b/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgServer$1.class
new file mode 100644
index 0000000000000000000000000000000000000000..78e99d373bec1f53a4a42594be3fbb6d0c1a0f0a
Binary files /dev/null and b/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgServer$1.class differ
diff --git a/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgServer.class b/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgServer.class
new file mode 100644
index 0000000000000000000000000000000000000000..82801f09c3c4f26ca94e16ecd1849feb1f02c561
Binary files /dev/null and b/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgServer.class differ
diff --git a/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgThing.class b/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgThing.class
new file mode 100644
index 0000000000000000000000000000000000000000..593257c01ca4552b5bdcfc447df3180c874db735
Binary files /dev/null and b/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgThing.class differ
diff --git a/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgWorker.class b/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgWorker.class
new file mode 100644
index 0000000000000000000000000000000000000000..0f2fdff6b99c4575419736c4c265ad7da5aa7b78
Binary files /dev/null and b/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgWorker.class differ
diff --git a/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor.class b/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor.class
new file mode 100644
index 0000000000000000000000000000000000000000..94e4a8acfad0961d9a0da817ffb61eb1a4254b49
Binary files /dev/null and b/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor.class differ
diff --git a/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor.java b/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor.java
new file mode 100644
index 0000000000000000000000000000000000000000..fa7b5654de5d9cf3b6dfc4c11ca59247ce7e89b9
--- /dev/null
+++ b/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor.java
@@ -0,0 +1,198 @@
+import javax.swing.*;
+import java.io.*;
+import java.net.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+// Copyright 2009 The MathWorks, Inc.
+
+public class ParforProgressMonitor {
+
+    /**
+     * Create a "server" progress monitor - this runs on the desktop client and
+     * pops up the progress monitor UI.
+     */
+    public static ProgServer createServer( String s, int N, int progressStepSize, int width, int height )
+        throws IOException {
+        ProgServer ret = new ProgServer( s, N, progressStepSize, width, height );
+        ret.start();
+        return ret;
+    }
+
+    /**
+     * Create a "worker" progress monitor - runs on the remote lab and sends updates
+     */
+    public static ProgWorker createWorker( String host, int port )
+        throws IOException {
+        return new ProgWorker( host, port );
+    }
+
+    /**
+     * Common interface exposed by both objects
+     */
+    public interface ProgThing {
+        public void increment();
+        public void done();
+    }
+
+    /**
+     * The worker-side object. Simply connects to the server to indicate that a
+     * quantum of progress has been made. This is a very basic implementation -
+     * a more sophisticated implementation would use a persistent connection,
+     * and a SocketChannel on the client with a thread doing a select loop and
+     * accepting connections etc.
+     */
+    private static class ProgWorker implements ProgThing {
+        private int fPort;
+        private String fHost;
+        private ProgWorker( String host, int port ) {
+            fHost = host;
+            fPort = port;
+        }
+
+        /**
+         * Connect and disconnect immediately to indicate progress
+         */
+        public void increment() {
+            try {
+                Socket s = new Socket( fHost, fPort );
+                s.close();
+            } catch( Exception e ) {
+                e.printStackTrace();
+            }
+        }
+
+        /**
+         * Nothing for us to do here
+         */
+        public void done() {
+        }
+    }
+
+    /**
+     * The client-side object which pops up a window with a
+     * JProgressBar. Accepts connections from the workers, and then disconnects
+     * them immediately. Beware, the connection backlog of the ServerSocket
+     * might be insufficient.
+     */
+    private static class ProgServer implements Runnable, ProgThing {
+        private JFrame fFrame;
+        private JProgressBar fBar;
+        private ServerSocket fSocket;
+        private int fValue, fN, fStep;
+        private String title;
+        private Thread fThread;
+        private AtomicBoolean fKeepGoing;
+
+        private ProgServer( String s, int N, int progressStepSize, int width, int height ) throws IOException {
+            // The UI
+            fFrame = new JFrame( s );
+            fBar   = new JProgressBar( 0, N );
+            fFrame.getContentPane().add( fBar );
+            fFrame.pack();
+			fFrame.setSize(width,height);
+            fFrame.setLocationRelativeTo( null );
+            fFrame.setVisible( true );
+
+            // How far we are through - requires synchronized access
+            fValue = 0;
+			fN = N;
+			fStep = progressStepSize;
+			title = s;
+
+            // Get an anonymous port
+            fSocket = new ServerSocket( 0 );
+            // Set SO_TIMEOUT so that we don't block forever
+            fSocket.setSoTimeout( 100 );
+
+            // Our background thread
+            fThread = new Thread( this );
+            fThread.setDaemon( true );
+
+            // Used to indicate to fThread when it's time to go
+            fKeepGoing = new AtomicBoolean( true );
+        }
+
+        /**
+         * Don't start the Thread in the constructor
+         */
+        public void start() { fThread.start(); }
+
+        /**
+         * Loop over accepting connections and updating
+         */
+        public void run() {
+            while( fKeepGoing.get() ) {
+                try {
+                    acceptAndIncrement();
+                } catch( Exception e ) {
+                    if( fKeepGoing.get() ) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+        }
+
+        /**
+         * If there's a connection - accept and then disconnect; increment our count.
+         */
+        private void acceptAndIncrement() throws IOException {
+            Socket worker;
+            try {
+                worker = fSocket.accept();
+            } catch( SocketTimeoutException timeout ) {
+                // don't care about timeouts
+                return;
+            }
+            worker.close();
+            increment();
+        }
+
+
+        /**
+         * On the EDT, update the progress bar
+         */
+        private void updateBar( final int newVal ) {
+            SwingUtilities.invokeLater( new Runnable() {
+                    public void run() {
+                        fBar.setValue( fStep*newVal );
+                        double percentage = 100.0*fStep*newVal/fN;
+                        fFrame.setTitle(title + (int)percentage + "% completed.");
+                        if ( newVal == fBar.getMaximum() ) {
+                            done();
+                        }
+                    }
+                } );
+        }
+
+        /**
+         * M-code needs to know which port we got
+         */
+        public int getPort() {
+            return ((InetSocketAddress)fSocket.getLocalSocketAddress()).getPort();
+        }
+
+        /**
+         * Provide public access to this for pool-close PARFORs
+         */
+        public synchronized void increment() {
+            fValue++;
+            updateBar( fValue );
+        }
+
+        /**
+         * Shut it all down
+         */
+        public void done() {
+            fKeepGoing.set( false );
+            try {
+                fSocket.close();
+            } catch( Exception e ) {
+                e.printStackTrace();
+            }
+            fFrame.dispose();
+        }
+    }
+
+    /** This class isn't useful - use the static methods */
+    private ParforProgressMonitor() {}
+}
\ No newline at end of file
diff --git a/NODDI_toolbox_v1.01/ParforProgMonv2/license.txt b/NODDI_toolbox_v1.01/ParforProgMonv2/license.txt
new file mode 100644
index 0000000000000000000000000000000000000000..27fd717279ba6894c2a9ae9b9fb29016e4ec1355
--- /dev/null
+++ b/NODDI_toolbox_v1.01/ParforProgMonv2/license.txt
@@ -0,0 +1,28 @@
+Copyright (c) 2011, Willem-Jan de Goeij
+Copyright (c) 2009, The MathWorks, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are 
+met:
+
+    * Redistributions of source code must retain the above copyright 
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright 
+      notice, this list of conditions and the following disclaimer in 
+      the documentation and/or other materials provided with the distribution
+    * Neither the name of the The MathWorks, Inc. nor the names 
+      of its contributors may be used to endorse or promote products derived 
+      from this software without specific prior written permission.
+      
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/NODDI_toolbox_v1.01/VERSION b/NODDI_toolbox_v1.01/VERSION
new file mode 100644
index 0000000000000000000000000000000000000000..eff316426e0a6bd8cbf00d30be64c9916df10a59
--- /dev/null
+++ b/NODDI_toolbox_v1.01/VERSION
@@ -0,0 +1,2 @@
+This version of the toolbox is extracted from WUZI r1020.
+
diff --git a/NODDI_toolbox_v1.01/fitting/CreateROI.m b/NODDI_toolbox_v1.01/fitting/CreateROI.m
new file mode 100644
index 0000000000000000000000000000000000000000..ee756489ab6458b5f62338e5fb6e20479a1a41c4
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/CreateROI.m
@@ -0,0 +1,83 @@
+function CreateROI(dwifile, maskfile, outputfile)
+%
+% function CreateROI(dwifile, maskfile)
+%
+% This function converts 4-D DWI volume into the data format suitable
+% for subsequent NODDI fitting.
+%
+% Inputs:
+%
+% dwifile: the 4-D DWI volume in NIfTI or Analyze format
+%
+% maskfile: the brain mask volume in NIfTI or Analyze format which
+% specifies the voxels to include for fitting
+%
+% outputfile: the mat file to store the resulting data for subsequent
+% fitting
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+% first check if niftimatlib is available
+if (exist('nifti') ~= 2)
+    error('niftimatlib does not appear to be installed or included in the search path');
+    return;
+end
+
+% load the DWI volume
+fprintf('loading the DWI volume : %s\n', dwifile);
+dwi = nifti(dwifile);
+xsize = dwi.dat.dim(1);
+ysize = dwi.dat.dim(2);
+zsize = dwi.dat.dim(3);
+ndirs = dwi.dat.dim(4);
+
+% convert the data from scanner order to voxel order
+dwi = dwi.dat(:,:,:,:);
+dwi = permute(dwi,[4 1 2 3]);
+
+% load the brain mask volume
+fprintf('loading the brain mask : %s\n', maskfile);
+mask = nifti(maskfile);
+mask = mask.dat(:,:,:);
+
+% create an ROI that is in voxel order and contains just the voxels in the
+% brain mask
+fprintf('creating the output ROI ...\n');
+
+% first get the number of voxels first
+% to more efficiently allocate the memory
+count=0;
+for i=1:xsize
+    for j=1:ysize
+        for k=1:zsize
+            if mask(i,j,k) > 0
+                count = count + 1;
+                mask(i,j,k) = count;
+            end
+        end
+    end
+end
+roi = zeros(count,ndirs);
+idx = zeros(count,3);
+
+% next construct the ROI
+count=0;
+for i=1:xsize
+    for j=1:ysize
+        for k=1:zsize
+            if mask(i,j,k) > 0
+                count = count + 1;
+                roi(count,:) = dwi(:,i,j,k);
+                idx(count,:) = [i j k];
+            end
+        end
+    end
+end
+
+% save the ROI
+fprintf('saving the output ROI as %s\n', outputfile);
+save(outputfile, 'roi', 'mask', 'idx');
+
+disp('done');
+
diff --git a/NODDI_toolbox_v1.01/fitting/DT_DesignMatrix.m b/NODDI_toolbox_v1.01/fitting/DT_DesignMatrix.m
new file mode 100644
index 0000000000000000000000000000000000000000..f27307f899c2d2aa83b2028205ff5c8c18bc2b1c
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/DT_DesignMatrix.m
@@ -0,0 +1,77 @@
+function X=DT_DesignMatrix(protocol)
+% Computes the design matrix for DT fitting using linear least squares.
+%
+% function X=DT_DesignMatrix(protocol)
+%
+% protocol is the acquisition protocol.
+%
+% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
+%
+
+
+GAMMA = 2.675987E8;
+
+if(strcmp(protocol.pulseseq, 'PGSE') || strcmp(protocol.pulseseq, 'STEAM'))
+    modQ = GAMMA*protocol.smalldel'.*protocol.G';
+    q = repmat(modQ, [1,3]).*protocol.grad_dirs;
+    diffTime = (protocol.delta' - protocol.smalldel'/3);
+
+    % Compute the design matrix
+    X = [ones(1, length(q)); -diffTime'.*q(:,1)'.*q(:,1)'; -2*diffTime'.*q(:,1)'.*q(:,2)'; -2*diffTime'.*q(:,1)'.*q(:,3)'; -diffTime'.*q(:,2)'.*q(:,2)'; -2*diffTime'.*q(:,2)'.*q(:,3)'; -diffTime'.*q(:,3)'.*q(:,3)']';
+
+elseif(strcmp(protocol.pulseseq, 'OGSE'))
+    q = protocol.grad_dirs;
+    b = GetB_Values(protocol);
+
+    % Compute the design matrix
+    X = [ones(1, length(q)); -b.*q(:,1)'.*q(:,1)'; -2*b.*q(:,1)'.*q(:,2)'; -2*b.*q(:,1)'.*q(:,3)'; -b.*q(:,2)'.*q(:,2)'; -2*b.*q(:,2)'.*q(:,3)'; -b.*q(:,3)'.*q(:,3)']';
+
+elseif(strcmp(protocol.pulseseq, 'DSE'))
+
+    bValue = GetB_ValuesDSE(protocol.G, protocol.delta1, protocol.delta2, protocol.delta3, protocol.t1, protocol.t2, protocol.t3);
+    
+    % Compute the design matrix
+    X = [ones(1, length(protocol.G)); -bValue.*protocol.grad_dirs(:,1)'.*protocol.grad_dirs(:,1)'; -2*bValue.*protocol.grad_dirs(:,1)'.*protocol.grad_dirs(:,2)'; -2*bValue.*protocol.grad_dirs(:,1)'.*protocol.grad_dirs(:,3)'; -bValue.*protocol.grad_dirs(:,2)'.*protocol.grad_dirs(:,2)'; -2*bValue.*protocol.grad_dirs(:,2)'.*protocol.grad_dirs(:,3)'; -bValue.*protocol.grad_dirs(:,3)'.*protocol.grad_dirs(:,3)']';
+
+elseif(strcmp(protocol.pulseseq, 'FullSTEAM'))
+
+    tdd = protocol.gap1 + protocol.gap2 + protocol.TM + 2*protocol.sdelc + 2*protocol.smalldel/3 + 2*protocol.sdelr;
+    tcc = protocol.TM + 2*protocol.sdelc/3 + 2*protocol.sdelr;
+    trr = protocol.TM + 2*protocol.sdelr/3;
+    tdc = protocol.TM + protocol.sdelc + 2*protocol.sdelr;
+    tdr = protocol.TM + protocol.sdelr;
+    tcr = protocol.TM + protocol.sdelr;
+
+    qdx = protocol.grad_dirs(:,1)'.*protocol.G.*protocol.smalldel;
+    qdy = protocol.grad_dirs(:,2)'.*protocol.G.*protocol.smalldel;
+    qdz = protocol.grad_dirs(:,3)'.*protocol.G.*protocol.smalldel;
+    qcx = protocol.cG(:,1)'.*protocol.sdelc;
+    qcy = protocol.cG(:,2)'.*protocol.sdelc;
+    qcz = protocol.cG(:,3)'.*protocol.sdelc;
+    qrx = protocol.rG(:,1)'.*protocol.sdelr;
+    qry = protocol.rG(:,2)'.*protocol.sdelr;
+    qrz = protocol.rG(:,3)'.*protocol.sdelr;
+
+    Fxx = -GAMMA^2*(qdx.^2.*tdd + qcx.^2.*tcc + qrx.^2.*trr + 2*qdx.*qcx.*tdc + 2*qdx.*qrx.*tdr + 2*qcx.*qrx.*tcr);
+    Fyy = -GAMMA^2*(qdy.^2.*tdd + qcy.^2.*tcc + qry.^2.*trr + 2*qdy.*qcy.*tdc + 2*qdy.*qry.*tdr + 2*qcy.*qry.*tcr);
+    Fzz = -GAMMA^2*(qdz.^2.*tdd + qcz.^2.*tcc + qrz.^2.*trr + 2*qdz.*qcz.*tdc + 2*qdz.*qrz.*tdr + 2*qcz.*qrz.*tcr);
+    Fxy = -GAMMA^2*(qdx.*qdy.*tdd + qcx.*qcy.*tcc + qrx.*qry.*trr + (qdx.*qcy+qdy.*qcx).*tdc + (qdx.*qry+qdy.*qrx).*tdr + (qcx.*qry+qcy.*qrx).*tcr)*2;
+    Fxz = -GAMMA^2*(qdx.*qdz.*tdd + qcx.*qcz.*tcc + qrx.*qrz.*trr + (qdx.*qcz+qdz.*qcx).*tdc + (qdx.*qrz+qdz.*qrx).*tdr + (qcx.*qrz+qcz.*qrx).*tcr)*2;
+    Fyz = -GAMMA^2*(qdy.*qdz.*tdd + qcy.*qcz.*tcc + qry.*qrz.*trr + (qdy.*qcz+qdz.*qcy).*tdc + (qdy.*qrz+qdz.*qry).*tdr + (qcy.*qrz+qcz.*qry).*tcr)*2;
+
+    % Compute the design matrix
+    X = [ones(1, length(protocol.G)); Fxx; Fxy; Fxz; Fyy; Fyz; Fzz]';
+save /tmp/FS_X.mat X;
+
+elseif(strcmp(protocol.pulseseq, 'GEN'))
+    
+    bValue = GENGetB_Values(protocol);
+    % Compute the design matrix
+    bValue=bValue';
+    X = [ones(1, length(protocol.delta)); -bValue.*protocol.grad_dirs(:,1)'.*protocol.grad_dirs(:,1)'; -2*bValue.*protocol.grad_dirs(:,1)'.*protocol.grad_dirs(:,2)'; -2*bValue.*protocol.grad_dirs(:,1)'.*protocol.grad_dirs(:,3)'; -bValue.*protocol.grad_dirs(:,2)'.*protocol.grad_dirs(:,2)'; -2*bValue.*protocol.grad_dirs(:,2)'.*protocol.grad_dirs(:,3)'; -bValue.*protocol.grad_dirs(:,3)'.*protocol.grad_dirs(:,3)']';
+    
+else
+
+    error('Not implemented for pulse sequence: %s', protocol.pulseseq);
+end
+
diff --git a/NODDI_toolbox_v1.01/fitting/EstimateSigma.m b/NODDI_toolbox_v1.01/fitting/EstimateSigma.m
new file mode 100644
index 0000000000000000000000000000000000000000..93ddd423c09c30d11fc2f23239eb35e0365dc2af
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/EstimateSigma.m
@@ -0,0 +1,27 @@
+function sigma = EstimateSigma(signal, protocol, model)
+%
+% function sigma = EstimateSigma(signal, protocol, model)
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+if model.sigma.perVoxel == 1
+    sigma = std(signal(protocol.b0_Indices), 1);
+    % if lower than the minimum SNR
+    sigmaMin = model.sigma.minSNR*mean(signal(protocol.b0_Indices));
+    if sigma < sigmaMin
+        sigma = sigmaMin;
+    end
+else
+    if isfield(model.sigma, 'globalSigma')
+        sigma = model.sigma.globalSigma;
+    elseif isfield(model.sigma, 'globalSNR')
+        sigma = model.sigma.globalSNR*mean(signal(protocol.b0_Indices));
+    else
+        disp('You have chosen not to use per voxel sigma estimate');
+        error('You need to specify either sigma.globalSigma or sigma.globalSNR for your model');
+    end
+end
+
+% apply the scaling parameter that may improve fitting
+sigma = sigma/model.sigma.scaling;
diff --git a/NODDI_toolbox_v1.01/fitting/FSL2Protocol.m b/NODDI_toolbox_v1.01/fitting/FSL2Protocol.m
new file mode 100644
index 0000000000000000000000000000000000000000..be1c271fb1d1e54721030d044ca821d0e52119f7
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/FSL2Protocol.m
@@ -0,0 +1,95 @@
+function protocol = FSL2Protocol(bvalfile, bvecfile, b0threshold)
+%
+% function protocol = FSL2Protocol(bvalfile, bvecfile, b0threshold)
+%
+% Note: for NODDI, the exact sequence timing is not important.
+%  this function reverse-engineerings one possible sequence timing
+%  given the b-values.
+%
+% b0threshold: optional argument to specify a non-zero value for your b=0
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+if nargin == 2
+    b0threshold = 0;
+end
+
+protocol.pulseseq = 'PGSE';
+protocol.schemetype = 'multishellfixedG';
+protocol.teststrategy = 'fixed';
+
+% load bval
+bval = load(bvalfile);
+bval = bval';
+
+% set total number of measurements
+protocol.totalmeas = length(bval);
+
+% set the b=0 indices
+protocol.b0_Indices = find(bval<=b0threshold);
+protocol.numZeros = length(protocol.b0_Indices);
+
+% find the unique non-zero b-values
+B = unique(bval(bval>b0threshold));
+
+% set the number of shells
+protocol.M = length(B);
+for i=1:length(B)
+    protocol.N(i) = length(find(bval==B(i)));
+end
+
+% maximum b-value in the s/mm^2 unit
+maxB = max(B);
+
+% set maximum G = 40 mT/m
+Gmax = 0.04;
+
+% set smalldel and delta and G
+GAMMA = 2.675987E8;
+tmp = nthroot(3*maxB*10^6/(2*GAMMA^2*Gmax^2),3);
+for i=1:length(B)
+    protocol.udelta(i) = tmp;
+    protocol.usmalldel(i) = tmp;
+    protocol.uG(i) = sqrt(B(i)/maxB)*Gmax;        
+end
+
+protocol.delta = zeros(size(bval))';
+protocol.smalldel = zeros(size(bval))';
+protocol.G = zeros(size(bval))';
+
+for i=1:length(B)
+    tmp = find(bval==B(i));
+    for j=1:length(tmp)
+        protocol.delta(tmp(j)) = protocol.udelta(i);
+        protocol.smalldel(tmp(j)) = protocol.usmalldel(i);
+        protocol.G(tmp(j)) = protocol.uG(i);
+    end
+end
+
+% load bvec
+bvec = load(bvecfile);
+protocol.grad_dirs = bvec';
+
+% some systems set vector to zeros for b=0
+% the codes below try to account for this
+if isempty(protocol.b0_Indices)
+    for i=1:protocol.totalmeas
+        if norm(protocol.grad_dirs(i,:)) == 0
+            protocol.G(i) = 0.0;
+            protocol.b0_Indices = [protocol.b0_Indices i];
+        end
+    end
+    protocol.numZeros = length(protocol.b0_Indices);
+end
+    
+% make the gradient directions for b=0's [1 0 0]
+for i=1:length(protocol.b0_Indices)
+    protocol.grad_dirs(protocol.b0_Indices(i),:) = [1 0 0];
+end
+
+% make sure the gradient directions are unit vectors
+for i=1:protocol.totalmeas
+    protocol.grad_dirs(i,:) = protocol.grad_dirs(i,:)/norm(protocol.grad_dirs(i,:));
+end
+
diff --git a/NODDI_toolbox_v1.01/fitting/FitLinearDT.m b/NODDI_toolbox_v1.01/fitting/FitLinearDT.m
new file mode 100644
index 0000000000000000000000000000000000000000..411e90ec2202f7d07ed0fba254f97808e37fec81
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/FitLinearDT.m
@@ -0,0 +1,55 @@
+function [D, Ep] = FitLinearDT(E, protocol, fitS0)
+% Fits the DT model using linear least squares.
+%
+% D=FitLinearDT(E, protocol, fitS0)
+% returns [logS(0) Dxx Dxy Dxz Dyy Dyz Dzz].
+%
+% E is the set of measurements.
+%
+% protocol is the acquisition protocol.
+%
+%
+% fitS0 is a flag for enabling the fitting of S0
+%
+% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
+%         Gary Hui Zhang     (gary.zhang@ucl.ac.uk)
+%
+
+if (nargin < 3)
+	fitS0 = 0;
+end
+
+if (isfield(protocol, 'dti_subset'))
+    E = E(protocol.dti_subset);
+    protocol.delta = protocol.delta(protocol.dti_subset);
+    protocol.smalldel = protocol.smalldel(protocol.dti_subset);
+    protocol.G = protocol.G(protocol.dti_subset);
+    protocol.grad_dirs = protocol.grad_dirs(protocol.dti_subset,:);
+    protocol.b0_Indices = intersect(protocol.b0_Indices, protocol.dti_subset);
+end
+
+X = DT_DesignMatrix(protocol);
+if fitS0 == 0
+  X = X(:,2:end);
+end
+Xi = pinv(X);
+
+% We assume that E are all positives
+% If not, first filter out the nonpositive values with RemoveNegMeas
+
+if (fitS0)
+	D = Xi*log(E);
+    if (nargout > 1)
+        Ep = exp(X*D);
+    end
+else
+	S0 = squeeze(mean(E(protocol.b0_Indices)));
+	E = E/S0;
+	D = zeros(7,1);
+	D(1) = log(S0);
+	D(2:end) = Xi*log(E);
+    if (nargout > 1)
+        Ep = S0*exp(X*D(2:end));
+    end
+end
+
diff --git a/NODDI_toolbox_v1.01/fitting/GetSearchGrid.m b/NODDI_toolbox_v1.01/fitting/GetSearchGrid.m
new file mode 100644
index 0000000000000000000000000000000000000000..502c48a4bdff8504db5aa319f8b1f4970cca38de
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/GetSearchGrid.m
@@ -0,0 +1,654 @@
+function grid = GetSearchGrid(model, material, fix, fixedvals)
+% Returns a list of parameter combinations for the specified model
+% for the GridSearch function to use in search for the combination
+% that best fits a set of measurements.
+%
+% grid=GetSearchGrid(model, material, fix, fixedvals)
+% returns a list of parameter combinations for the model that
+% are realistic for a particular material type.
+%
+% model is a string specifying the model.
+%
+% material is a string specifying the type of material, which
+% determines the range of each parameter in the grid.
+% Options are:
+% invivo
+% invivopreterm
+% invivowhitematter
+% fixedwhitematter
+%
+% fix is a list of binary numbers specifying which
+% model parameters have fixed values.  By default the
+% list is all zeros so no parameters are fixed.
+%
+% fixedvals is an array the same size as fix that specifies
+% the fixed values of any fixed parameters.  Entries in
+% fixedvals in locations where fix has value zero are not
+% used.
+%
+% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
+%         Gary Hui Zhang     (gary.zhang@ucl.ac.uk)
+%
+
+if(nargin<3)
+    fix=zeros(6);
+    fixedvals = zeros(6);
+end
+
+if(strcmp(material, 'invivo'))
+    fs = [0.0 0.25 0.5 0.75 1.0];
+    dpars = [13.0 17.0 21.0]*1E-10;
+    disos = [10.0 20.0 30.0 50.0]*1E-10;
+    Rs=[0.5 1 2 4]*1E-6;
+    irfracs=[0 0.1 0.2 0.3];
+    fisos=[0.0 0.25 0.5 0.75 1.0];
+    kappas = [0.5 1 2 4 8];
+    fic = [0.3 0.5 0.7];
+elseif(strcmp(material, 'exvivo'))
+    fs = [0.0 0.25 0.5 0.75 1.0];
+    dpars = [3.0 4.5 6.0 7.5]*1E-10;
+    disos = [5.0 10.0 15.0]*1E-10;
+    Rs=[1 2 4 8]*1E-6;
+    irfracs=[0 0.1 0.2 0.3];
+    fisos=[0.0 0.25 0.5 0.75 1.0];
+    kappas = [0.5 1 2 4 8];
+    fic = [0.3 0.5 0.7];
+elseif(strcmp(material, 'invivopreterm'))
+    fs = [0.0 0.1 0.2 0.3];
+    dpars = [13.0 17.0 21.0]*1E-10;
+    disos = [10.0 20.0 30.0 50.0]*1E-10;
+    Rs=[1 2 4 8]*1E-6;
+    irfracs=[0 0.1 0.2 0.3];
+    fisos=[0.0 0.25 0.5 0.75 1.0];
+    kappas = [0.5 1 2 4 8];
+    fic = [0.3 0.5 0.7];
+elseif(strcmp(material, 'invivowhitematter'))
+    fs = [0.5 0.7 0.9];
+    dpars = [10.0 13.0 15.0 17.0 19.0 21.0 23.0 25.0]*1E-10;
+    disos = [10.0 20.0 30.0 50.0]*1E-10;
+    Rs=[1 2 4 8]*1E-6;
+    irfracs=[0 0.1 0.2 0.3];
+    fisos=[0 0.2 0.4];
+    kappas = [4 8 16 32 64 128];
+    fic = [0.3 0.5 0.7];
+elseif(strcmp(material, 'postmortemwhitematter'))
+    fs = [0.5 0.7 0.9];
+    dpars = [2.0 3.0 4.0 5.0 6.0]*1E-10;
+    disos = [5.0 10.0 15.0]*1E-10;
+    Rs=[1 2 4 8]*1E-6;
+    irfracs=[0 0.1 0.2 0.3];
+    fisos=[0 0.2 0.4];
+    kappas = [4 8 16 32 64 128];
+    fic = [0.3 0.5 0.7];
+else
+    error(['Unknown material: ', tissue]);
+end
+
+% Adjust for fixed parameters.  The first two parameters are the same for
+% all models.
+if(fix(1))
+    fs = [fixedvals(1)];
+end
+if(fix(2))
+    dpars = [fixedvals(2)];
+end
+
+if(strcmp(model, 'CylSingleRadTortGPD'))
+    if(fix(3))
+        Rs = [fixedvals(3)];
+    end
+
+    numCombs = length(Rs)*length(fs)*length(dpars);
+    grid = zeros(3, numCombs);
+    ind = 1;
+    for i=1:length(Rs)
+        for j=1:length(fs)
+            for k=1:length(dpars)
+                pars = [fs(j) dpars(k) Rs(i)];
+                grid(:,ind) = pars;
+                ind = ind + 1;
+            end
+        end
+    end
+elseif(strcmp(model, 'CylSingleRadGPD'))
+    if(fix(4))
+        Rs = [fixedvals(4)];
+    end
+
+    numCombs = length(Rs)*length(fs)*length(dpars);
+    grid = zeros(4, numCombs);
+    ind = 1;
+    for i=1:length(Rs)
+        for j=1:length(fs)
+            for k=1:length(dpars)
+                % Set dperp using the standard tortuosity model for
+                % randomly placed cylinders unless fixed.
+                dperp = dpars(k)*(1-fs(j));
+                if(fix(3))
+                    dperp = fixedvals(3);
+                end
+                pars = [fs(j) dpars(k) dperp Rs(i)];
+                grid(:,ind) = pars;
+                ind = ind + 1;
+            end
+        end
+    end
+elseif(strcmp(model, 'CylSingleRadTortIsoGPD'))
+    if(fix(3))
+        Rs = [fixedvals(3)];
+    end
+    if(fix(4))
+        fisos = [fixedvals(4)];
+    end
+
+    numCombs = length(Rs)*length(fs)*length(dpars)*length(fisos);
+    grid = zeros(4, numCombs);
+    ind = 1;
+    for i=1:length(Rs)
+        for j=1:length(fs)
+            for k=1:length(dpars)
+                for l=1:length(fisos)
+                    pars = [fs(j) dpars(k) Rs(i) fisos(l)];
+                    grid(:,ind) = pars;
+                    ind = ind + 1;
+                end
+            end
+        end
+    end
+elseif(strcmp(model, 'CylSingleRadIsoV_GPD') || strcmp(model, 'CylSingleRadIsoV_GPD_B0'))
+    if(fix(4))
+        Rs = [fixedvals(4)];
+    end
+    if(fix(5))
+        fisos = [fixedvals(5)];
+    end
+    if(fix(6))
+        disos = [fixedvals(6)];
+    end
+
+    numCombs = length(Rs)*length(fs)*length(dpars)*length(fisos)*length(disos);
+    grid = zeros(6, numCombs);
+    ind = 1;
+    for i=1:length(Rs)
+        for j=1:length(fs)
+            for k=1:length(dpars)
+                for l=1:length(fisos)
+                    for m=1:length(disos)
+                        % Set dperp using the standard tortuosity model for
+                        % randomly placed cylinders unless fixed.
+                        dperp = dpars(k)*(1-fs(j));
+                        if(fix(3))
+                            dperp = fixedvals(3);
+                        end
+                        pars = [fs(j) dpars(k) dperp Rs(i) fisos(l) disos(m)];
+                        grid(:,ind) = pars;
+                        ind = ind + 1;
+                    end
+                end
+            end
+        end
+    end
+elseif(strcmp(model, 'CylSingleRadTortIsoV_GPD') || strcmp(model, 'CylSingleRadTortIsoV_GPD_B0'))
+    if(fix(3))
+        Rs = [fixedvals(3)];
+    end
+    if(fix(4))
+        fisos = [fixedvals(4)];
+    end
+    if(fix(5))
+        disos = [fixedvals(5)];
+    end
+
+    numCombs = length(Rs)*length(fs)*length(dpars)*length(fisos)*length(disos);
+    grid = zeros(5, numCombs);
+    ind = 1;
+    for i=1:length(Rs)
+        for j=1:length(fs)
+            for k=1:length(dpars)
+                for l=1:length(fisos)
+                    for m=1:length(disos)
+                        pars = [fs(j) dpars(k) Rs(i) fisos(l) disos(m)];
+                        grid(:,ind) = pars;
+                        ind = ind + 1;
+                    end
+                end
+            end
+        end
+    end
+elseif(strcmp(model, 'CylSingleRadIsoDotGPD'))
+    if(fix(4))
+        Rs = [fixedvals(4)];
+    end
+    if(fix(5))
+        irfracs = [fixedvals(5)];
+    end
+    numCombs = length(Rs)*length(fs)*length(dpars)*length(irfracs);
+    grid = zeros(5, numCombs);
+    ind = 1;
+    for i=1:length(Rs)
+        for j=1:length(fs)
+            for k=1:length(dpars)
+                for l=1:length(irfracs)
+                    dperp = dpars(k)*(1-fs(j));
+                    pars = [fs(j) dpars(k) dperp Rs(i) irfracs(l)];
+                    grid(:,ind) = pars;
+                    ind = ind + 1;
+                end
+            end
+        end
+    end
+elseif(strcmp(model, 'CylSingleRadIsoResTortIsoV_GPD') || strcmp(model, 'CylSingleRadIsoResTortIsoV_GPD_B0')...
+        || strcmp(model, 'CylSingleRadIsoStickTortIsoV_GPD') || strcmp(model, 'CylSingleRadIsoStickTortIsoV_GPD_B0')...
+        || strcmp(model, 'CylSingleRadIsoSphereTortIsoV_GPD') || strcmp(model, 'CylSingleRadIsoSphereTortIsoV_GPD_B0')...
+        || strcmp(model, 'CylSingleRadIsoDotTortIsoV_GPD') || strcmp(model, 'CylSingleRadIsoDotTortIsoV_GPD_B0'))
+    if(fix(3))
+        Rs = [fixedvals(3)];
+    end
+    if(fix(4))
+        irfracs = [fixedvals(4)];
+    end
+    if(fix(5))
+        fisos = [fixedvals(5)];
+    end
+    if(fix(6))
+        disos = [fixedvals(6)];
+    end
+
+    numCombs = length(Rs)*length(fs)*length(dpars)*length(fisos)*length(disos);
+    grid = zeros(6, numCombs);
+    ind = 1;
+    for i=1:length(Rs)
+        for j=1:length(fs)
+            for k=1:length(dpars)
+                for l=1:length(fisos)
+                    for m=1:length(disos)
+                        for n=1:length(irfracs)
+                            pars = [fs(j) dpars(k) Rs(i) irfracs(n) fisos(l) disos(m)];
+                            grid(:,ind) = pars;
+                            ind = ind + 1;
+                        end
+                    end
+                end
+            end
+        end
+    end
+elseif(strcmp(model, 'Stick'))
+    numCombs = length(fs)*length(dpars);
+    grid = zeros(3, numCombs);
+    ind = 1;
+    for i=1:length(fs)
+        for j=1:length(dpars)
+            % Set dperp using the standard tortuosity model for
+            % randomly placed cylinders unless fixed.
+            dperp = dpars(j)*(1-fs(i));
+            if(fix(3))
+                dperp = fixedvals(3);
+            end
+            pars = [fs(i) dpars(j) dperp];
+            grid(:,ind) = pars;
+            ind = ind + 1;
+        end
+    end
+elseif(strcmp(model, 'StickIsoV_B0'))
+    if(fix(4))
+        fisos = [fixedvals(4)];
+    end
+    if(fix(5))
+        disos = [fixedvals(5)];
+    end
+
+    numCombs = length(fs)*length(dpars)*length(fisos)*length(disos);
+    grid = zeros(5, numCombs);
+    ind = 1;
+    for i=1:length(fs)
+        for j=1:length(dpars)
+            for k=1:length(fisos)
+                for l=1:length(disos)
+                    % Set dperp using the standard tortuosity model for
+                    % randomly placed cylinders unless fixed
+                    dperp = dpars(j)*(1-fs(i));
+                    if(fix(3))
+                        dperp = fixedvals(3);
+                    end
+                    pars = [fs(i) dpars(j) dperp fisos(k) disos(l)];
+                    grid(:,ind) = pars;
+                    ind = ind + 1;
+                end
+            end
+        end
+    end
+elseif(strcmp(model, 'StickTortIsoV_B0'))
+    if(fix(3))
+        fisos = [fixedvals(3)];
+    end
+    if(fix(4))
+        disos = [fixedvals(4)];
+    end
+
+    numCombs = length(fs)*length(dpars)*length(fisos)*length(disos);
+    grid = zeros(4, numCombs);
+    ind = 1;
+    for i=1:length(fs)
+        for j=1:length(dpars)
+            for k=1:length(fisos)
+                for l=1:length(disos)
+                    pars = [fs(i) dpars(j) fisos(k) disos(l)];
+                    grid(:,ind) = pars;
+                    ind = ind + 1;
+                end
+            end
+        end
+    end
+elseif(strcmp(model, 'WatsonStick') || strcmp(model, 'WatsonSHStick'))
+    numCombs = length(fs)*length(dpars)*length(kappas);
+    grid = zeros(4, numCombs);
+    ind = 1;
+    for i=1:length(fs)
+        for j=1:length(dpars)
+		  for k=1:length(kappas)
+                % Set dperp using the standard tortuosity model for
+                % randomly placed cylinders unless fixed.
+                dperp = dpars(j)*(1-fs(i));
+                if(fix(3))
+                    dperp = fixedvals(3);
+                end
+                pars = [fs(i) dpars(j) dperp kappas(k)];
+                grid(:,ind) = pars;
+                ind = ind + 1;
+            end
+        end
+    end
+elseif(strcmp(model, 'WatsonSHStickIsoV_B0'))
+    if(fix(4))
+        kappas = [fixedvals(4)];
+    end
+    if(fix(5))
+        fisos = [fixedvals(5)];
+    end
+    if(fix(6))
+        disos = [fixedvals(6)];
+    end
+
+    numCombs = length(fs)*length(dpars)*length(fisos)*length(disos)*length(kappas);
+    grid = zeros(6, numCombs);
+    ind = 1;
+    for i=1:length(fs)
+        for j=1:length(dpars)
+            for k=1:length(fisos)
+                for l=1:length(disos)
+                    for m=1:length(kappas)
+                      dperp = dpars(j)*(1-fs(i));
+                      if(fix(3))
+                          dperp = fixedvals(3);
+                      end
+                      pars = [fs(i) dpars(j) dperp kappas(m) fisos(k) disos(l)];
+                      grid(:,ind) = pars;
+                      ind = ind + 1;
+                    end
+                end
+            end
+        end
+    end
+elseif(strcmp(model, 'WatsonSHStickIsoVIsoDot_B0'))
+    if(fix(5))
+        fisos = [fixedvals(5)];
+    end
+    if(fix(6))
+        disos = [fixedvals(6)];
+    end
+    if(fix(7))
+        irfracs = [fixedvals(7)];
+    end
+
+    numCombs = length(fs)*length(dpars)*length(fisos)*length(disos)*length(kappas)*length(irfracs);
+    grid = zeros(7, numCombs);
+    ind = 1;
+    for i=1:length(fs)
+        for j=1:length(dpars)
+            for k=1:length(fisos)
+                for l=1:length(disos)
+                    for m=1:length(kappas)
+                        for n=1:length(irfracs)
+                          dperp = dpars(j)*(1-fs(i));
+                          if(fix(3))
+                             dperp = fixedvals(3);
+                          end
+                          pars = [fs(i) dpars(j) dperp kappas(m) fisos(k) disos(l) irfracs(n)];
+                          grid(:,ind) = pars;
+                          ind = ind + 1;
+                        end
+                    end
+                end
+            end
+        end
+    end
+elseif(strcmp(model, 'WatsonStickTort') || strcmp(model, 'WatsonSHStickTort'))
+    numCombs = length(fs)*length(dpars)*length(kappas);
+    grid = zeros(3, numCombs);
+    ind = 1;
+    for i=1:length(fs)
+        for j=1:length(dpars)
+		  for k=1:length(kappas)
+                pars = [fs(i) dpars(j) kappas(k)];
+                grid(:,ind) = pars;
+                ind = ind + 1;
+            end
+        end
+    end
+elseif(strcmp(model, 'WatsonSHStickTortIsoV_B0'))
+    if(fix(4))
+        fisos = [fixedvals(4)];
+    end
+    if(fix(5))
+        disos = [fixedvals(5)];
+    end
+
+    numCombs = length(fs)*length(dpars)*length(fisos)*length(disos)*length(kappas);
+    grid = zeros(5, numCombs);
+    ind = 1;
+    for i=1:length(fs)
+        for j=1:length(dpars)
+            for k=1:length(fisos)
+                for l=1:length(disos)
+                    for m=1:length(kappas)
+                      pars = [fs(i) dpars(j) kappas(m) fisos(k) disos(l)];
+                      grid(:,ind) = pars;
+                      ind = ind + 1;
+                    end
+                end
+            end
+        end
+    end
+elseif(strcmp(model, 'WatsonSHStickTortIsoVIsoDot_B0'))
+    if(fix(4))
+        fisos = [fixedvals(4)];
+    end
+    if(fix(5))
+        disos = [fixedvals(5)];
+    end
+    if(fix(6))
+        irfracs = [fixedvals(6)];
+    end
+
+    numCombs = length(fs)*length(dpars)*length(fisos)*length(disos)*length(kappas)*length(irfracs);
+    grid = zeros(6, numCombs);
+    ind = 1;
+    for i=1:length(fs)
+        for j=1:length(dpars)
+            for k=1:length(fisos)
+                for l=1:length(disos)
+                    for m=1:length(kappas)
+                        for n=1:length(irfracs)
+                          pars = [fs(i) dpars(j) kappas(m) fisos(k) disos(l) irfracs(n)];
+                          grid(:,ind) = pars;
+                          ind = ind + 1;
+                        end
+                    end
+                end
+            end
+        end
+    end
+elseif(strcmp(model, 'WatsonSHCylSingleRadTortIsoV_GPD') || strcmp(model, 'WatsonSHCylSingleRadTortIsoV_GPD_B0'))
+    if(fix(3))
+        Rs = [fixedvals(3)];
+    end
+    if(fix(5))
+        fisos = [fixedvals(5)];
+    end
+    if(fix(6))
+        disos = [fixedvals(6)];
+    end
+
+    numCombs = length(Rs)*length(fs)*length(dpars)*length(fisos)*length(disos)*length(kappas);
+    grid = zeros(6, numCombs);
+    ind = 1;
+    for i=1:length(Rs)
+        for j=1:length(fs)
+            for k=1:length(dpars)
+                for l=1:length(fisos)
+                    for m=1:length(disos)
+                      for n=1:length(kappas)
+                        pars = [fs(j) dpars(k) Rs(i) kappas(n) fisos(l) disos(m)];
+                        grid(:,ind) = pars;
+                        ind = ind + 1;
+                      end
+                    end
+                end
+            end
+        end
+    end
+elseif(strcmp(model, 'BinghamCylSingleRadTortIsoV_GPD_B0'))
+    if(fix(3))
+        Rs = [fixedvals(3)];
+    end
+    if(fix(7))
+        fisos = [fixedvals(7)];
+    end
+    if(fix(8))
+        disos = [fixedvals(8)];
+    end
+
+    numCombs = length(Rs)*length(fs)*length(dpars)*length(fisos)*length(disos)*length(kappas);
+    grid = zeros(8, numCombs);
+    ind = 1;
+    for i=1:length(Rs)
+        for j=1:length(fs)
+            for k=1:length(dpars)
+                for l=1:length(fisos)
+                    for m=1:length(disos)
+                        for n=1:length(kappas)
+                            pars = [fs(j) dpars(k) Rs(i) kappas(n) 0 0 fisos(l) disos(m)];
+                            grid(:,ind) = pars;
+                            ind = ind + 1;
+                        end
+                    end
+                end
+            end
+        end
+    end
+elseif(strcmp(model, 'BinghamStickTortIsoV_B0'))
+    if(fix(6))
+        fisos = [fixedvals(6)];
+    end
+    if(fix(7))
+        disos = [fixedvals(7)];
+    end
+
+    numCombs = length(fs)*length(dpars)*length(fisos)*length(disos)*length(kappas);
+    grid = zeros(7, numCombs);
+    ind = 1;
+    for i=1:length(fs)
+        for j=1:length(dpars)
+            for k=1:length(fisos)
+                for l=1:length(disos)
+                    for m=1:length(kappas)
+                        pars = [fs(i) dpars(j) kappas(m) 0 0 fisos(k) disos(l)];
+                        grid(:,ind) = pars;
+                        ind = ind + 1;
+                    end
+                end
+            end
+        end
+    end
+elseif(strcmp(model, 'ExCrossingCylSingleRadGPD'))
+    R1s = Rs;
+    R2s = Rs;
+    if(fix(4))
+        R1s = [fixedvals(4)];
+    end
+
+    if(fix(5))
+        R2s = [fixedvals(5)];
+    end
+
+    numCombs = length(R1s)*length(R2s)*length(fs)*length(dpars)*length(fic);
+    grid = zeros(6, numCombs);
+    ind = 1;
+    for i=1:length(R1s)
+        for j=1:length(R2s)
+            for k=1:length(fs)
+                for l=1:length(dpars)
+                    for m=1:length(fic)
+                        % Set dperp using the standard tortuosity model for
+                        % randomly placed cylinders unless fixed.
+                        dperp = dpars(l)*(1-fs(k));
+                        if(fix(3))
+                            dperp = fixedvals(3);
+                        end                        
+                        pars = [fs(k) dpars(l) dperp R1s(i) R2s(j) fic(m)];
+                        grid(:,ind) = pars;
+                        ind = ind + 1;
+                    end
+                end
+            end
+        end
+    end
+elseif(strcmp(model, 'ExCrossingCylSingleRadIsoDotTortIsoV_GPD_B0'))
+    R1s = Rs;
+    R2s = Rs;
+    if(fix(3))
+        R1s = [fixedvals(3)];
+    end
+
+    if(fix(4))
+        R2s = [fixedvals(4)];
+    end
+    
+    if(fix(6))
+        irfracs = [fixedvals(6)];
+    end
+    
+    if(fix(7))
+        fisos = [fixedvals(7)];
+    end
+    
+    if(fix(8))
+        disos = [fixedvals(8)]; 
+    end
+    
+    numCombs = length(R1s)*length(R2s)*length(fs)*length(dpars)*length(fic)*length(irfracs)*length(fisos)*length(disos);
+    grid = zeros(8, numCombs);
+    ind = 1;
+    for i=1:length(R1s)
+        for j=1:length(R2s)
+            for k=1:length(fs)
+                for l=1:length(dpars)
+                    for m=1:length(fic)
+								 for n=1:length(irfracs)
+										for p=1:length(fisos)
+											 for q=1:length(disos)
+						  				  		  pars = [fs(k) dpars(l) R1s(i) R2s(j) fic(m) irfracs(n) fisos(p) disos(q)];
+						  				  		  grid(:,ind) = pars;
+						  				  		  ind = ind + 1;
+									 		 end
+										end
+								 end
+                    end
+                end
+            end
+        end
+    end
+else
+    error(['Starting combinations not implemented for model: ', model]);
+end
+
diff --git a/NODDI_toolbox_v1.01/fitting/GradDescDecode.m b/NODDI_toolbox_v1.01/fitting/GradDescDecode.m
new file mode 100644
index 0000000000000000000000000000000000000000..44e66e28e8f74cb9fd2dfca5f6cc569b4a7e147e
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/GradDescDecode.m
@@ -0,0 +1,37 @@
+function params = GradDescDecode(modelname, optoutput)
+%
+% function params = GradDescDecode(modelname, optoutput)
+%
+% Encodes raw parameter values to enforce simple constraints during direct fitting.
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+parameterStrings = GetParameterStrings(modelname);
+params = zeros(1, length(parameterStrings));
+
+for i=1:length(parameterStrings)
+    if (strcmp(parameterStrings(i), 'ficvf') ||...
+        strcmp(parameterStrings(i), 'fiso') ||...
+        strcmp(parameterStrings(i), 'irfrac'))
+       params(i) = sin(optoutput(i))^2;
+    elseif (strcmp(parameterStrings(i), 'di') ||...
+            strcmp(parameterStrings(i), 'diso') ||...
+            strcmp(parameterStrings(i), 'rad') ||...
+            strcmp(parameterStrings(i), 'kappa') ||...
+            strcmp(parameterStrings(i), 'b0') ||...
+            strcmp(parameterStrings(i), 't1'))
+       params(i) = optoutput(i)^2;
+    elseif (strcmp(parameterStrings(i), 'dh'))
+		 diIdx = GetParameterIndex(modelname, 'di');
+       params(i) = params(diIdx)*sin(optoutput(i))^2;
+	 elseif (strcmp(parameterStrings(i), 'beta'))
+		 kappaIdx = GetParameterIndex(modelname, 'kappa');
+       params(i) = params(kappaIdx)*sin(optoutput(i))^2;
+    elseif (strcmp(parameterStrings(i), 'theta') ||...
+            strcmp(parameterStrings(i), 'phi') ||...
+            strcmp(parameterStrings(i), 'psi'))
+       params(i) = optoutput(i);
+	 end
+end
+
diff --git a/NODDI_toolbox_v1.01/fitting/GradDescEncode.m b/NODDI_toolbox_v1.01/fitting/GradDescEncode.m
new file mode 100644
index 0000000000000000000000000000000000000000..24a6a5875131f46186195fefcc174f1135d3af3a
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/GradDescEncode.m
@@ -0,0 +1,41 @@
+function optarray = GradDescEncode(modelname, x)
+%
+% function optarray = GradDescEncode(modelname, x)
+%
+% Encodes raw parameter values to enforce simple constraints during direct fitting.
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+parameterStrings = GetParameterStrings(modelname);
+optarray = zeros(1, length(parameterStrings));
+
+for i=1:length(parameterStrings)
+    if (strcmp(parameterStrings(i), 'ficvf') ||...
+        strcmp(parameterStrings(i), 'fiso') ||...
+        strcmp(parameterStrings(i), 'irfrac'))
+       optarray(i) = asin(sqrt(x(i)));
+    elseif (strcmp(parameterStrings(i), 'di') ||...
+            strcmp(parameterStrings(i), 'diso') ||...
+            strcmp(parameterStrings(i), 'rad') ||...
+            strcmp(parameterStrings(i), 'kappa') ||...
+            strcmp(parameterStrings(i), 'b0') ||...
+            strcmp(parameterStrings(i), 't1'))
+       optarray(i) = sqrt(x(i));
+    elseif (strcmp(parameterStrings(i), 'dh'))
+		 diIdx = GetParameterIndex(modelname, 'di');
+       optarray(i) = asin(sqrt(x(i)/x(diIdx)));
+	 elseif (strcmp(parameterStrings(i), 'beta'))
+		 kappaIdx = GetParameterIndex(modelname, 'kappa');
+		 if (x(kappaIdx) == 0)
+           optarray(i) = 0;
+       else
+           optarray(i) = asin(sqrt(x(i)/x(kappaIdx)));
+       end
+    elseif (strcmp(parameterStrings(i), 'theta') ||...
+            strcmp(parameterStrings(i), 'phi') ||...
+            strcmp(parameterStrings(i), 'psi'))
+       optarray(i) = x(i);
+	 end
+end
+
diff --git a/NODDI_toolbox_v1.01/fitting/GradDescLimits.m b/NODDI_toolbox_v1.01/fitting/GradDescLimits.m
new file mode 100644
index 0000000000000000000000000000000000000000..a9eb11c467c127e72d30d8adb6ac319c039c1e55
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/GradDescLimits.m
@@ -0,0 +1,69 @@
+function [min_val max_val] = GradDescLimits(modelname)
+%
+% function [min_val max_val] = GradDescLimits(modelname)
+%
+% Returns maximum and minimum settings for the parameters of different
+% models to use during direct fitting.
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+LARGE = 100000;
+
+D_MIN = 0.001;
+D_MAX = 3;
+D_PERP_MIN = 0.001;
+
+ANGLEMAX=100;
+
+R_MIN = 0.1;
+R_MAX = 5;
+
+% the values need to account for scaling defined
+% in GetScalingFactors.m
+K_MIN = 0;
+K_MAX = 6.4;
+
+B_MIN = 0;
+B_MAX = 3.2;
+
+parameterStrings = GetParameterStrings(modelname);
+min_val = zeros(1, length(parameterStrings));
+max_val = zeros(1, length(parameterStrings));
+
+for i=1:length(parameterStrings)
+    if (strcmp(parameterStrings(i), 'ficvf') ||...
+        strcmp(parameterStrings(i), 'fiso') ||...
+        strcmp(parameterStrings(i), 'irfrac'))
+        min_val(i) = 0;
+        max_val(i) = LARGE;
+    elseif (strcmp(parameterStrings(i), 'di') ||...
+            strcmp(parameterStrings(i), 'diso'))
+        min_val(i) = sqrt(D_MIN);
+        max_val(i) = sqrt(D_MAX);
+    elseif (strcmp(parameterStrings(i), 'dh'))
+        min_val(i) = sqrt(D_PERP_MIN);
+        max_val(i) = LARGE;
+    elseif (strcmp(parameterStrings(i), 'rad'))
+        min_val(i) = sqrt(R_MIN);
+        max_val(i) = sqrt(R_MAX);
+    elseif (strcmp(parameterStrings(i), 'kappa'))
+        min_val(i) = sqrt(K_MIN);
+        max_val(i) = sqrt(K_MAX);
+    elseif (strcmp(parameterStrings(i), 'beta'))
+        min_val(i) = sqrt(B_MIN);
+        max_val(i) = sqrt(B_MAX);
+    elseif (strcmp(parameterStrings(i), 'theta') ||...
+            strcmp(parameterStrings(i), 'phi') ||...
+            strcmp(parameterStrings(i), 'psi'))
+        min_val(i) = -ANGLEMAX;
+        max_val(i) = ANGLEMAX;
+    elseif (strcmp(parameterStrings(i), 'b0'))
+        min_val(i) = 0.001;
+        max_val(i) = LARGE;
+    elseif (strcmp(parameterStrings(i), 't1'))
+        min_val(i) = 0.1;
+        max_val(i) = 1;
+    end
+end
+
diff --git a/NODDI_toolbox_v1.01/fitting/GridSearchRician.m b/NODDI_toolbox_v1.01/fitting/GridSearchRician.m
new file mode 100644
index 0000000000000000000000000000000000000000..0a739a9b8c90b86b5d44da8f0875989fd5ddac38
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/GridSearchRician.m
@@ -0,0 +1,134 @@
+function [x0, liks] = GridSearchRician(Epn, model, grid, protocol, constants, initSig, fixT1, fibredir)
+% Performs a discrete grid search for the combination of parameters
+% that best fits a set of measurements for the specified model using a
+% Rician noise model.
+%
+% [x0, liks] = GridSearchRician(Epn, model, grid, protocol, constants, initSig, fibredir)
+% returns the parameter combination x0 with the lowest fitting error and a list
+% liks of the values of the objective function for each parameter combination in the grid.
+%
+% model is a string specifying the model.
+%
+% Epn is the array of measurements.
+%
+% model is a string specifying the model
+%
+% grid is the list of parameter combinations to check; typically
+% this comes from GetSearchGrid.
+% 
+% protocol contains the protocol for obtaining the measurements.
+%
+% constants contains values required for the model signal computations.
+%
+% initSig is the standard deviation of the noise underlying the Rician
+% noise model.
+%
+% fibredir can be specified, but if left out is estimated by fitting the
+% diffusion tensor model to the measurements and using the principal
+% eigenvalue.
+%
+% fixT1 is a fixed value for T1 that can be specified.  If not
+% specified and the model is one that contains T1 as a parameter,
+% then T1 is estimated via a linear fit at the same time as the
+% diffusion tensor.  Note: this may not work particularly well.
+% If the DT is a bad fit for the data, this can easily result
+% in negative diffusivities etc.
+%
+% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
+%         Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+[junk numCombs] = size(grid);
+
+% Find the fiber direction and S0 from the best fit DT
+if(nargin<8)
+    if(strcmp(model, 'CylSingleRadIsoDotTortIsoV_GPD_B0T1'))
+        if(nargin<7)
+                D = FitLinearDT_T1(Epn, protocol);
+                % Linear estimate of T1 can occasionally go negative
+                % from noise.
+                T1 = max([0 D(8)]);
+        else
+                % Correct for the known T1 and fit DT in the normal way.
+                D = FitLinearDT(Epn.*exp(-fixT1./protocol.TM), protocol);
+                T1 = fixT1;
+        end
+    else
+        D = FitLinearDT(Epn, protocol);
+    end
+    dt = MakeDT_Matrix(D(2), D(3), D(4), D(5), D(6), D(7));
+    [evec, eval] = eig(dt);
+	 % try to deal with non-positive definite tensors
+    [eigs, ind] = sort(abs([eval(1, 1) eval(2, 2) eval(3, 3)]));
+    fibredir = evec(:,ind(3));
+    if(strncmp(model, 'Bingham', 7))
+        beta_to_kappa = eigs(2)/eigs(3);
+        fanningdir = evec(:,ind(2));
+    end
+    S0 = exp(D(1));
+end
+
+initTheta = acos(fibredir(3));
+initPhi = atan2(fibredir(2), fibredir(1));
+
+if(strncmp(model, 'Bingham', 7))
+    if abs(fibredir(3)) > 0.1
+        mat = [-sin(initPhi) -cos(initTheta)*cos(initPhi); cos(initPhi) -cos(initTheta)*sin(initPhi)];
+        tmp = mat\[fanningdir(1) fanningdir(2)]';
+        initPsi = atan2(tmp(2), tmp(1));
+    elseif abs(sin(initPhi)) > 0.1
+        mat = [-sin(initPhi) -cos(initTheta)*cos(initPhi); 0 sin(initTheta)];
+        tmp = mat\[fanningdir(1) fanningdir(3)]';
+        initPsi = atan2(tmp(2), tmp(1));
+    else
+        mat = [cos(initPhi) -cos(initTheta)*sin(initPhi); 0 sin(initTheta)];
+        tmp = mat\[fanningdir(2) fanningdir(3)]';
+        initPsi = atan2(tmp(2), tmp(1));
+    end
+    if(strcmp(model, 'BinghamStickTortIsoV_B0'))
+        grid(4,:) = grid(3,:)*beta_to_kappa;
+        grid(5,:) = initPsi;
+    elseif(strcmp(model, 'BinghamCylSingleRadTortIsoV_GPD_B0'))
+        grid(5,:) = grid(4,:)*beta_to_kappa;
+        grid(6,:) = initPsi;
+    else
+        error('ERROR: Bingham initialization not implemented for this model');
+    end
+end
+
+% Add the b=0 measurement to the test combinations for models that need it.
+if(strcmp(model, 'CylSingleRadIsoV_GPD_B0') ||...
+   strcmp(model, 'CylSingleRadTortIsoV_GPD_B0') ||...
+   strcmp(model, 'CylSingleRadIsoDotTortIsoV_GPD_B0') ||...
+   strcmp(model, 'WatsonSHCylSingleRadTortIsoV_GPD_B0') ||...
+   strcmp(model, 'WatsonSHStickIsoV_B0') ||...
+   strcmp(model, 'WatsonSHStickIsoVIsoDot_B0') ||...
+   strcmp(model, 'WatsonSHStickTortIsoV_B0') ||...
+   strcmp(model, 'WatsonSHStickTortIsoVIsoDot_B0') ||...
+   strcmp(model, 'BinghamStickTortIsoV_B0') ||...
+   strcmp(model, 'BinghamCylSingleRadTortIsoV_GPD_B0') ||...
+   strcmp(model, 'StickIsoV_B0') ||...
+   strcmp(model, 'StickTortIsoV_B0'))
+        grid = [grid' ones(size(grid,2), 1)*S0]';
+end
+
+% Add T1 and the b=0 measurement to the test combinations for models
+% that need it.
+if(strcmp(model, 'CylSingleRadIsoDotTortIsoV_GPD_B0T1'))
+        grid = [grid' ones(size(grid,2), 1)*S0 ones(size(grid,2), 1)*T1]';
+end
+
+% Test each combination
+liks = zeros(numCombs, 1);
+for j=1:numCombs
+    Eest = SynthMeas(model, grid(:,j), protocol, fibredir, constants);
+    liks(j) = RicianLogLik(Epn, Eest, initSig);
+end
+[a ind] = max(liks);
+mlPars = grid(:,ind);
+
+% Rescale and construct the final result.
+scale = GetScalingFactors(model);
+psc = [mlPars' initSig].*scale;
+x0 = [psc(1:(end-1)) initTheta initPhi initSig];
+
diff --git a/NODDI_toolbox_v1.01/fitting/PlotFittedModel.m b/NODDI_toolbox_v1.01/fitting/PlotFittedModel.m
new file mode 100644
index 0000000000000000000000000000000000000000..21e78d90114fd4ee070c76b4bcaa275f37a1f6da
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/PlotFittedModel.m
@@ -0,0 +1,58 @@
+function PlotFittedModel(protocol, MODELNAME, fittedpars, constants, h, style)
+% Plots the normalized measurements predicted by the model with
+% the fitted parameters against the absolute dot product of the
+% gradient and fibre directions.
+%
+% PlotFittedModel(protocol, MODELNAME, fittedpars, h)
+% adds the plot to figure handle h.
+%
+% protocol is the imaging protocol.
+%
+% MODELNAME is the name identifying the model.
+%
+% fittedpars and the model parameter values.
+%
+% constants is a structure containing fixed values required for the model.
+%
+% h is a figure handle to add the plot to.  If not specified, a new figure
+% appears.
+%
+% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
+%         Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+if(nargin<5)
+    h = figure;
+end
+
+% Get estimated fibre direction and b=0 signal.
+fibredir = GetFibreOrientation(MODELNAME, fittedpars);
+b0est = GetB0(MODELNAME, fittedpars);
+
+if(nargin<6)
+    style = '-';
+end
+
+linedef{1} = ['r', style];
+linedef{2} = ['b', style];
+linedef{3} = ['g', style];
+linedef{4} = ['m', style];
+linedef{5} = ['c', style];
+linedef{6} = ['k', style];
+linedef{7} = ['y', style];
+
+hold on;
+
+scale = GetScalingFactors(MODELNAME);
+xsc = fittedpars(1:(length(scale)-1))./scale(1:(end-1));
+S_Meas = SynthMeas(MODELNAME, xsc, protocol, fibredir, constants);
+Snormdw = S_Meas./b0est;
+for j=1:length(protocol.uG)
+    inds = find(protocol.G == protocol.uG(j) & protocol.delta == protocol.udelta(j) & protocol.smalldel == protocol.usmalldel(j));
+    dps = abs(protocol.grad_dirs(inds,:)*fibredir);
+    [t tinds] = sort(dps);
+    plot(dps(tinds), Snormdw(inds(tinds)), linedef{j}, 'LineWidth', 2);
+end
+xlabel('|n.G|/|G|_{max}');
+ylabel('S/S_0');
+
diff --git a/NODDI_toolbox_v1.01/fitting/QualityOfFit.m b/NODDI_toolbox_v1.01/fitting/QualityOfFit.m
new file mode 100644
index 0000000000000000000000000000000000000000..08a920f1b81089c162f72453a9c304e67e35a5d5
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/QualityOfFit.m
@@ -0,0 +1,31 @@
+function [h] = QualityOfFit(signal, fittedpars, model, protocol)
+% Assess the quality of fit
+% [h] = QualityOfFit(signal, fittedpars, model, protocol);
+%
+% Typical usage as follows:
+% 
+% 1) First fit the signal
+% [gs fgs ml fml] = ThreeStageFittingVoxel(signal, protocol, model);
+%
+% 2) Now check the quality of fit
+% QualityOfFit(signal, ml, model, protocol);
+%
+% Author: Gary Hui Zhang, PhD
+%
+
+b0 = GetB0(model.name, fittedpars);
+fibredir = GetFibreOrientation(model.name, fittedpars);
+
+h = figure;
+
+% the data plot
+VoxelDataViewer(protocol, signal, fibredir, b0, h);
+
+% the predicted data plot
+% constants is set to zero for NODDI but should be different for
+% ActiveAx models
+constants = 0;
+PlotFittedModel(protocol, model.name, fittedpars, constants, h);
+
+end
+
diff --git a/NODDI_toolbox_v1.01/fitting/RemoveNegMeas.m b/NODDI_toolbox_v1.01/fitting/RemoveNegMeas.m
new file mode 100644
index 0000000000000000000000000000000000000000..93da4b40cf47ca7275dc3531fa5574a4bf5ca5d1
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/RemoveNegMeas.m
@@ -0,0 +1,78 @@
+function [E tempprot] = RemoveNegMeas(Epn, protocol)
+% Removes negative or zero measurements from a set and returns a protocol
+% with the corresponding elements removed to exclude the negative
+% measurements from the fitting.
+%
+% Epn is the full set of measurements; E is that with the negative ones
+% removed.
+%
+% protocol is the full protocol; tempprot is that with the entries
+% corresponding to negative measurements removed.
+%
+% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
+%         Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+tempprot = protocol;
+E = Epn;
+if(min(Epn)<=0)
+    posonly = find(Epn>0);
+    E = Epn(posonly);
+    nonposonly = setdiff([1:size(Epn,1)], posonly);
+    tempprot.totalmeas = length(posonly);
+    
+    if (isfield(tempprot, 'b0_Indices'))
+        tempprot.b0_Indices = [];
+    end
+    if (isfield(tempprot, 'dti_subset'))
+        tempprot.dti_subset = [];
+    end
+    
+    for i=1:tempprot.totalmeas
+        if(isfield(tempprot, 'b0_Indices'))
+            if ismember(posonly(i), protocol.b0_Indices)
+                tempprot.b0_Indices = [tempprot.b0_Indices i];
+            end
+        end
+        if(isfield(tempprot, 'dti_subset'))
+            if ismember(posonly(i), protocol.dti_subset)
+                tempprot.dti_subset = [tempprot.dti_subset i];
+            end
+        end
+    end
+    if(isfield(tempprot, 'b0_Indices'))
+        tempprot.numZeros = length(tempprot.b0_Indices);
+        if length(tempprot.b0_Indices) == 0
+            error('All b=0 measurements are negative');
+        end
+    end
+    
+    if tempprot.totalmeas - length(tempprot.b0_Indices) < 6
+        error('Not enough DWI measurements');
+    end
+    
+    if(isfield(tempprot, 'dti_subset'))
+        if length(tempprot.dti_subset) - length(tempprot.b0_Indices) < 6
+            error('Not enough DWI measurements');
+        end
+    end
+    
+    if(strcmp(tempprot.pulseseq, 'PGSE') || strcmp(tempprot.pulseseq, 'STEAM'))
+        tempprot.G = tempprot.G(posonly);
+        tempprot.delta = tempprot.delta(posonly);
+        tempprot.smalldel = tempprot.smalldel(posonly);
+        tempprot.grad_dirs = tempprot.grad_dirs(posonly, :);
+        if(strcmp(tempprot.pulseseq, 'STEAM'))
+            tempprot.TM = tempprot.TM(posonly);
+            tempprot.TR = tempprot.TR(posonly);
+            tempprot.TE = tempprot.TE(posonly);
+        end
+        if(isfield(tempprot, 'TE'))
+            tempprot.TE = tempprot.TE(posonly);
+        end
+    else
+        error('Need to adapt for other pulse sequences.');
+    end
+end
+
+
diff --git a/NODDI_toolbox_v1.01/fitting/SaveAsNIfTI.m b/NODDI_toolbox_v1.01/fitting/SaveAsNIfTI.m
new file mode 100644
index 0000000000000000000000000000000000000000..7b272eb5a1a62080cafa2974637ae9ee6628bb2b
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/SaveAsNIfTI.m
@@ -0,0 +1,35 @@
+function SaveAsNIfTI(data, target, output)
+
+% function SaveAsNIfTI(data, nifti)
+%
+% Input:
+%
+% data: the data array to be saved to disk
+%
+% target: the NIfTI object specifying the target volume specification
+%
+% output: the filename for the output NIfTI file
+%
+
+% following the example in
+% http://niftilib.sourceforge.net/mat_api_html/README.txt
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+dat = file_array;
+dat.fname = output;
+dat.dim = target.dim;
+dat.dtype = 'FLOAT64-LE';
+dat.offset = ceil(348/8)*8;
+
+N = nifti;
+N.dat = dat;
+N.mat = target.mat;
+N.mat_intent = target.mat_intent;
+N.mat0 = target.mat0;
+N.mat0_intent = target.mat0_intent;
+
+create(N);
+
+N.dat(:,:,:,:) = data;
diff --git a/NODDI_toolbox_v1.01/fitting/SaveParamsAsNIfTI.m b/NODDI_toolbox_v1.01/fitting/SaveParamsAsNIfTI.m
new file mode 100644
index 0000000000000000000000000000000000000000..afac5892bc3adf784396a1647186cc0416142aeb
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/SaveParamsAsNIfTI.m
@@ -0,0 +1,153 @@
+function SaveParamsAsNIfTI(paramsfile, roifile, targetfile, outputpref)
+%
+% function SaveParamsAsNIfTI(paramsfile, roifile, targetfile, outputpref)
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+% load the fitting results
+fprintf('loading the fitted parameters from : %s\n', paramsfile);
+load(paramsfile);
+
+% load the roi file
+fprintf('loading the roi from : %s\n', roifile);
+load(roifile);
+
+% load the target volume
+fprintf('loading the target volume : %s\n', targetfile);
+target = nifti(targetfile);
+xsize = target.dat.dim(1);
+ysize = target.dat.dim(2);
+if length(target.dat.dim) == 2
+    zsize = 1;
+else
+    zsize = target.dat.dim(3);
+end
+total = xsize*ysize*zsize;
+
+% determine the volumes to be saved
+% the number of fitted parameters minus the two fibre orientation
+% parameters.
+idxOfFitted = find(model.GD.fixed(1:end-2)==0);
+noOfVols = length(idxOfFitted);
+vols = zeros(total,noOfVols);
+% the volume for the objective function values
+fobj_ml_vol = zeros(total,1);
+% the volume for the error code
+error_code_vol = zeros(total,1);
+% some special cases
+if (strfind(model.name, 'Watson'))
+    idxOfKappa = find(ismember(model.paramsStr, 'kappa')==1);
+    odi_vol = zeros(total,1);
+end
+
+% the volumes for the fibre orientations
+fibredirs_x_vol = zeros(total,1);
+fibredirs_y_vol = zeros(total,1);
+fibredirs_z_vol = zeros(total,1);
+% compute the fibre orientations from the estimated theta and phi.
+fibredirs = GetFibreOrientation(model.name, mlps);
+
+% determine the volumes with MCMC fitting to be saved
+if (model.noOfStages==3)
+    idxOfFittedMCMC = find(model.MCMC.fixed(1:end-2)==0);
+    noOfVolsMCMC = length(idxOfFittedMCMC);
+    volsMCMC = zeros(total,noOfVolsMCMC);
+
+    if (strfind(model.name, 'Watson'))
+        idxOfKappa = find(ismember(model.paramsStr, 'kappa')==1);
+	     if (model.MCMC.fixed(idxOfKappa)==0)
+            odi_volMCMC = zeros(total,1);
+        end
+    end
+end
+
+% convert to volumetric maps
+fprintf('converting the fitted parameters into volumetric maps ...\n');
+for i=1:size(mlps,1)
+    % compute the index to 3D
+    volume_index = (idx(i,3)-1)*ysize*xsize + (idx(i,2)-1)*xsize + idx(i,1);
+    
+    % fitted parameters other than the fiber orientations
+    for j=1:length(idxOfFitted)
+        vols(volume_index,j) = mlps(i, idxOfFitted(j));
+    end
+    
+    % objective function values
+    fobj_ml_vol(volume_index) = fobj_ml(i);
+    
+    % error codes
+    error_code_vol(volume_index) = error_code(i);
+    
+    % fiber orientations
+    fibredirs_x_vol(volume_index) = fibredirs(1,i);
+    fibredirs_y_vol(volume_index) = fibredirs(2,i);
+    fibredirs_z_vol(volume_index) = fibredirs(3,i);
+    
+    % special cases
+    if (strfind(model.name, 'Watson'))
+        odi_vol(volume_index) = atan2(1, mlps(i,idxOfKappa)*10)*2/pi;
+    end
+    
+	 % MCMC fitted parameters
+    if (model.noOfStages==3)
+        for j=1:length(idxOfFittedMCMC)
+            volsMCMC(volume_index,j) = mean(squeeze(mcmcps(i,:,j)));
+        end
+        if (strfind(model.name, 'Watson'))
+            % Warning: Here we hard-coded the index to kappa!!!
+            odi_volMCMC(volume_index) = atan2(1, mean(squeeze(mcmcps(i,:,3)))*10)*2/pi;
+        end
+    end
+    
+end
+
+% save as NIfTI
+fprintf('Saving the volumetric maps of the fitted parameters ...\n');
+
+niftiSpecs.dim = [xsize ysize zsize];
+niftiSpecs.mat = target.mat;
+niftiSpecs.mat_intent = target.mat_intent;
+niftiSpecs.mat0 = target.mat0;
+niftiSpecs.mat0_intent = target.mat0_intent;
+
+% the fitted parameters other than the fiber orientations
+for i=1:length(idxOfFitted)
+    output = [outputpref '_' cell2mat(model.paramsStr(idxOfFitted(i))) '.nii'];
+    SaveAsNIfTI(reshape(squeeze(vols(:,i)), [xsize ysize zsize]), niftiSpecs, output);
+end
+
+% the special cases
+if (strfind(model.name, 'Watson'))
+    output = [outputpref '_' 'odi.nii'];
+    SaveAsNIfTI(reshape(odi_vol, [xsize ysize zsize]), niftiSpecs, output);
+end
+
+% the objective function values
+output = [outputpref '_' 'fmin.nii'];
+SaveAsNIfTI(reshape(fobj_ml_vol, [xsize ysize zsize]), niftiSpecs, output);
+
+% the error codes
+output = [outputpref '_' 'error_code.nii'];
+SaveAsNIfTI(reshape(error_code_vol, [xsize ysize zsize]), niftiSpecs, output);
+
+% the fibre orientations
+output = [outputpref '_' 'fibredirs_xvec.nii'];
+SaveAsNIfTI(reshape(fibredirs_x_vol, [xsize ysize zsize]), niftiSpecs, output);
+output = [outputpref '_' 'fibredirs_yvec.nii'];
+SaveAsNIfTI(reshape(fibredirs_y_vol, [xsize ysize zsize]), niftiSpecs, output);
+output = [outputpref '_' 'fibredirs_zvec.nii'];
+SaveAsNIfTI(reshape(fibredirs_z_vol, [xsize ysize zsize]), niftiSpecs, output);
+
+% the MCMC fitted parameters
+if (model.noOfStages==3)
+    for i=1:length(idxOfFittedMCMC)
+        output = [outputpref '_' cell2mat(model.paramsStr(idxOfFittedMCMC(i))) '_MCMC.nii'];
+        SaveAsNIfTI(reshape(squeeze(volsMCMC(:,i)), [xsize ysize zsize]), niftiSpecs, output);
+    end
+    if (strfind(model.name, 'Watson'))
+        output = [outputpref '_' 'odi_MCMC.nii'];
+        SaveAsNIfTI(reshape(odi_volMCMC, [xsize ysize zsize]), niftiSpecs, output);
+    end
+end
+
diff --git a/NODDI_toolbox_v1.01/fitting/SchemeToProtocol.m b/NODDI_toolbox_v1.01/fitting/SchemeToProtocol.m
new file mode 100644
index 0000000000000000000000000000000000000000..45a1c361ab192b71512e730ec9cd6e8d89590017
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/SchemeToProtocol.m
@@ -0,0 +1,34 @@
+function protocol = SchemeToProtocol(schemefile)
+%
+% Reads a Camino Version 1 schemefile into a protocol object
+%
+% function protocol = SchemeToProtocol(schemefile)
+%
+% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
+%         Gary Hui Zhang     (gary.zhang@ucl.ac.uk)
+%
+
+fid = fopen(schemefile, 'r', 'b');
+
+% Read in the header (assumes one line)
+%A = fscanf(fid, '%c', 10);
+A = fgetl(fid);
+
+% Read in the data
+A = fscanf(fid, '%f', [7, inf]);
+
+fclose(fid);
+
+% Create the protocol
+protocol.pulseseq = 'PGSE';
+protocol.grad_dirs = A(1:3,:)';
+protocol.G = A(4,:);
+protocol.delta = A(5,:);
+protocol.smalldel = A(6,:);
+protocol.TE = A(7,:);
+protocol.totalmeas = length(A);
+
+% Find the B0's
+bVals = GetB_Values(protocol);
+protocol.b0_Indices = find(bVals==0);
+
diff --git a/NODDI_toolbox_v1.01/fitting/ThreeStageFittingVoxel.m b/NODDI_toolbox_v1.01/fitting/ThreeStageFittingVoxel.m
new file mode 100644
index 0000000000000000000000000000000000000000..890594e955c00b011ad727222ac1656d1f7de550
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/ThreeStageFittingVoxel.m
@@ -0,0 +1,219 @@
+function [gsps, fobj_gs, mlps, fobj_ml, error_code, ps] = ThreeStageFittingVoxel(Epn, protocol, model, verbose)
+% Performs the three stage fitting routine used for the human data in
+% Alexander et al NeuroImage 2000.  The three stages are grid search,
+% maximum likelihood gradient descent and MCMC with a Rician noise model.
+%
+% function [gsps, fobj_gs, mlps, fobj_ml, error_code, ps] = ThreeStageFittingVoxel(Epn, protocol, model, verbose)
+%
+% protocol is the measurement protocol.
+%
+% model is the model structure created with MakeModel
+%
+% verbose: optional, 1 for printing verbose messages, 0 for quiet (default)
+%
+% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
+%         Gary Hui Zhang     (gary.zhang@ucl.ac.uk)
+%
+
+if nargin < 4
+	verbose = 0;
+end
+
+%% Initialization
+
+warning off all
+
+% Get the required variables
+modelname = model.name;
+noOfStages = model.noOfStages;
+tissuetype = model.tissuetype;
+GS = model.GS;
+GD = model.GD;
+MCMC = model.MCMC;
+
+% Initialize the output
+error_code = 0;
+gsps = zeros(1, model.numParams);
+mlps = gsps;
+fobj_gs = 0;
+fobj_ml = 0;
+
+% Constants used during grid search and gradient descent
+constantsGD.roots_cyl = BesselJ_RootsCyl(30);
+
+%% First remove non-positive measurements
+try
+    [Epn, protocol] = RemoveNegMeas(Epn, protocol);
+catch err
+    error_code = 1;
+    disp(err);
+    return;
+end
+
+%% Determine the sigma
+sig = EstimateSigma(Epn, protocol, model);
+
+%% Grid Search stage
+
+if verbose
+    fprintf('Grid Search fitting with %s\n', modelname);
+end
+
+% Set up the search grid
+grid = GetSearchGrid(modelname, tissuetype, GS.fixed, GS.fixedvals);
+
+% Run the grid search
+[x0 liks] = GridSearchRician(Epn, modelname, grid, protocol, constantsGD, sig);
+gsps = x0(1:(end-1));
+fobj_gs = max(liks);
+if verbose
+    if (strcmp(modelname, 'StickIsoV_B0'))
+        fprintf('gsps: %5.4f %2.1f %2.1f %5.4f %2.1f %5.1f %5.4f %5.4f : %e\n', gsps, fobj_gs)
+    elseif (strcmp(modelname, 'StickTortIsoV_B0'))
+        fprintf('gsps: %5.4f %2.1f %5.4f %2.1f %5.1f %5.4f %5.4f : %e\n', gsps, fobj_gs)
+    elseif (strcmp(modelname, 'WatsonSHStickTortIsoV_B0'))
+        fprintf('gsps: %5.4f %2.1f %5.4f %5.4f %2.1f %5.1f %5.4f %5.4f : %e\n', gsps, fobj_gs)
+    elseif (strcmp(modelname, 'WatsonSHStickTortIsoVIsoDot_B0'))
+        fprintf('gsps: %5.4f %2.1f %5.4f %5.4f %2.1f %5.4f %5.1f %5.4f %5.4f : %e\n', gsps, fobj_gs)
+    elseif (strcmp(modelname, 'BinghamStickTortIsoV_B0'))
+        fprintf('gsps: %5.4f %2.1f %5.4f %5.4f %5.4f %5.4f %2.1f %5.1f %5.4f %5.4f : %e\n', gsps, fobj_gs)
+    else
+        disp(fobj_gs);
+        disp(gsps);
+    end
+end
+
+if noOfStages == 1
+    return;
+end
+
+%% Gradient Descent stage
+
+if verbose
+    fprintf('Gradient Descent fitting with %s\n', modelname);
+end
+
+h=optimset('Algorithm', 'active-set', 'Display', 'iter', 'MaxIter',100,...
+           'MaxFunEvals',20000,'TolX',1e-6,...
+           'TolFun',1e-6,'GradObj','off', 'Hessian', 'off', 'FunValCheck',...
+           'on', 'Display', 'off');%,'DerivativeCheck','on');
+
+% Convert from actual parameters to optimized quantities that enforce
+% constraints.
+startx = GradDescEncode(modelname, gsps);
+fobj_ml = fobj_gs;
+mlps = gsps;
+if (strcmp(GD.type, 'multistart'))
+    noOfIterations = GD.multistart.noOfRuns;
+    perturbation = GD.multistart.perturbation;
+    if isempty(find(perturbation~=0, 1))
+        error('multistart mode: at least one perturbation should be nonzero');
+    else
+        perturbation(GD.fixed==1) = 0;
+    end
+    if verbose
+        fprintf('Multistart fitting with %i trials\n', noOfIterations);
+        fprintf('Parameter perturbation adjusted for fixed variables');
+    end
+else
+    noOfIterations = 1;
+end
+
+% Get limits and constraints for gradient descent
+[MinValGD MaxValGD] = GradDescLimits(modelname);
+
+% Get orientation dispersion index, if applicable
+kappaIdx = GetParameterIndex(modelname, 'kappa');
+
+for i=1:noOfIterations
+    if i==1
+        parameter_input = startx;
+    else
+        parameter_input = startx.*(1 + perturbation.*randn(1,length(perturbation)));
+    end
+    
+    try
+        % optimize with orientation fixed
+        fixedGD = GD.fixed;
+        fixedGD(end-1:end) = 1;
+        % if kappa is a parameter, fix it first as well
+        if (kappaIdx ~= -1)
+            fixedGD(kappaIdx) = 1;
+        end
+        % Account for any fixed parameters
+        fittedMinValGD = MinValGD(fixedGD==0);
+        fittedMaxValGD = MaxValGD(fixedGD==0);
+        [parameter_hat,RESNORM,EXITFLAG,OUTPUT]=fmincon_fix(fixedGD, 'fobj_rician_fix',...
+            parameter_input,[],[],[],[],fittedMinValGD,fittedMaxValGD,[],h,Epn,protocol, modelname, sig, constantsGD);
+        parameter_input = parameter_hat;
+        
+        % now optimize all free variables
+        % Account for any fixed parameters
+        fittedMinValGD = MinValGD(GD.fixed==0);
+        fittedMaxValGD = MaxValGD(GD.fixed==0);
+        [parameter_hat,RESNORM,EXITFLAG,OUTPUT]=fmincon_fix(GD.fixed, 'fobj_rician_fix',...
+            parameter_input,[],[],[],[],fittedMinValGD,fittedMaxValGD,[],h,Epn,protocol, modelname, sig, constantsGD);
+        
+        if (-RESNORM > fobj_ml)
+            fobj_ml = -RESNORM;
+            mlps = GradDescDecode(modelname, parameter_hat);
+        end
+        if (verbose)
+            disp(fobj_ml);
+        end
+    catch err
+        error_code = 2;
+        disp(err);
+        return;
+    end
+    
+end
+
+if verbose
+    if (strcmp(modelname, 'StickIsoV_B0'))
+        fprintf('mlps: %5.4f %2.1f %2.1f %5.4f %2.1f %5.1f %5.4f %5.4f : %e\n', mlps, fobj_ml)
+    elseif (strcmp(modelname, 'StickTortIsoV_B0'))
+        fprintf('mlps: %5.4f %2.1f %5.4f %2.1f %5.1f %5.4f %5.4f : %e\n', mlps, fobj_ml)
+    elseif (strcmp(modelname, 'WatsonSHStickTortIsoV_B0'))
+        fprintf('mlps: %5.4f %2.1f %5.4f %5.4f %2.1f %5.1f %5.4f %5.4f : %e\n', mlps, fobj_ml)
+    elseif (strcmp(modelname, 'WatsonSHStickTortIsoVIsoDot_B0'))
+        fprintf('mlps: %5.4f %2.1f %5.4f %5.4f %2.1f %5.4f %5.1f %5.4f %5.4f : %e\n', mlps, fobj_ml)
+    elseif (strcmp(modelname, 'BinghamStickTortIsoV_B0'))
+        fprintf('mlps: %5.4f %2.1f %5.4f %5.4f %5.4f %5.4f %2.1f %5.1f %5.4f %5.4f : %e\n', mlps, fobj_ml)
+    else
+        disp(fobj_ml);
+        disp(mlps);
+    end
+end
+
+if noOfStages == 2
+    return;
+end
+
+%% MCMC stage
+
+if verbose
+    fprintf('MCMC fitting with %s\n', modelname);
+end
+
+% Get limits and constraints for MCMC
+[MinValMCMC MaxValMCMC] = MCMC_Limits(modelname);
+
+% MCMC parameters
+steplengths = MCMC.steplengths;
+burnin = MCMC.burnin;
+interval = MCMC.interval;
+samples = MCMC.samples;
+
+% Constants used during MCMC
+constantsMCMC.roots_cyl = BesselJ_RootsCyl(20);
+
+% Run the MCMC procedure
+x0t = [mlps sig];
+
+ps(:,:) = RicianMCMC(Epn, x0t, modelname, protocol, MinValMCMC, MaxValMCMC, constantsMCMC, MCMC.fixed, steplengths, burnin, samples, interval);
+mcmcps = squeeze(mean(ps,1));
+
+if verbose
+    disp(mcmcps);
+end
diff --git a/NODDI_toolbox_v1.01/fitting/VoxelDataViewer.m b/NODDI_toolbox_v1.01/fitting/VoxelDataViewer.m
new file mode 100644
index 0000000000000000000000000000000000000000..0cc24faaf308bd73e83c60e51d8a8093757812c0
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/VoxelDataViewer.m
@@ -0,0 +1,70 @@
+function VoxelDataViewer(protocol, data, fibredir, b0, h, style)
+% Plots the normalized measurements in one image voxel against the
+% absolute dot product of the gradient and fibre directions.
+%
+% VoxelDataViewer(protocol, data, fibredir, b0, h)
+% brings up a window containing the plot.
+%
+% protocol is the imaging protocol.
+%
+% data is the set of measurements in the voxel.
+%
+% fibredir is an estimate of the fibre direction in that voxel. By default
+% this is set to the z-axis
+%
+% b0 is an estimate of the b=0 signal.  By default, this is set to one.
+%
+% h is a figure handle to add the plot to.  If not specified, a new figure
+% appears.
+%
+% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
+%         Gary Hui Zhang     (gary.zhang@ucl.ac.uk)
+%
+
+if(nargin<3)
+    fibredir = [0 0 1]';
+end
+if(nargin<4)
+    b0=1;
+end
+if(nargin<5)
+    h = figure;
+end
+
+% Compute b-values
+GAMMA = 2.675987E8;
+modQ = GAMMA*protocol.usmalldel.*protocol.uG;
+diffTime = (protocol.udelta - protocol.usmalldel/3);
+bvals = diffTime.*modQ.^2;
+
+% Create normalized data set.
+normdw = data/b0;
+
+if(nargin<6)
+    style = 'x';
+end
+
+linedef{1} = ['r', style];
+linedef{2} = ['b', style];
+linedef{3} = ['g', style];
+linedef{4} = ['m', style];
+linedef{5} = ['c', style];
+linedef{6} = ['k', style];
+linedef{7} = ['y', style];
+
+hold on;
+set(gca, 'FontName', 'Times');
+set(gca, 'FontSize', 17);
+for j=1:length(protocol.uG)
+    inds = find(protocol.G == protocol.uG(j) & protocol.delta == protocol.udelta(j) & protocol.smalldel == protocol.usmalldel(j));
+    scatter(abs(protocol.grad_dirs(inds,:)*fibredir), normdw(inds), linedef{j});
+end
+xlabel('|n.G|/|G|_{max}');
+ylabel('S/S_0');
+%ylim([0,b0*1.1]);
+
+% Add b=0 measurements
+b0_meas = data(protocol.b0_Indices);
+for b=1:length(b0_meas)
+    h(1) = plot([0 1], [b0_meas(b)/b0 b0_meas(b)/b0], ':k');
+end
diff --git a/NODDI_toolbox_v1.01/fitting/batch_fitting.m b/NODDI_toolbox_v1.01/fitting/batch_fitting.m
new file mode 100644
index 0000000000000000000000000000000000000000..5806ea9ccaf12869de864e31e37551f1c59494dd
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/batch_fitting.m
@@ -0,0 +1,130 @@
+function batch_fitting(roifile, protocol, model, outputfile, poolsize)
+
+%
+% function batch_fitting(roifile, protocol, model, outputfile, poolsize)
+%
+% This function does batch fitting to the voxels in an entire ROI created with
+% CreateROI function.
+%
+% Input:
+%
+% roifile: the ROI file created with CreateROI
+%
+% protocol: the protocol object created with FSL2Protocol
+%
+% model: the model object created with MakeModel
+%
+% outputfile: the name of the mat file to store the fitted parameters
+%
+% poolsize (optional): the number of parallel processes to run
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+% first check if there is a file there to resume
+if exist(outputfile, 'file')
+    load(outputfile);
+    if exist('split_end', 'var')
+        % previously run and need to be restarted
+        current_split_start = split_end + 1;
+        fprintf('Resume an interrupted run from %i\n', current_split_start);
+    else
+        % completed
+        fprintf('An output file of the same name detected.\n');
+        fprintf('Choose a different output file name.\n');
+        return;
+    end
+else
+    % if this is the first run
+    current_split_start = 1;
+end
+
+% initiate the parallel environment if necessary
+pool = gcp('nocreate');
+if	isempty(pool)
+    if (nargin < 5)
+        pool = parpool('local');
+    else
+        pool = parpool('local', poolsize);
+    end
+end
+
+% load the roi file
+load(roifile);
+numOfVoxels = size(roi,1);
+
+% set up the fitting parameter variables if it is the first run
+if current_split_start == 1
+    gsps = zeros(numOfVoxels, model.numParams);
+    mlps = zeros(numOfVoxels, model.numParams);
+    fobj_gs = zeros(numOfVoxels, 1);
+    fobj_ml = zeros(numOfVoxels, 1);
+    error_code = zeros(numOfVoxels, 1);
+    if model.noOfStages == 3
+        mcmcps = zeros(numOfVoxels, model.MCMC.samples, model.numParams + 1);
+    end
+end
+
+% set up the PARFOR Progress Monitor
+[mypath myname myext] = fileparts(mfilename('fullpath'));
+mypath = [mypath '/../ParforProgMonv2/java'];
+pctRunOnAll(['javaaddpath '  mypath]);
+progressStepSize = 100;
+ppm = ParforProgMon(['Fitting ' roifile, ' : '], numOfVoxels-current_split_start+1,...
+                    progressStepSize, 400, 80);
+
+tic
+
+fprintf('%i of voxels to fit\n', numOfVoxels-current_split_start+1);
+
+% start the parallel fitting
+for split_start=current_split_start:progressStepSize:numOfVoxels
+    % set up the split end
+    split_end = split_start + progressStepSize - 1;
+    if split_end > numOfVoxels
+        split_end = numOfVoxels;
+    end
+    
+    % fit the split
+    parfor i=split_start:split_end
+        
+        % get the MR signals for the voxel i
+        voxel = roi(i,:)';
+        
+        % fit the voxel
+        if model.noOfStages == 2
+            [gsps(i,:), fobj_gs(i), mlps(i,:), fobj_ml(i), error_code(i)] = ThreeStageFittingVoxel(voxel, protocol, model);
+        else
+            [gsps(i,:), fobj_gs(i), mlps(i,:), fobj_ml(i), error_code(i), mcmcps(i,:,:)] = ThreeStageFittingVoxel(voxel, protocol, model);
+        end
+        
+        % report to the progress monitor
+        if mod(i, progressStepSize)==0
+            ppm.increment();
+        end
+        
+    end
+    
+    % save the temporary results of the split
+    if model.noOfStages == 2
+        save(outputfile, 'split_end', 'model', 'gsps', 'fobj_gs', 'mlps', 'fobj_ml', 'error_code');
+    else
+        save(outputfile, 'split_end', 'model', 'gsps', 'fobj_gs', 'mlps', 'fobj_ml', 'mcmcps', 'error_code');
+    end
+    
+end
+
+toc
+
+ppm.delete();
+
+% save the fitted parameters
+if model.noOfStages == 2
+    save(outputfile, 'model', 'gsps', 'fobj_gs', 'mlps', 'fobj_ml', 'error_code');
+else
+    save(outputfile, 'model', 'gsps', 'fobj_gs', 'mlps', 'fobj_ml', 'mcmcps', 'error_code');
+end
+
+% close the parallel pool
+delete pool;
+
diff --git a/NODDI_toolbox_v1.01/fitting/batch_fitting_single.m b/NODDI_toolbox_v1.01/fitting/batch_fitting_single.m
new file mode 100644
index 0000000000000000000000000000000000000000..9b7c92e7fada75ff8d081dd3deaeae7a15f80640
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/batch_fitting_single.m
@@ -0,0 +1,95 @@
+function batch_fitting_single(roifile, protocol, model, outputfile)
+
+%
+% function batch_fitting_single(roifile, protocol, model, outputfile)
+%
+% This function does batch fitting to the voxels in an entire ROI created with
+% CreateROI function.
+%
+% Input:
+%
+% roifile: the ROI file created with CreateROI
+%
+% protocol: the protocol object created with FSL2Protocol
+%
+% model: the model object created with MakeModel
+%
+% outputfile: the name of the mat file to store the fitted parameters
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+
+% first check if there is a file there to resume
+if exist(outputfile, 'file')
+    load(outputfile);
+    if exist('current_index', 'var')
+        % previously run and need to be restarted
+        current_index = current_index + 1;
+        fprintf('Resume an interrupted run from voxel %i\n', current_index);
+    else
+        % completed
+        fprintf('An output file of the same name detected.\n');
+        fprintf('Choose a different output file name.\n');
+        return;
+    end
+else
+    % if this is the first run
+    current_index = 1;
+end
+
+% load the roi file
+load(roifile);
+numOfVoxels = size(roi,1);
+
+% set up the fitting parameter variables if it is the first run
+if current_index == 1
+    gsps = zeros(numOfVoxels, model.numParams);
+    mlps = zeros(numOfVoxels, model.numParams);
+    fobj_gs = zeros(numOfVoxels, 1);
+    fobj_ml = zeros(numOfVoxels, 1);
+    error_code = zeros(numOfVoxels, 1);
+    if model.noOfStages == 3
+        mcmcps = zeros(numOfVoxels, model.MCMC.samples, model.numParams + 1);
+    end
+end
+
+tic
+
+fprintf('%i of voxels to fit\n', numOfVoxels-current_index+1);
+
+% start the parallel fitting
+for i=current_index:numOfVoxels
+    
+    fprintf('Fitting voxel %i\n', i);
+    
+    % get the MR signals for the voxel i
+    voxel = roi(i,:)';
+    
+    % fit the voxel
+    if model.noOfStages == 2
+        [gsps(i,:), fobj_gs(i), mlps(i,:), fobj_ml(i), error_code(i)] = ThreeStageFittingVoxel(voxel, protocol, model);
+    else
+        [gsps(i,:), fobj_gs(i), mlps(i,:), fobj_ml(i), error_code(i), mcmcps(i,:,:)] = ThreeStageFittingVoxel(voxel, protocol, model);
+    end
+    
+    % save the temporary results
+    if mod(i, 100)==0
+        current_index = i;
+        if model.noOfStages == 2
+            save(outputfile, 'current_index', 'model', 'gsps', 'fobj_gs', 'mlps', 'fobj_ml', 'error_code');
+        else
+            save(outputfile, 'current_index', 'model', 'gsps', 'fobj_gs', 'mlps', 'fobj_ml', 'mcmcps', 'error_code');
+        end
+    end
+    
+end
+
+toc
+
+% save the fitted parameters
+if model.noOfStages == 2
+    save(outputfile, 'model', 'gsps', 'fobj_gs', 'mlps', 'fobj_ml', 'error_code');
+else
+    save(outputfile, 'model', 'gsps', 'fobj_gs', 'mlps', 'fobj_ml', 'mcmcps', 'error_code');
+end
diff --git a/NODDI_toolbox_v1.01/fitting/fmincon_fix.m b/NODDI_toolbox_v1.01/fitting/fmincon_fix.m
new file mode 100644
index 0000000000000000000000000000000000000000..3ed93ba3478f39d3c52f6c401b095019cd676fe2
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/fmincon_fix.m
@@ -0,0 +1,23 @@
+function [x,fval,exitflag,output,lambda,grad,hessian] = fmincon_fix(fix,fun,x0,A,b,Aeq,beq,lb,ub,nonlcon,options,varargin)
+% Wrapper for fmincon that allows the user to specify a number of model
+% parameters that remain fixed to the initial settings.
+%
+% fix is a binary array.  Zero indicates that the parameter in the
+% corresponding position in x0 varies during fitting; one indicates that
+% the value remains fixed at the alue in x0.
+%
+% The other parameters are all as for fmincon.
+%
+% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
+%
+
+% Construct the parameter vector with fixed values removed.
+x0f = x0(find(fix==0));
+
+% Run the opt.
+[x,fval,exitflag,output,lambda,grad,hessian] = fmincon(fun,x0f,A,b,Aeq,beq,lb,ub,nonlcon,options,varargin{:}, fix, x0);
+
+% Reconstruct the full fitted parameter list including the fixed values.
+xf = fix.*x0;
+xf(find(fix==0)) = x;
+x = xf;
diff --git a/NODDI_toolbox_v1.01/fitting/fobj_rician.m b/NODDI_toolbox_v1.01/fitting/fobj_rician.m
new file mode 100644
index 0000000000000000000000000000000000000000..7acb8c74ddae85f3a7ef22a37ed99f9d2a50bf36
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/fobj_rician.m
@@ -0,0 +1,43 @@
+function [sumRes, resJ, H]=fobj_rician(x, meas, protocol, model, sig, constants)
+% Objective function for fitting models using a Rician noise  model.
+%
+% x is the encoded model parameter values
+%
+% meas is the measurements
+%
+% protocol is the measurement protocol
+%
+% model is a string encoding the model
+%
+% sig is the standard deviation of the Gaussian distributions underlying
+% the Rician noise
+%
+% constants contains values required to compute the model signals.
+%
+% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
+%
+
+% Need to transform to actual parameter values from optimized quantities.
+xdec = GradDescDecode(model, x);
+
+scale = GetScalingFactors(model);
+if (strcmp(model, 'ExCrossingCylSingleRadGPD') ||...
+    strcmp(model, 'ExCrossingCylSingleRadIsoDotTortIsoV_GPD_B0'))
+    xsc = xdec(1:(end-4))./scale(1:(end-1));
+    theta = [xdec(end-3) xdec(end-1)]';
+    phi = [xdec(end-2) xdec(end)]';
+    fibredir = [cos(phi).*sin(theta) sin(phi).*sin(theta) cos(theta)]';
+else
+    xsc = xdec(1:(end-2))./scale(1:(end-1));
+    theta = xdec(end-1);
+    phi = xdec(end);
+    fibredir = [cos(phi)*sin(theta) sin(phi)*sin(theta) cos(theta)]';
+end
+
+if(nargout == 1)
+    sumRes = fobj_rician_st(xsc, meas, protocol, model, sig, fibredir, constants);
+elseif(nargout == 2)
+    [sumRes resJ] = fobj_rician_st(xsc, meas, protocol, model, sig, fibredir, constants);
+else
+    [sumRes, resJ, H] = fobj_rician_st(xsc, meas, protocol, model, sig, fibredir, constants);
+end
diff --git a/NODDI_toolbox_v1.01/fitting/fobj_rician_fix.m b/NODDI_toolbox_v1.01/fitting/fobj_rician_fix.m
new file mode 100644
index 0000000000000000000000000000000000000000..2d9231dbb02d6cddfa40a76072a5c1cb37a85ca5
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/fobj_rician_fix.m
@@ -0,0 +1,36 @@
+function [sumRes, resJ, H]=fobj_rician_fix(x, meas, protocol, model, sig, constants, fix, x0)
+% Wrapper for fobj_rician for use with fmincon_fix.
+%
+% x is the encoded model parameter values
+%
+% meas is the measurements
+%
+% protocol is the measurement protocol
+%
+% model is a string encoding the model
+%
+% sig is the standard deviation of the Gaussian distributions underlying
+% the Rician noise
+%
+% constants contains values required to compute the model signals.
+%
+% fix is a binary array specifying which parameters are fixed and which
+% vary.
+%
+% x0 is the full starting point including the fixed parameters.
+%
+% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
+%
+
+% Construct the full parameter list including fixed values.
+xf = fix.*x0;
+xf(find(fix==0)) = x;
+
+% Now call the full objective function.
+if(nargout == 1)
+    sumRes = fobj_rician(xf, meas, protocol, model, sig, constants);
+elseif(nargout == 2)
+    [sumRes resJ] = fobj_rician(xf, meas, protocol, model, sig, constants);
+else
+    [sumRes, resJ, H] = fobj_rician(xf, meas, protocol, model, sig, constants);
+end
diff --git a/NODDI_toolbox_v1.01/fitting/fobj_rician_st.m b/NODDI_toolbox_v1.01/fitting/fobj_rician_st.m
new file mode 100644
index 0000000000000000000000000000000000000000..8206c3cb186212bf068c5c527f62826b2428d4ab
--- /dev/null
+++ b/NODDI_toolbox_v1.01/fitting/fobj_rician_st.m
@@ -0,0 +1,69 @@
+function [sumRes, resJ, H] = fobj_rician_st(xsc, meas, protocol, model, sig, fibredir, constants)
+% General function called by variants of fobj_rician once fibre direction
+% has been extracted and other parameters scaled appropriately.
+%
+% xsc is the decoded model parameter values
+%
+% meas is the measurements
+%
+% protocol is the measurement protocol
+%
+% model is a string encoding the model
+%
+% sig is the standard deviation of the Gaussian distributions underlying
+% the Rician noise
+%
+% fibredir is the fibre direction extracted from the full parameter list.
+%
+% constants contains values required to compute the model signals.
+%
+% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
+%
+
+E = SynthMeas(model, xsc, protocol, fibredir, constants);
+
+% Find the fitting error (log probabilities of the data given the parameter
+% settings).
+sumRes = -RicianLogLik(meas, E, sig);
+
+if(nargout>1)
+    % Construct the Jacobian of the probabilities from the Jacobian of the
+    % measurement estimates.
+    scp = meas.*signals./(sig.^2);
+    ysc = besseli1d0(scp);
+    sc = (E - meas.*ysc)./(sig.^2);
+    J = zeros(length(E), length(x));
+    for i=1:(length(x)-1)
+        J(:,i) = sc.*Jnn(:,i);
+    end
+
+    % Need to rescale the derivates to the scale of x
+    J = J./repmat(scale(1:(end-1)),[length(E),1]);
+
+    % Now sum over the measurements
+    resJ = sum(J);
+end
+
+% Finally create the Hessian matrix.  Here in fact we use the Fisher
+% information matrix instead to reduce computation and increase stability
+% and convergence.  Code is the same as FishMatRician.m.
+% if(nargout>2)
+%     global RicCorX RicCorY;
+% 
+%     C = zeros(length(E),1);
+%     Esc = E/sig;
+%     out = find(Esc>=max(RicCorX));
+%     in = find(Esc<max(RicCorX));
+%     C(in) = interp1(RicCorX, RicCorY, Esc(in))*sig^2;
+%     C(out) = sig^2;
+%     JCor = Jnn.*repmat(C, [1,length(x)-1]);
+% 
+%     H = Jnn'*JCor/(sig^4);
+%     
+%     % Now compute the elements that depend on sigma.
+%     Jsig = Jnn.*repmat(sig^2*E + E.^3 + 2*E.*C, [1,length(x)-1]);
+%     H(length(x), 1:(length(x)-1)) = -2*sum(Jsig)/(sig^5);
+%     H(1:(length(x)-1), length(x)) = squeeze(H(length(x), 1:(length(x)-1))');
+% 
+%     H(length(x), length(x)) = -4*sum(-sig^4 + sig^2*E.^2 - E.^2.*C)/(sig^6);
+% end
diff --git a/NODDI_toolbox_v1.01/models/BesselJ_RootsCyl.m b/NODDI_toolbox_v1.01/models/BesselJ_RootsCyl.m
new file mode 100644
index 0000000000000000000000000000000000000000..4ca982b30542caf5ed9fc80e7e46db5365c0f308
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/BesselJ_RootsCyl.m
@@ -0,0 +1,31 @@
+function root = BesselJ_RootsCyl(starts)
+% BesselJ_RootsCyl(starts) finds the roots of the equation J'_1(x) = 0
+% where J_1 is the first order Bessel function of the first kind.
+%
+% starts is the number of starting points in the search for
+% roots.  The larger it is, the more roots are returned in the root array.
+% The default is 20, which returns 6 roots.  starts = 100 returns 32 roots.
+% Generally the number of roots is just under 1/3 the number of starting
+% points.
+%
+% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
+%
+
+if(nargin==0)
+    starts = 20;
+end
+
+f = @(x)(0.5*(besselj(0,x) - besselj(2,x)));
+
+% Get a good list of starting points
+y = 0:0.1:starts;
+dj1 = f(y);
+starts = (find(dj1(1:end-1).*dj1(2:end)<0)+1)*0.1;
+
+for s=1:length(starts)
+    root(s) = fzero(f,starts(s));
+end
+
+
+
+
diff --git a/NODDI_toolbox_v1.01/models/CylNeumanLePar_PGSE.m b/NODDI_toolbox_v1.01/models/CylNeumanLePar_PGSE.m
new file mode 100644
index 0000000000000000000000000000000000000000..2db0dd634836337d0ac1dcfa76910bc97eff8191
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/CylNeumanLePar_PGSE.m
@@ -0,0 +1,42 @@
+function [LE,J]=CylNeumanLePar_PGSE(x, G, delta, smalldel)
+% Substrate: Parallel, impermeable cylinders with one radius in an empty
+%            background.
+% Pulse sequence: Pulsed gradient spin echo
+% Signal approximation: Gaussian phase distribution.
+%
+% [LE,J]=CylNeumanLePar_PGSE(x, G, delta, smalldel)
+% returns the log signal attenuation in parallel direction (LePar) according
+% to the Neuman model and the Jacobian J of LePar with respect to the
+% parameters.  The Jacobian does not include derivates with respect to the
+% fibre direction.
+%
+% x is the list of model parameters in SI units:
+% x(1) is the diffusivity of the material inside the cylinders.
+%
+% G, delta and smalldel are the gradient strength, pulse separation and
+% pulse length of each measurement in the protocol.  Each has
+% size [N 1].
+%
+% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
+%         Gary Hui Zhang     (gary.zhang@ucl.ac.uk)
+%
+
+d=x(1);
+
+% Radial wavenumbers
+GAMMA = 2.675987E8;
+modQ = GAMMA*smalldel.*G;
+modQ_Sq = modQ.^2;
+
+% diffusion time for PGSE, in a matrix for the computation below.
+difftime = (delta-smalldel/3);
+
+% Parallel component
+LE =-modQ_Sq.*difftime*d;
+
+% Compute the Jacobian matrix
+if(nargout>1)
+    % dLE/d
+    J = -modQ_Sq.*difftime;
+end
+
diff --git a/NODDI_toolbox_v1.01/models/CylNeumanLePerp_PGSE.m b/NODDI_toolbox_v1.01/models/CylNeumanLePerp_PGSE.m
new file mode 100644
index 0000000000000000000000000000000000000000..466cdc7badf092505c3a83d223059368c458691c
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/CylNeumanLePerp_PGSE.m
@@ -0,0 +1,137 @@
+function [LE,J]=CylNeumanLePerp_PGSE(d, R, G, delta, smalldel, roots)
+% Substrate: Parallel, impermeable cylinders with one radius in an empty
+%            background.
+% Pulse sequence: Pulsed gradient spin echo
+% Signal approximation: Gaussian phase distribution.
+%
+% [LE,J] = CylNeumanLePerp_PGSE(d, R, G, delta, smalldel, roots)
+%
+% returns the log signal attenuation in perpendicular direction (LePerp) for
+% EACH RADIUS specified in R according to the Neuman model and the Jacobian J
+% of LePerp with respect to the parameters.
+%
+% The Jacobian DOES NOT include derivates with respect to the fibre direction.
+%
+% d is the diffusivity of the material inside the cylinders.
+%
+% R is the list of the radii of the cylinders. It has size [1 m] where m is the
+% number of radii.
+%
+% G, delta and smalldel are the gradient strength, pulse separation and
+% pulse length of each measurement in the protocol.  Each has
+% size [N 1].
+%
+% roots contains solutions to the Bessel function equation from function
+% BesselJ_RootsCyl.
+%
+% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
+%         Gary Hui Zhang     (gary.zhang@ucl.ac.uk)
+%
+
+% When R=0, no need to do any calculation
+if (R == 0.00)
+    LE = zeros(size(G,1), size(R,2));
+    J = zeros([size(LE), 2]);
+	 J(:,:,:) = 0;
+    return;
+end
+
+% Check the roots array is correct
+if(abs(roots(1) - 1.8412)>0.0001)
+    error('Looks like the roots array is wrong.  First value should be 1.8412, but is %f', roots(1));
+end
+
+% Radial wavenumbers
+GAMMA = 2.675987E8;
+
+% number of gradient directions, i.e. number of measurements
+l_q=size(G,1);
+l_a=numel(R);
+k_max=numel(roots);
+
+R_mat=repmat(R,[l_q 1]);
+R_mat=R_mat(:);
+R_mat=repmat(R_mat,[1 1 k_max]);
+R_matSq=R_mat.^2;
+
+root_m=reshape(roots,[1 1 k_max]);
+alpha_mat=repmat(root_m,[l_q*l_a 1 1])./R_mat;
+amSq=alpha_mat.^2;
+amP6=amSq.^3;
+
+deltamx=repmat(delta,[1,l_a]);
+deltamx_rep = deltamx(:);
+deltamx_rep = repmat(deltamx_rep,[1 1 k_max]);
+
+smalldelmx=repmat(smalldel,[1,l_a]);
+smalldelmx_rep = smalldelmx(:);
+smalldelmx_rep = repmat(smalldelmx_rep,[1 1 k_max]);
+
+Gmx=repmat(G,[1,l_a]);
+GmxSq = Gmx.^2;
+
+% Perpendicular component (Neuman model)
+sda2 = smalldelmx_rep.*amSq;
+bda2 = deltamx_rep.*amSq;
+emdsda2 = exp(-d*sda2);
+emdbda2 = exp(-d*bda2);
+emdbdmsda2 = exp(-d*(bda2 - sda2));
+emdbdpsda2 = exp(-d*(bda2 + sda2));
+
+sumnum1 = 2*d*sda2;
+% the rest can be reused in dE/dR
+sumnum2 = - 2 + 2*emdsda2 + 2*emdbda2;
+sumnum2 = sumnum2 - emdbdmsda2 - emdbdpsda2;
+sumnum = sumnum1 + sumnum2;
+
+sumdenom = d^2*amP6.*(R_matSq.*amSq - 1);
+
+% Check for zeros on top and bottom
+%sumdenom(find(sumnum) == 0) = 1;
+sumterms = sumnum./sumdenom;
+
+testinds = find(sumterms(:,:,end)>0);
+test = sumterms(testinds,1)./sumterms(testinds,end);
+if(min(test)<1E4)
+    warning('Ratio of largest to smallest terms in Neuman model sum is <1E4.  May need more terms.');
+end
+
+s = sum(sumterms,3);
+s = reshape(s,[l_q,l_a]);
+if(min(s)<0)
+    warning('Negative sums found in Neuman sum.  Setting to zero.');
+    s(find(s<0))=0;
+end
+
+LE = -2*GAMMA^2*GmxSq.*s;
+
+% Compute the Jacobian matrix
+if(nargout>1)
+    
+    % dLE/dd
+    sumnumD = 2*sda2;
+    sumnumD = sumnumD - 2*sda2.*emdsda2;
+    sumnumD = sumnumD - 2*bda2.*emdbda2;
+    sumnumD = sumnumD + (bda2 - sda2).*emdbdmsda2;
+    sumnumD = sumnumD + (bda2 + sda2).*emdbdpsda2;
+    sumtermsD = sumnumD./sumdenom;
+
+    sD = sum(sumtermsD,3);
+    sD = reshape(sD,[l_q,l_a]);
+
+    dLEdd = -2*GAMMA^2*GmxSq.*(sD - 2*s/d);
+
+    % dLE/dR
+    sumtermsR = (6*sumterms - 2*d*sumtermsD)./R_mat;
+    
+    sR = sum(sumtermsR,3);
+    sR = reshape(sR,[l_q,l_a]);
+
+    dLEdr = -2*GAMMA^2*GmxSq.*sR;
+
+    % Construct the jacobian matrix.
+    J = zeros([size(LE), 2]);
+    J(:,:,1) = dLEdd;
+    J(:,:,2) = dLEdr;
+end
+
diff --git a/NODDI_toolbox_v1.01/models/GetB0.m b/NODDI_toolbox_v1.01/models/GetB0.m
new file mode 100644
index 0000000000000000000000000000000000000000..65696598b76b42ad0fa09459136df95765858955
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/GetB0.m
@@ -0,0 +1,16 @@
+function b0 = GetB0(modelname, fittedpars)
+%
+% function b0 = GetB0(modelname, fittedpars)
+%
+% Returns the b=0 signal estimate.
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+b0Idx = GetParameterIndex(modelname, 'b0');
+if b0Idx > 0
+    b0 = fittedpars(b0Idx);
+else
+    b0 = 1;
+end
+
diff --git a/NODDI_toolbox_v1.01/models/GetB_Values.m b/NODDI_toolbox_v1.01/models/GetB_Values.m
new file mode 100644
index 0000000000000000000000000000000000000000..660aff310fba8395452422a93646d6e66ceec1e2
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/GetB_Values.m
@@ -0,0 +1,25 @@
+function b = GetB_Values(protocol)
+% Computes the b value for each measurement in the protocol
+%
+% b = GetB_Values(protocol)
+% returns an array of b values, one for each measurement defined
+% in the list of measurements in the protocol.
+%
+% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
+%
+
+GAMMA = 2.675987E8;
+if(strcmp(protocol.pulseseq, 'PGSE') || strcmp(protocol.pulseseq, 'STEAM'))
+    modQ = GAMMA*protocol.smalldel.*protocol.G;
+    diffTime = protocol.delta - protocol.smalldel/3;
+    b = diffTime.*modQ.^2;
+
+elseif(strcmp(protocol.pulseseq, 'DSE'))
+    b = getB_ValuesDSE(protocol.G, protocol.delta1, protocol.delta2, protocol.delta3, protocol.t1, protocol.t2, protocol.t3);
+
+elseif(strcmp(protocol.pulseseq, 'OGSE'))
+    b = GetB_ValuesOGSE(protocol.G, protocol.delta, protocol.smalldel, protocol.omega);
+end
+
+
+
diff --git a/NODDI_toolbox_v1.01/models/GetFibreOrientation.m b/NODDI_toolbox_v1.01/models/GetFibreOrientation.m
new file mode 100644
index 0000000000000000000000000000000000000000..3053520dd81decc7f672ba3c2c1ea8328865b51c
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/GetFibreOrientation.m
@@ -0,0 +1,14 @@
+function fibredir = GetFibreOrientation(modelname, fittedpars)
+%
+% function fibredir = GetFibreOrientation(modelname, fittedpars)
+%
+% Returns the fibre orientation as a unit vector from fitted parameters.
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+theta = fittedpars(:, GetParameterIndex(modelname, 'theta'));
+phi = fittedpars(:, GetParameterIndex(modelname, 'phi'));
+
+fibredir = [cos(phi).*sin(theta) sin(phi).*sin(theta) cos(theta)]';
+
diff --git a/NODDI_toolbox_v1.01/models/GetParameterIndex.m b/NODDI_toolbox_v1.01/models/GetParameterIndex.m
new file mode 100644
index 0000000000000000000000000000000000000000..2cac511c7d4610f75544df5b058a91a17318d4c0
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/GetParameterIndex.m
@@ -0,0 +1,20 @@
+function idx = GetParameterIndex(modelname, parametername)
+%
+% function idx = GetParameterIndex(modelname, parametername)
+%
+% Given an input modelname and parametername, this function returns the index
+% of the parameter within the model.
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+strings = GetParameterStrings(modelname);
+
+for i=1:length(strings)
+    if (strcmp(strings(i), parametername))
+        idx = i;
+        return;
+    end
+end
+
+idx = -1;
diff --git a/NODDI_toolbox_v1.01/models/GetParameterStrings.m b/NODDI_toolbox_v1.01/models/GetParameterStrings.m
new file mode 100644
index 0000000000000000000000000000000000000000..ef3c4b29d8cad4e0552404e99c5173ab90159f9b
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/GetParameterStrings.m
@@ -0,0 +1,34 @@
+function strings = GetParameterStrings(modelname)
+%
+% function strings = GetParameterStrings(modelname)
+%
+% Given an input modelname, this function returns the names of the model
+% parameters
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+if (strcmp(modelname, 'StickIsoV_B0'))
+    strings = {'ficvf', 'di', 'dh', 'fiso', 'diso', 'b0', 'theta', 'phi'};
+elseif (strcmp(modelname, 'StickTortIsoV_B0'))
+    strings = {'ficvf', 'di', 'fiso', 'diso', 'b0', 'theta', 'phi'};
+elseif (strcmp(modelname, 'WatsonSHStick'))
+    strings = {'ficvf', 'di', 'dh', 'kappa', 'theta', 'phi'};
+elseif (strcmp(modelname, 'WatsonSHStickIsoV_B0'))
+    strings = {'ficvf', 'di', 'dh', 'kappa', 'fiso', 'diso', 'b0', 'theta', 'phi'};
+elseif (strcmp(modelname, 'WatsonSHStickIsoVIsoDot_B0'))
+    strings = {'ficvf', 'di', 'dh', 'kappa', 'fiso', 'diso', 'irfrac', 'b0', 'theta', 'phi'};
+elseif (strcmp(modelname, 'WatsonSHStickTortIsoV_B0'))
+    strings = {'ficvf', 'di', 'kappa', 'fiso', 'diso', 'b0', 'theta', 'phi'};
+elseif (strcmp(modelname, 'WatsonSHStickTortIsoVIsoDot_B0'))
+    strings = {'ficvf', 'di', 'kappa', 'fiso', 'diso', 'irfrac', 'b0', 'theta', 'phi'};
+elseif (strcmp(modelname, 'BinghamStickTortIsoV_B0'))
+    strings = {'ficvf', 'di', 'kappa', 'beta', 'psi', 'fiso', 'diso', 'b0', 'theta', 'phi'};
+elseif (strcmp(modelname, 'WatsonSHCylSingleRadTortIsoV_GPD_B0'))
+    strings = {'ficvf', 'di', 'rad', 'kappa', 'fiso', 'diso', 'b0', 'theta', 'phi'};
+elseif (strcmp(modelname, 'CylSingleRadIsoDotTortIsoV_GPD_B0'))
+    strings = {'ficvf', 'di', 'rad', 'irfrac', 'fiso', 'diso', 'b0', 'theta', 'phi'};
+else
+    error(['Parameter strings yet to be defined for this model:', modelname]);
+end
+
diff --git a/NODDI_toolbox_v1.01/models/GetScalingFactors.m b/NODDI_toolbox_v1.01/models/GetScalingFactors.m
new file mode 100644
index 0000000000000000000000000000000000000000..d40f1dcaba94d84ab7c6c01687c80353aab0b923
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/GetScalingFactors.m
@@ -0,0 +1,44 @@
+function scale = GetScalingFactors(modelname)
+%
+% function scale = GetScalingFactors(modelname)
+%
+% Returns an array of scaling factors for the parameters of the model
+% intended to rescale so that they all have value close to 1.
+%
+% Note that including the scaling factor for sigma increases the number
+% of model variables by 1.
+%
+% Note that the scaling factor not set for theta and phi
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+parameterStrings = GetParameterStrings(modelname);
+
+% here the scaling factors do not include the ones for theta and phi
+% but include one for the sigma
+scale = zeros(1, length(parameterStrings) - 1);
+
+% the scaling factor for sigma is set to 1
+scale(end) = 1;
+
+for i=1:length(parameterStrings)
+    if (strcmp(parameterStrings(i), 'di') ||...
+            strcmp(parameterStrings(i), 'dh') ||...
+            strcmp(parameterStrings(i), 'diso'))
+        scale(i) = 1E9;
+    elseif (strcmp(parameterStrings(i), 'rad'))
+        scale(i) = 1E6;
+    elseif (strcmp(parameterStrings(i), 'ficvf') ||...
+            strcmp(parameterStrings(i), 'fiso') ||...
+            strcmp(parameterStrings(i), 'irfrac') ||...
+            strcmp(parameterStrings(i), 'psi') ||...
+            strcmp(parameterStrings(i), 'b0') ||...
+            strcmp(parameterStrings(i), 't1'))
+        scale(i) = 1;
+    elseif (strcmp(parameterStrings(i), 'kappa') ||...
+            strcmp(parameterStrings(i), 'beta'))
+        scale(i) = 0.1;
+    end
+end
+
diff --git a/NODDI_toolbox_v1.01/models/MakeDT_Matrix.m b/NODDI_toolbox_v1.01/models/MakeDT_Matrix.m
new file mode 100644
index 0000000000000000000000000000000000000000..3d9633a6b1258c686fb68612adc26731067808c3
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/MakeDT_Matrix.m
@@ -0,0 +1,14 @@
+function dt = MakeDT_Matrix(d11, d12, d13, d22, d23, d33)
+% Makes a diffusion tensor matrix out of the six elements.
+%
+% dt = MakeDT_Matrix(d11, d12, d13, d22, d23, d33)
+% returns the matrix
+% [d11 d12 d13]
+% [d12 d22 d23]
+% [d13 d23 d33]
+%
+% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
+%
+
+dt = [d11 d12 d13; d12 d22 d23; d13 d23 d33];
+
diff --git a/NODDI_toolbox_v1.01/models/MakeModel.m b/NODDI_toolbox_v1.01/models/MakeModel.m
new file mode 100644
index 0000000000000000000000000000000000000000..6bd48645d34649d22a065209d62dec9923c28817
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/MakeModel.m
@@ -0,0 +1,89 @@
+function model = MakeModel(modelname)
+
+% function model = MakeModel(modelname)
+%
+% Set up the model specification for fitting
+% 
+% model.name: model name
+%
+% model.numParams: number of parameters
+%
+% model.paramsStr: parameter strings
+%
+% model.tissuetype: type of tissue
+%
+% model.noOfStages: how many stages to run
+%
+% model.fixGD: fixed variables during gradient descent
+% model.fixedvalsGD: values for the fixed variables during gradient descent
+%
+% model.fixMCMC: fixed variables during MCMC
+% model.MCMC.steplengths: MCMC step lengths
+% model.MCMC.burnin: MCMC burn-in
+% model.MCMC.interval: MCMC interval
+% model.MCMC.samples: MCMC samples
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+model.name = modelname;
+model.numParams = NumFreeParams(modelname);
+model.paramsStr = GetParameterStrings(modelname);
+model.tissuetype = 'invivo';
+model.GS.fixed = zeros(1, model.numParams);
+model.GS.fixedvals = zeros(1, model.numParams);
+model.GD.fixed = zeros(1, model.numParams);
+model.GD.fixedvals = zeros(1, model.numParams);
+model.GD.type = 'single'; % 'multistart'
+model.GD.multistart.perturbation = zeros(1, model.numParams);
+model.GD.multistart.noOfRuns = 10;
+model.MCMC.fixed = ones(1, model.numParams + 1);
+model.MCMC.steplengths = 0.05*ones(1, model.numParams+1);
+model.MCMC.burnin = 2000;
+model.MCMC.interval = 200;
+model.MCMC.samples = 40;
+model.noOfStages = 2;
+model.sigma.perVoxel = 1;
+model.sigma.minSNR = 0.02;
+model.sigma.scaling = 100;
+
+% use exvivo setting if isotropic restriction is included
+irfracIdx = GetParameterIndex(modelname, 'irfrac');
+if irfracIdx > 0
+    model.tissuetype = 'exvivo';
+end
+
+% fix intrinsic diffusivity
+diIdx = GetParameterIndex(modelname, 'di');
+model.GS.fixed(diIdx) = 1;
+model.GD.fixed(diIdx) = 1;
+if strcmp(model.tissuetype, 'invivo')
+    model.GS.fixedvals(diIdx) = 1.7E-9;
+    model.GD.fixedvals(diIdx) = 1.7E-9;
+else
+    model.GS.fixedvals(diIdx) = 0.6E-9;
+    model.GD.fixedvals(diIdx) = 0.6E-9;
+end
+
+% fix isotropic diffusivity
+disoIdx = GetParameterIndex(modelname, 'diso');
+if disoIdx > 0
+    model.GS.fixed(disoIdx) = 1;
+    model.GD.fixed(disoIdx) = 1;
+	 if strcmp(model.tissuetype, 'invivo')
+        model.GS.fixedvals(disoIdx) = 3.0E-9;
+        model.GD.fixedvals(disoIdx) = 3.0E-9;
+    else
+        model.GS.fixedvals(disoIdx) = 2.0E-9;
+        model.GD.fixedvals(disoIdx) = 2.0E-9;
+    end
+end
+
+% fix B0
+% fixed value is estimated from the b0 images voxel-wise
+b0Idx = GetParameterIndex(modelname, 'b0');
+if b0Idx > 0
+    model.GS.fixed(b0Idx) = 1;
+    model.GD.fixed(b0Idx) = 1;
+end
+
diff --git a/NODDI_toolbox_v1.01/models/NumFreeParams.m b/NODDI_toolbox_v1.01/models/NumFreeParams.m
new file mode 100644
index 0000000000000000000000000000000000000000..6905509842a5824b193d89babac0c43c14d78af4
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/NumFreeParams.m
@@ -0,0 +1,11 @@
+function numParams = NumFreeParams(modelname)
+%
+% function numParams = NumFreeParams(modelname)
+%
+% Given an input modelname, returns the number of free parameters of the model.
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+numParams = length(GetParameterStrings(modelname));
+
diff --git a/NODDI_toolbox_v1.01/models/RicianLogLik.m b/NODDI_toolbox_v1.01/models/RicianLogLik.m
new file mode 100644
index 0000000000000000000000000000000000000000..2d504e71ddb9e6e6e88516c4b6cd359f59aaec2d
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/RicianLogLik.m
@@ -0,0 +1,22 @@
+function loglik = RicianLogLik(meas, signals, sig)
+% Computes the log likelihood of the measurements given the model signals
+% for the Rician noise model.
+%
+% loglik = RicianLogLik(meas, signals, sig) returns the likelihood of
+% measuring meas given the signals and the noise standard deviation sig. 
+%
+% meas are the measurements
+%
+% signals are computed from a model
+%
+% sig is the standard deviation of the Gaussian distributions underlying
+% the Rician distribution.
+%
+% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
+%
+
+sumsqsc = (signals.^2 + meas.^2)./(2*sig.^2);
+scp = meas.*signals./(sig.^2);
+lb0 = logbesseli0(scp);
+logliks = - 2*log(sig) - sumsqsc + log(signals) + lb0;
+loglik = sum(logliks);
diff --git a/NODDI_toolbox_v1.01/models/SynthMeas.m b/NODDI_toolbox_v1.01/models/SynthMeas.m
new file mode 100644
index 0000000000000000000000000000000000000000..3d91046de327728cbedc8d5bebd63a595aadf8dd
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/SynthMeas.m
@@ -0,0 +1,212 @@
+function [E J] = SynthMeas(model, xsc, protocol, fibredir, constants)
+%
+% function [E J] = SynthMeas(model, xsc, protocol, fibredir, constants)
+%
+% General method for generating synthetic data from a model.
+%
+% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
+%         Gary Hui Zhang     (gary.zhang@ucl.ac.uk)
+%
+
+if(nargout == 1)
+    if(strcmp(model, 'IsoGPD'))
+        [E] = SynthMeasIsoGPD(xsc, protocol);
+    elseif(strcmp(model, 'CylSingleRadGPD'))
+        [E] = SynthMeasCylSingleRadGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'CylSingleRadGPD_B0'))
+        [E] = SynthMeasCylSingleRadGPD_B0(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'CylSingleRadIsoV_GPD'))
+        [E] = SynthMeasCylSingleRadIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'CylSingleRadIsoV_GPD_B0'))
+        [E] = SynthMeasCylSingleRadIsoV_GPD_B0(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'CylSingleRadTortGPD'))
+        [E] = SynthMeasCylSingleRadTortGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'CylSingleRadTortIsoGPD'))
+        [E] = SynthMeasCylSingleRadTortIsoGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'CylSingleRadTortIsoV_GPD'))
+        [E] = SynthMeasCylSingleRadTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'CylSingleRadTortIsoV_GPD_B0'))
+        [E] = SynthMeasCylSingleRadTortIsoV_GPD_B0(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'CylSingleRadIsoCylTortIsoV_GPD'))
+        [E] = SynthMeasCylSingleRadIsoCylTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'CylSingleRadIsoStickTortIsoV_GPD'))
+        [E] = SynthMeasCylSingleRadIsoStickTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'CylSingleRadIsoSphereTortIsoV_GPD'))
+        [E] = SynthMeasCylSingleRadIsoSphereTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl, constants.roots_sph);
+    elseif(strcmp(model, 'CylSingleRadIsoDotGPD'))
+        [E] = SynthMeasCylSingleRadIsoDotGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'CylSingleRadIsoDotTortIsoV_GPD'))
+        [E] = SynthMeasCylSingleRadIsoDotTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'CylSingleRadIsoDotTortIsoV_GPD_B0'))
+        [E] = SynthMeasCylSingleRadIsoDotTortIsoV_GPD_B0(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'CylSingleRadIsoDotTortIsoV_GPD_B0T1'))
+        [E] = SynthMeasCylSingleRadIsoDotTortIsoV_GPD_B0T1(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'CylSingleRadIsoSphereTortIsoV_GPD'))
+        [E] = SynthMeasCylSingleRadIsoSphereTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'CylGammaRadGPD'))
+        [E] = SynthMeasCylGammaRadGPD_PGSE(xsc, protocol.grad_dirs, protocol.G', protocol.delta', protocol.smalldel', fibredir, constants.roots_cyl, 0);
+    elseif(strcmp(model, 'CylGammaRadTortGPD'))
+        [E] = SynthMeasCylGammaRadTortGPD(xsc, protocol, fibredir, constants.roots_cyl, 0);
+    elseif(strcmp(model, 'CylGammaRadTortIsoGPD'))
+        [E] = SynthMeasCylGammaRadTortIsoGPD(xsc, protocol, fibredir, constants.roots_cyl, 0);
+    elseif(strcmp(model, 'CylGammaRadTortIsoV_GPD'))
+        [E] = SynthMeasCylGammaRadTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl, 0);
+    elseif(strcmp(model, 'CylGammaRadByVolGPD'))
+        [E] = SynthMeasCylGammaRadByVolGPD_PGSE(xsc, protocol.grad_dirs, protocol.G', protocol.delta', protocol.smalldel', fibredir, constants.roots_cyl, 0);
+    elseif(strcmp(model, 'CylGammaRadByVolTortGPD'))
+        [E] = SynthMeasCylGammaRadByVolTortGPD(xsc, protocol, fibredir, constants.roots_cyl, 0);
+    elseif(strcmp(model, 'CylGammaRadByVolTortIsoGPD'))
+        [E] = SynthMeasCylGammaRadByVolTortIsoGPD(xsc, protocol, fibredir, constants.roots_cyl, 0);
+    elseif(strcmp(model, 'CylGammaRadByVolTortIsoV_GPD'))
+        [E] = SynthMeasCylGammaRadByVolTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl, 0);
+    elseif(strcmp(model, 'SphereSingleRadGPD'))
+        [E] = SynthMeasSphereSingleRadGPD(xsc, protocol, constants.roots_sph);
+    elseif(strcmp(model, 'Stick'))
+        [E] = SynthMeasStick(xsc, protocol, fibredir);
+    elseif(strcmp(model, 'StickTort'))
+        [E] = SynthMeasStickTort(xsc, protocol, fibredir);
+    elseif(strcmp(model, 'StickIsoV_B0'))
+        [E] = SynthMeasStickIsoV_B0(xsc, protocol, fibredir);
+    elseif(strcmp(model, 'StickTortIsoV_B0'))
+        [E] = SynthMeasStickTortIsoV_B0(xsc, protocol, fibredir);
+    elseif(strcmp(model, 'WatsonCylSingleRadGPD'))
+        [E] = SynthMeasWatsonCylSingleRadGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'WatsonCylSingleRadTortGPD'))
+        [E] = SynthMeasWatsonCylSingleRadTortGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'WatsonCylSingleRadTortIsoV_GPD'))
+        [E] = SynthMeasWatsonCylSingleRadTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'WatsonCylSingleRadTortIsoV_GPD_B0'))
+        [E] = SynthMeasWatsonCylSingleRadTortIsoV_GPD_B0(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'WatsonStick'))
+        [E] = SynthMeasWatsonStick(xsc, protocol, fibredir);
+    elseif(strcmp(model, 'WatsonStickTort'))
+        [E] = SynthMeasWatsonStickTort(xsc, protocol, fibredir);
+    elseif(strcmp(model, 'WatsonSHCylSingleRadGPD'))
+        [E] = SynthMeasWatsonSHCylSingleRadGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'WatsonSHCylSingleRadTortGPD'))
+        [E] = SynthMeasWatsonSHCylSingleRadTortGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'WatsonSHCylSingleRadTortIsoV_GPD'))
+        [E] = SynthMeasWatsonSHCylSingleRadTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'WatsonSHCylSingleRadTortIsoV_GPD_B0'))
+        [E] = SynthMeasWatsonSHCylSingleRadTortIsoV_GPD_B0(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'WatsonSHStick'))
+        [E] = SynthMeasWatsonSHStick(xsc, protocol, fibredir);
+    elseif(strcmp(model, 'WatsonSHStickIsoV_B0'))
+        [E] = SynthMeasWatsonSHStickIsoV_B0(xsc, protocol, fibredir);
+    elseif(strcmp(model, 'WatsonSHStickIsoVIsoDot_B0'))
+        [E] = SynthMeasWatsonSHStickIsoVIsoDot_B0(xsc, protocol, fibredir);
+    elseif(strcmp(model, 'WatsonSHStickTort'))
+        [E] = SynthMeasWatsonSHStickTort(xsc, protocol, fibredir);
+    elseif(strcmp(model, 'WatsonSHStickTortIsoV_B0'))
+        [E] = SynthMeasWatsonSHStickTortIsoV_B0(xsc, protocol, fibredir);
+    elseif(strcmp(model, 'WatsonSHStickTortIsoVIsoDot_B0'))
+        [E] = SynthMeasWatsonSHStickTortIsoVIsoDot_B0(xsc, protocol, fibredir);
+    elseif(strcmp(model, 'BinghamCylSingleRadGPD'))
+        [E] = SynthMeasBinghamCylSingleRadGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'BinghamCylSingleRadTortGPD'))
+        [E] = SynthMeasBinghamCylSingleRadTortGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'BinghamCylSingleRadTortIsoV_GPD'))
+        [E] = SynthMeasBinghamCylSingleRadTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'BinghamCylSingleRadTortIsoV_GPD_B0'))
+        [E] = SynthMeasBinghamCylSingleRadTortIsoV_GPD_B0(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'BinghamStickTortIsoV_B0'))
+        [E] = SynthMeasBinghamStickTortIsoV_B0(xsc, protocol, fibredir);
+    elseif(strcmp(model, 'ExCrossingCylSingleRadGPD'))
+        [E] = SynthMeasExCrossingCylSingleRadGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'ExCrossingCylSingleRadGPD'))
+        [E] = SynthMeasExCrossingCylSingleRadTortGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'ExCrossingCylSingleRadIsoDotGPD'))
+        [E] = SynthMeasExCrossingCylSingleRadIsoDotGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'ExCrossingCylSingleRadIsoDotTortGPD'))
+        [E] = SynthMeasExCrossingCylSingleRadIsoDotTortGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'ExCrossingCylSingleRadIsoDotTortIsoV_GPD'))
+        [E] = SynthMeasExCrossingCylSingleRadIsoDotTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'ExCrossingCylSingleRadIsoDotTortIsoV_GPD_B0'))
+        [E] = SynthMeasExCrossingCylSingleRadIsoDotTortIsoV_GPD_B0(xsc, protocol, fibredir, constants.roots_cyl);
+    else
+        error(['Undefined model: ', model]);
+    end
+else
+    if(strcmp(model, 'IsoGPD'))
+        [E J] = SynthMeasIsoGPD(xsc, protocol);
+    elseif(strcmp(model, 'CylSingleRadGPD'))
+        [E J] = SynthMeasCylSingleRadGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'CylSingleRadIsoV_GPD'))
+        [E J] = SynthMeasCylSingleRadIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'CylSingleRadIsoV_GPD_B0'))
+        [E J] = SynthMeasCylSingleRadIsoV_GPD_B0(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'CylSingleRadTortGPD'))
+        [E J] = SynthMeasCylSingleRadTortGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'CylSingleRadTortIsoGPD'))
+        [E J] = SynthMeasCylSingleRadTortIsoGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'CylSingleRadTortIsoV_GPD'))
+        [E J] = SynthMeasCylSingleRadTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'CylSingleRadTortIsoV_GPD_B0'))
+        [E J] = SynthMeasCylSingleRadTortIsoV_GPD_B0(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'CylGammaRadGPD'))
+        [E J] = SynthMeasCylGammaRadGPD_PGSE(xsc, protocol.grad_dirs, protocol.G', protocol.delta', protocol.smalldel', fibredir, constants.roots_cyl, 0);
+    elseif(strcmp(model, 'CylGammaRadTortGPD'))
+        [E J] = SynthMeasCylGammaRadTortGPD(xsc, protocol, fibredir, constants.roots_cyl, 0);
+    elseif(strcmp(model, 'CylGammaRadTortIsoGPD'))
+        [E J] = SynthMeasCylGammaRadTortIsoGPD(xsc, protocol, fibredir, constants.roots_cyl, 0);
+    elseif(strcmp(model, 'CylGammaRadTortIsoV_GPD'))
+        [E J] = SynthMeasCylGammaRadTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl, 0);
+    elseif(strcmp(model, 'CylGammaRadByVolGPD'))
+        [E J] = SynthMeasCylGammaRadByVolGPD_PGSE(xsc, protocol.grad_dirs, protocol.G', protocol.delta', protocol.smalldel', fibredir, constants.roots_cyl, 0);
+    elseif(strcmp(model, 'CylGammaRadByVolTortGPD'))
+        [E J] = SynthMeasCylGammaRadByVolTortGPD(xsc, protocol, fibredir, constants.roots_cyl, 0);
+    elseif(strcmp(model, 'CylGammaRadByVolTortIsoGPD'))
+        [E J] = SynthMeasCylGammaRadByVolTortIsoGPD(xsc, protocol, fibredir, constants.roots_cyl, 0);
+    elseif(strcmp(model, 'CylGammaRadByVolTortIsoV_GPD'))
+        [E J] = SynthMeasCylGammaRadByVolTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl, 0);
+    elseif(strcmp(model, 'SphereSingleRadGPD'))
+        [E J] = SynthMeasSphereSingleRadGPD(xsc, protocol, constants.roots_sph);
+    elseif(strcmp(model, 'CylSingleRadGPD_B0'))
+        [E J] = SynthMeasCylSingleRadGPD_B0(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'Stick'))
+        [E J] = SynthMeasStick(xsc, protocol, fibredir);
+    elseif(strcmp(model, 'StickTort'))
+        [E J] = SynthMeasStickTort(xsc, protocol, fibredir);
+    elseif(strcmp(model, 'WatsonStick'))
+        [E J] = SynthMeasWatsonStick(xsc, protocol, fibredir);
+    elseif(strcmp(model, 'WatsonStickTort'))
+        [E J] = SynthMeasWatsonStickTort(xsc, protocol, fibredir);
+    elseif(strcmp(model, 'WatsonSHStick'))
+        [E J] = SynthMeasWatsonSHStick(xsc, protocol, fibredir);
+    elseif(strcmp(model, 'WatsonSHStickIsoV_B0'))
+        [E J] = SynthMeasWatsonSHStickIsoV_B0(xsc, protocol, fibredir);
+    elseif(strcmp(model, 'WatsonSHStickIsoVIsoDot_B0'))
+        [E J] = SynthMeasWatsonSHStickIsoVIsoDot_B0(xsc, protocol, fibredir);
+    elseif(strcmp(model, 'WatsonSHStickTort'))
+        [E J] = SynthMeasWatsonSHStickTort(xsc, protocol, fibredir);
+    elseif(strcmp(model, 'WatsonSHStickTortIsoV_B0'))
+        [E J] = SynthMeasWatsonSHStickTortIsoV_B0(xsc, protocol, fibredir);
+    elseif(strcmp(model, 'WatsonSHStickTortIsoVIsoDot_B0'))
+        [E J] = SynthMeasWatsonSHStickTortIsoVIsoDot_B0(xsc, protocol, fibredir);
+    elseif(strcmp(model, 'WatsonCylSingleRadGPD'))
+        [E J] = SynthMeasWatsonCylSingleRadGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'WatsonSHCylSingleRadGPD'))
+        [E J] = SynthMeasWatsonSHCylSingleRadGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'WatsonSHCylSingleRadTortGPD'))
+        [E J] = SynthMeasWatsonSHCylSingleRadTortGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'WatsonSHCylSingleRadTortIsoV_GPD'))
+        [E J] = SynthMeasWatsonSHCylSingleRadTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'BinghamCylSingleRadGPD'))
+        [E J] = SynthMeasBinghamCylSingleRadGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'ExCrossingCylSingleRadGPD'))
+        [E J] = SynthMeasExCrossingCylSingleRadGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'ExCrossingCylSingleRadTortGPD'))
+        [E J] = SynthMeasExCrossingCylSingleRadTortGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'ExCrossingCylSingleRadIsoDotGPD'))
+        [E J] = SynthMeasExCrossingCylSingleRadIsoDotGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'ExCrossingCylSingleRadIsoDotTortGPD'))
+        [E J] = SynthMeasExCrossingCylSingleRadIsoDotTortGPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'ExCrossingCylSingleRadIsoDotTortIsoV_GPD'))
+        [E J] = SynthMeasExCrossingCylSingleRadIsoDotTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl);
+    elseif(strcmp(model, 'ExCrossingCylSingleRadIsoDotTortIsoV_GPD_B0'))
+        [E J] = SynthMeasExCrossingCylSingleRadIsoDotTortIsoV_GPD_B0(xsc, protocol, fibredir, constants.roots_cyl);
+    else
+        error(['Undefined model: ', model]);
+    end
+end
+
diff --git a/NODDI_toolbox_v1.01/models/SynthMeasHinderedDiffusion_PGSE.m b/NODDI_toolbox_v1.01/models/SynthMeasHinderedDiffusion_PGSE.m
new file mode 100644
index 0000000000000000000000000000000000000000..f384052bd6736366804067e82ab057a2efdd912d
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/SynthMeasHinderedDiffusion_PGSE.m
@@ -0,0 +1,61 @@
+function [E,J]=SynthMeasHinderedDiffusion_PGSE(x, grad_dirs, G, delta, smalldel, fibredir)
+% Substrate: Anisotropic hindered diffusion compartment
+% Pulse sequence: Pulsed gradient spin echo
+% Signal approximation: N/A
+%
+% [E,J]=SynthMeasHinderedDiffusion_PGSE(x, grad_dirs, G, delta, smalldel, fibredir)
+% returns the measurements E according to the model and the Jacobian J of the
+% measurements with respect to the parameters.  The Jacobian does not
+% include derivates with respect to the fibre direction.
+%
+% x is the list of model parameters in SI units:
+% x(1) is the free diffusivity of the material inside and outside the cylinders.
+% x(2) is the hindered diffusivity outside the cylinders in perpendicular directions.
+%
+% grad_dirs is the gradient direction for each measurement.  It has size [N
+% 3] where N is the number of measurements.
+%
+% G, delta and smalldel are the gradient strength, pulse separation and
+% pulse length of each measurement in the protocol.  Each has
+% size [N 1].
+%
+% fibredir is a unit vector along the cylinder axis.  It must be in
+% Cartesian coordinates [x y z]' with size [3 1].
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+dPar=x(1);
+dPerp=x(2);
+
+% Radial wavenumbers
+GAMMA = 2.675987E8;
+modQ = GAMMA*smalldel.*G;
+modQ_Sq = modQ.^2;
+
+% Angles between gradient directions and fibre direction.
+cosTheta = grad_dirs*fibredir;
+cosThetaSq = cosTheta.^2;
+sinThetaSq = 1-cosThetaSq;
+
+% b-value
+bval = (delta-smalldel/3).*modQ_Sq;
+
+% Find hindered signals
+E=exp(-bval.*((dPar - dPerp)*cosThetaSq + dPerp));
+
+% Compute the Jacobian matrix
+if(nargout>1)
+    bvalE = bval.*E;
+    % dE/ddPar
+    dEddPar = -bvalE.*cosThetaSq;
+    
+    % dE/ddPerp
+    dEddPerp = -bvalE.*sinThetaSq;
+    
+    % Construct the jacobian matrix.
+    J = zeros(size(E, 1), 2);
+    J(:,1) = dEddPar;
+    J(:,2) = dEddPerp;
+end
+
diff --git a/NODDI_toolbox_v1.01/models/SynthMeasIsoGPD.m b/NODDI_toolbox_v1.01/models/SynthMeasIsoGPD.m
new file mode 100644
index 0000000000000000000000000000000000000000..71f506ae50a2932bfde957959a6bc72adab92302
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/SynthMeasIsoGPD.m
@@ -0,0 +1,73 @@
+function [E,J]=SynthMeasIsoGPD(d, protocol)
+% Computes signals and their derivatives for isotropic free diffusion with
+% diffusivity d for the protocol.
+%
+% [E,J]=SynthMeasIsoGPD(d, protocol)
+% returns the measurements E according to the model and the Jacobian J of the
+% measurements with respect to the parameter d.
+%
+% d is the diffusivity.
+%
+% protocol is the object containing the acquisition protocol.
+%
+% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
+%
+
+if(strcmp(protocol.pulseseq, 'PGSE') || strcmp(protocol.pulseseq, 'STEAM'))
+
+    GAMMA = 2.675987E8;
+    modQ = GAMMA*protocol.smalldel'.*protocol.G';
+    modQ_Sq = modQ.^2;
+    difftime = (protocol.delta'-protocol.smalldel'/3);
+
+    E = exp(-difftime.*modQ_Sq*d);
+    if(nargout>1)
+        J = -difftime.*modQ_Sq.*E;
+    end
+elseif(strcmp(protocol.pulseseq, 'FullSTEAM'))
+
+    GAMMA = 2.675987E8;
+
+    FullG = protocol.grad_dirs.*repmat(protocol.G', [1 3]);
+    GdGd = sum(FullG.*FullG,2)';
+    GcGc = sum(protocol.cG.*protocol.cG,2)';
+    GrGr = sum(protocol.rG.*protocol.rG,2)';
+    GdGc = sum(FullG.*protocol.cG,2)';
+    GdGr = sum(FullG.*protocol.rG,2)';
+    GcGr = sum(protocol.cG.*protocol.rG,2)';
+
+    tdd = protocol.gap1 + protocol.gap2 + protocol.TM + 2*protocol.sdelc + 2*protocol.smalldel/3 + 2*protocol.sdelr;
+    tcc = protocol.TM + 2*protocol.sdelc/3 + 2*protocol.sdelr;
+    trr = protocol.TM + 2*protocol.sdelr/3;
+    tdc = protocol.TM + protocol.sdelc + 2*protocol.sdelr;
+    tdr = protocol.TM + protocol.sdelr;
+    tcr = protocol.TM + protocol.sdelr;
+
+    gqt = GAMMA^2*(GdGd.*protocol.smalldel.^2.*tdd + ...
+    GcGc.*protocol.sdelc.^2.*tcc + ...
+    GrGr.*protocol.sdelr.^2.*trr + ...
+    2*GdGc.*protocol.smalldel.*protocol.sdelc.*tdc + ...
+    2*GdGr.*protocol.smalldel.*protocol.sdelr.*tdr + ...
+    2*GcGr.*protocol.sdelc.*protocol.sdelr.*tcr);
+
+    E=exp(-gqt'*d);
+
+    if(nargout>1)
+        J = -gqt.*E;
+    end
+elseif(strcmp(protocol.pulseseq, 'DSE'))
+    bValue = GetB_ValuesDSE(protocol.G', protocol.delta1', protocol.delta2', protocol.delta3', protocol.t1', protocol.t2', protocol.t3');
+    E = exp(-bValue*d);
+    if(nargout>1)
+        J = -bValue.*E;
+    end
+elseif(strcmp(protocol.pulseseq, 'OGSE'))
+    bValue = GetB_Values(protocol)';
+    E = exp(-bValue*d);
+    if(nargout>1)
+        J = -bValue.*E;
+    end
+else
+    error('Not implemented for pulse sequence: %s', protocol.pulseseq);
+end
+
diff --git a/NODDI_toolbox_v1.01/models/logbesseli0.m b/NODDI_toolbox_v1.01/models/logbesseli0.m
new file mode 100644
index 0000000000000000000000000000000000000000..5134559969f378508c51808eb84f4b83e7900f01
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/logbesseli0.m
@@ -0,0 +1,25 @@
+% Computes log(besseli(0,x)) robustly.  Computing it directly causes
+% numerical problems at high x, but the function has asymptotic linear
+% behaviour, which we approximate here for high x.
+%
+% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
+%
+
+function lb0 = logbesseli0(x)
+
+% For very large arguments to besseli, we approximate log besseli using a
+% linear model of the asymptotic behaviour.
+% The linear parameters come from this command:
+% app=regress(log(besseli(0,500:700))',[ones(201,1) (500:700)']);
+app = [-3.61178295877576 0.99916157999904];
+
+lb0 = zeros(length(x), 1);
+exact = find(x<700);
+approx = find(x>=700);
+lb0(exact) = log(besseli(0, x(exact)));
+%lb0(approx) = x(approx)*app(2) + app(1);
+
+% This is a more standard approximation.  For large x, I_0(x) -> exp(x)/sqrt(2 pi x).
+lb0(approx) = x(approx) - log(2*pi*x(approx))/2;
+
+
diff --git a/NODDI_toolbox_v1.01/models/watson/LegendreGaussianIntegral.m b/NODDI_toolbox_v1.01/models/watson/LegendreGaussianIntegral.m
new file mode 100644
index 0000000000000000000000000000000000000000..dd4a3421bdceb2eebe4ca72684ce316e5c4c51a0
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/watson/LegendreGaussianIntegral.m
@@ -0,0 +1,155 @@
+function [L, D] = legendreGaussianIntegral(x, n)
+% function [L, D] = legendreGaussianIntegral(x, n)
+% Computes legendre gaussian integrals up to the order specified and the
+% derivatives if requested
+%
+% The integral takes the following form, in Mathematica syntax,
+%
+% L[x, n] = Integrate[Exp[-x \mu^2] Legendre[2*n, \mu], {\mu, -1, 1}]
+% D[x, n] = Integrate[Exp[-x \mu^2] (-\mu^2) Legendre[2*n, \mu], {\mu, -1, 1}]
+%
+% INPUTS:
+%
+% x should be a column vector of positive numbers, specifying the
+% parameters of the gaussian
+%
+% n should be a non-negative integer, such that 2n specifies the maximum order
+% of legendre polynomial
+%
+% The maximum value for n is 6.
+%
+% OUTPUTS:
+%
+% L will be a two-dimensional array with each row containing the
+% legendre gaussian integrals of the orders 0, 2, 4, ..., to 2n for the
+% parameter value at the corresponding row in x
+%
+% Note that the legendre gaussian integrals of the odd orders are zero.
+%
+% D will be the 1st order derivative of L
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+% Make sure n is not larger than 6
+if n > 6
+	error('The maximum value for n is 6, which correspondes to the 12th order Legendre polynomial');
+end
+
+%
+% Computing the related exponent gaussian integrals
+% I[x, n] = Integrate[Exp[-x \mu^2] \mu^(2*n), {\mu, -1, 1}]
+% with the following recursion:
+% 1) I[x, 0] = Sqrt[\pi]Erf[x]/Sqrt[x]
+% 2) I[x, n+1] = -Exp[-x]/x + (2n+1)/(2x) I[x, n]
+%
+% This does not work well when x is small
+
+exact = find(x>0.05);
+approx = find(x<=0.05);
+% Necessary to make matlab happy when x is a single value
+exact = exact(:);
+approx = approx(:);
+
+if nargout > 1
+	mn = n + 2;
+else
+	mn = n + 1;
+end
+I = zeros(length(x),mn);
+sqrtx = sqrt(x(exact));
+I(exact,1) = sqrt(pi)*erf(sqrtx)./sqrtx;
+dx = 1.0./x(exact);
+emx = -exp(-x(exact));
+for i = 2:mn
+    I(exact,i) = emx + (i-1.5)*I(exact,i-1);
+    I(exact,i) = I(exact,i).*dx;
+end
+
+% Computing the legendre gaussian integrals for large enough x
+L = zeros(length(x),n+1);
+for i = 1:n+1
+	if i == 1
+		L(exact,1) = I(exact,1);
+	elseif i == 2
+		L(exact,2) = -0.5*I(exact,1) + 1.5*I(exact,2);
+	elseif i == 3
+		L(exact,3) = 0.375*I(exact,1) - 3.75*I(exact,2) + 4.375*I(exact,3);
+	elseif i == 4
+		L(exact,4) = -0.3125*I(exact,1) + 6.5625*I(exact,2) - 19.6875*I(exact,3) + 14.4375*I(exact,4);
+	elseif i == 5
+		L(exact,5) = 0.2734375*I(exact,1) - 9.84375*I(exact,2) + 54.140625*I(exact,3) - 93.84375*I(exact,4) + 50.2734375*I(exact,5);
+    elseif i == 6
+        L(exact,6) = -(63/256)*I(exact,1) + (3465/256)*I(exact,2) - (30030/256)*I(exact,3) + (90090/256)*I(exact,4) - (109395/256)*I(exact,5) + (46189/256)*I(exact,6);
+    elseif i == 7
+        L(exact,7) = (231/1024)*I(exact,1) - (18018/1024)*I(exact,2) + (225225/1024)*I(exact,3) - (1021020/1024)*I(exact,4) + (2078505/1024)*I(exact,5) - (1939938/1024)*I(exact,6) + (676039/1024)*I(exact,7);
+	end
+end
+
+% Computing the legendre gaussian integrals for small x
+x2=x(approx,1).^2;
+x3=x2.*x(approx,1);
+x4=x3.*x(approx,1);
+x5=x4.*x(approx,1);
+x6=x5.*x(approx,1);
+for i = 1:n+1
+	if i == 1
+		L(approx,1) = 2 - 2*x(approx,1)/3 + x2/5 - x3/21 + x4/108;
+	elseif i == 2
+		L(approx,2) = -4*x(approx,1)/15 + 4*x2/35 - 2*x3/63 + 2*x4/297;
+	elseif i == 3
+		L(approx,3) = 8*x2/315 - 8*x3/693 + 4*x4/1287;
+	elseif i == 4
+		L(approx,4) = -16*x3/9009 + 16*x4/19305;
+	elseif i == 5
+		L(approx,5) = 32*x4/328185;
+    elseif i == 6
+		L(approx,6) = -64*x5/14549535;
+    elseif i == 7
+		L(approx,7) = 128*x6/760543875;
+	end
+end
+
+if nargout == 1
+	return;
+end
+
+% Computing the derivatives for large enough x
+D = zeros(length(x),n+1);
+for i = 1:n+1
+	if i == 1
+		D(exact,1) = -I(exact,2);
+	elseif i == 2
+		D(exact,2) = 0.5*I(exact,2) - 1.5*I(exact,3);
+	elseif i == 3
+		D(exact,3) = -0.375*I(exact,2) + 3.75*I(exact,3) - 4.375*I(exact,4);
+	elseif i == 4
+		D(exact,4) = 0.3125*I(exact,2) - 6.5625*I(exact,3) + 19.6875*I(exact,4) - 14.4375*I(exact,5);
+	elseif i == 5
+		D(exact,5) = -0.2734375*I(exact,2) + 9.84375*I(exact,3) - 54.140625*I(exact,4) + 93.84375*I(exact,5) - 50.2734375*I(exact,6);
+    elseif i == 6
+        D(exact,6) = (63/256)*I(exact,2) - (3465/256)*I(exact,3) + (30030/256)*I(exact,4) - (90090/256)*I(exact,5) + (109395/256)*I(exact,6) - (46189/256)*I(exact,7);
+    elseif i == 7
+        D(exact,7) = -(231/1024)*I(exact,2) + (18018/1024)*I(exact,3) - (225225/1024)*I(exact,4) + (1021020/1024)*I(exact,5) - (2078505/1024)*I(exact,6) + (1939938/1024)*I(exact,7) - (676039/1024)*I(exact,8);
+	end
+end
+
+% Computing the derivatives for small x
+for i = 1:n+1
+	if i == 1
+		D(approx,1) = -2/3 + 2*x(approx,1)/5 - x2/7 + x3/27 - x4/132;
+	elseif i == 2
+		D(approx,2) = -4/15 + 8*x(approx,1)/35 - 2*x2/21 + 8*x3/297 - 5*x4/858;
+	elseif i == 3
+		D(approx,3) = 16*x(approx,1)/315 - 8*x2/231 + 16*x3/1287 - 4*x4/1287;
+	elseif i == 4
+		D(approx,4) = -16*x2/3003 + 64*x3/19305 - 8*x4/7293;
+	elseif i == 5
+		D(approx,5) = 128*x3/328185 - 32*x4/138567;
+    elseif i == 6
+        D(approx,6) = -64*x4/2909907 + 128*x5/10140585;
+    elseif i == 7
+        D(approx,7) = 256*x5/253514625;
+	end
+end
+
diff --git a/NODDI_toolbox_v1.01/models/watson/NODDI_erfi.m b/NODDI_toolbox_v1.01/models/watson/NODDI_erfi.m
new file mode 100644
index 0000000000000000000000000000000000000000..8db27db289462a450dfc21668835975926ee1ebd
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/watson/NODDI_erfi.m
@@ -0,0 +1,21 @@
+function ans=NODDI_erfi(x)
+% %erfi(x). The Imaginary error function, as it is defined in Mathematica
+% %erfi(z)==erf(iz)/i (z could be complex) using 
+% %the incomplete gamma function in matlab: gammainc
+% %Using "@": erfi = @(x) real(-sqrt(-1).*sign(x).*gammainc(-x.^2,1/2))
+% %Note: limit(x->0) erfi(x)/x -> 2/sqrt(pi)
+%
+% %Example 1: 
+% x=linspace(0.001,6,100);
+% y=exp(-x.^2).*erfi(x)./2./x;
+% figure(1), clf;plot(x,y*sqrt(pi))
+%
+% %Example 2: 
+% [x,y]=meshgrid(linspace(-3,3,180),linspace(-3,3,180));
+% z=x+i*y;
+% figure(1), clf;contourf(x,y,log(erfi(z)))
+% axis equal;axis off
+xc=5.7;%cut for asymptotic approximation (when x is real)
+ans=~isreal(x).*(-(sqrt(-x.^2)./(x+isreal(x))).*gammainc(-x.^2,1/2))+...
+    isreal(x).*real(-sqrt(-1).*sign(x).*((x<xc).*gammainc(-x.^2,1/2))+...
+    (x>=xc).*exp(x.^2)./x/sqrt(pi));
diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonHinderedDiffusion_PGSE.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonHinderedDiffusion_PGSE.m
new file mode 100644
index 0000000000000000000000000000000000000000..38529358f53439a4f7bc1c655c53148c9d1fb161
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonHinderedDiffusion_PGSE.m
@@ -0,0 +1,56 @@
+function [E,J]=SynthMeasWatsonHinderedDiffusion_PGSE(x, grad_dirs, G, delta, smalldel, fibredir)
+% Substrate: Anisotropic hindered diffusion compartment
+% Orientation distribution: Watson's distribution
+% Pulse sequence: Pulsed gradient spin echo
+% Signal approximation: N/A
+%
+% [E,J]=SynthMeasWatsonHinderedDiffusion_PGSE(x, grad_dirs, G, delta, smalldel, fibredir)
+% returns the measurements E according to the model and the Jacobian J of the
+% measurements with respect to the parameters.  The Jacobian does not
+% include derivates with respect to the fibre direction.
+%
+% x is the list of model parameters in SI units:
+% x(1) is the free diffusivity of the material inside and outside the cylinders.
+% x(2) is the hindered diffusivity outside the cylinders in perpendicular directions.
+% x(3) is the concentration parameter of the Watson's distribution
+%
+% grad_dirs is the gradient direction for each measurement.  It has size [N
+% 3] where N is the number of measurements.
+%
+% G, delta and smalldel are the gradient strength, pulse separation and
+% pulse length of each measurement in the protocol.  Each has
+% size [N 1].
+%
+% fibredir is a unit vector along the symmetry axis of the Watson's
+% distribution.  It must be in Cartesian coordinates [x y z]' with size [3 1].
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+dPar = x(1);
+dPerp = x(2);
+kappa = x(3);
+
+% get the equivalent diffusivities
+if (nargout == 1)
+    dw = WatsonHinderedDiffusionCoeff(dPar, dPerp, kappa);
+else
+    [dw, Jdw] = WatsonHinderedDiffusionCoeff(dPar, dPerp, kappa);
+end
+
+xh = [dw(1) dw(2)];
+if (nargout == 1)
+    E = SynthMeasHinderedDiffusion_PGSE(xh, grad_dirs, G, delta, smalldel, fibredir);
+else
+    [E, Jh] = SynthMeasHinderedDiffusion_PGSE(xh, grad_dirs, G, delta, smalldel, fibredir);
+end
+
+% Compute the Jacobian matrix
+if(nargout>1)
+    % Construct the jacobian matrix.
+    J = zeros(size(E, 1), 3);
+    J(:,1) = Jh(:,1)*Jdw(1,1) + Jh(:,2)*Jdw(2,1);
+    J(:,2) = Jh(:,1)*Jdw(1,2) + Jh(:,2)*Jdw(2,2);
+    J(:,3) = Jh(:,1)*Jdw(1,3) + Jh(:,2)*Jdw(2,3);
+end
+
diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylNeuman_PGSE.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylNeuman_PGSE.m
new file mode 100644
index 0000000000000000000000000000000000000000..93838bbdff8d151e5f13bf53820f8d3d1326d2cb
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylNeuman_PGSE.m
@@ -0,0 +1,138 @@
+function [E,J]=SynthMeasWatsonSHCylNeuman_PGSE(x, grad_dirs, G, delta, smalldel, fibredir, roots)
+% Substrate: Impermeable cylinders with one radius in an empty background.
+% Orientation distribution: Watson's distribution with SH approximation
+% Pulse sequence: Pulsed gradient spin echo
+% Signal approximation: Gaussian phase distribution.
+%
+% [E,J]=SynthMeasWatsonSHCylNeuman_PGSE(x, grad_dirs, G, delta, smalldel, fibredir, roots)
+% returns the measurements E according to the model and the Jacobian J of the
+% measurements with respect to the parameters.  The Jacobian does not
+% include derivates with respect to the fibre direction.
+%
+% x is the list of model parameters in SI units:
+% x(1) is the diffusivity of the material inside the cylinders.
+% x(2) is the radius of the cylinders.
+% x(3) is the concentration parameter of the Watson's distribution
+%
+% grad_dirs is the gradient direction for each measurement.  It has size [N
+% 3] where N is the number of measurements.
+%
+% G, delta and smalldel are the gradient strength, pulse separation and
+% pulse length of each measurement in the protocol.  Each has
+% size [N 1].
+%
+% fibredir is a unit vector along the symmetry axis of the Watson's
+% distribution.  It must be in Cartesian coordinates [x y z]' with size [3 1].
+%
+% roots contains solutions to the Bessel function equation from function
+% BesselJ_RootsCyl.
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+if length(x) ~= 3
+    error('the first argument should have exactly three parameters');
+end
+
+d=x(1);
+R=x(2);
+kappa=x(3);
+
+l_q = size(grad_dirs,1);
+
+% Parallel component
+if nargout > 1
+    [LePar, J_LePar] = CylNeumanLePar_PGSE(d, G, delta, smalldel);
+else
+    LePar = CylNeumanLePar_PGSE(d, G, delta, smalldel);
+end
+
+% Perpendicular component
+if nargout > 1
+    [LePerp, J_LePerp] = CylNeumanLePerp_PGSE(d, R, G, delta, smalldel, roots);
+else
+    LePerp = CylNeumanLePerp_PGSE(d, R, G, delta, smalldel, roots);
+end
+ePerp = exp(LePerp);
+
+% Compute the Legendre weighted signal
+Lpmp = LePerp - LePar;
+if nargout > 1
+    [lgi, J_lgi] = LegendreGaussianIntegral(Lpmp, 6);
+else
+    lgi = LegendreGaussianIntegral(Lpmp, 6);
+end
+
+% Compute the spherical harmonic coefficients of the Watson's distribution
+if nargout > 1
+    [coeff, J_coeff] = WatsonSHCoeff(kappa);
+else
+    coeff = WatsonSHCoeff(kappa);
+end
+coeffMatrix = repmat(coeff, [l_q, 1]);
+
+% Compute the dot product between the symmetry axis of the Watson's distribution
+% and the gradient direction
+%
+% For numerical reasons, cosTheta might not always be between -1 and 1
+% Due to round off errors, individual gradient vectors in grad_dirs and the
+% fibredir are never exactly normal.  When a gradient vector and fibredir are
+% essentially parallel, their dot product can fall outside of -1 and 1.
+%
+% BUT we need make sure it does, otherwise the legendre function call below
+% will FAIL and abort the calculation!!!
+%
+cosTheta = grad_dirs*fibredir;
+badCosTheta = find(abs(cosTheta)>1);
+cosTheta(badCosTheta) = cosTheta(badCosTheta)./abs(cosTheta(badCosTheta));
+
+% Compute the SH values at cosTheta
+sh = zeros(size(coeff));
+shMatrix = repmat(sh, [l_q, 1]);
+for i = 1:7
+    shMatrix(:,i) = sqrt((i - .75)/pi);
+    % legendre function returns coefficients of all m from 0 to l
+    % we only need the coefficient corresponding to m = 0
+    % WARNING: make sure to input ROW vector as variables!!!
+    % cosTheta is expected to be a COLUMN vector.
+    tmp = legendre(2*i - 2, cosTheta');
+    tmp = tmp';
+    shMatrix(:,i) = shMatrix(:,i) .* tmp(:,1);
+end
+
+E = sum(lgi.*coeffMatrix.*shMatrix, 2);
+% with the SH approximation, there will be no guarantee that E will be positive
+% but we need to make sure it does!!! replace the negative values with 10% of
+% the smallest positive values
+E(find(E<=0)) = min(E(find(E>0)))*0.1;
+E = 0.5*E.*ePerp;
+
+% Compute the Jacobian matrix
+if(nargout>1)
+    % dePerp/dd
+    dePerpdd = E.*J_LePerp(1);
+    % dePar/dd
+    dElgi = sum(J_lgi.*coeffMatrix.*shMatrix, 2);
+    dePardd = 0.5*dElgi.*(J_LePerp(:,:,1) - J_LePar).*ePerp;
+    % dE/dd
+    dEdd = dePardd + dePerpdd;
+    
+	% dePerp/dR
+    dePerpdR = E.*J_LePerp(2);
+    % dePar/dR
+    dePardR = 0.5*dElgi.*J_LePerp(:,:,2).*ePerp;
+    % dE/dR
+    dEdR = dePardR + dePerpdR;
+    
+    % dE/dK
+    J_coeffMatrix = repmat(J_coeff, [l_q, 1]);
+    dEdk = sum(lgi.*J_coeffMatrix.*shMatrix,2);
+    dEdk = 0.5*dEdk.*ePerp;
+    
+    % Construct the jacobian matrix.
+    J = zeros(length(E), 3);
+    J(:,1) = dEdd;
+    J(:,2) = dEdR;
+    J(:,3) = dEdk;
+end
+
diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadGPD.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadGPD.m
new file mode 100644
index 0000000000000000000000000000000000000000..5dc387db240f9f5daffad709bcbbc58019768f9c
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadGPD.m
@@ -0,0 +1,45 @@
+function [E,J]=SynthMeasWatsonSHCylSingleRadGPD(x, protocol, fibredir, roots)
+% Substrate: Impermeable cylinders with one radius in a homogeneous background.
+% Orientation distribution: Watson's distribution with SH approximation
+% Pulse sequence: Any
+% Signal approximation: Gaussian phase distribution.
+%
+% [E,J]=SynthMeasWatsonSHCylSingleRadGPD(x, protocol, fibredir, roots)
+% returns the measurements E according to the model and the Jacobian J of the
+% measurements with respect to the parameters.  The Jacobian does not
+% include derivates with respect to the fibre direction.
+%
+% x is the list of model parameters in SI units:
+% x(1) is the volume fraction of the intracellular space.
+% x(2) is the free diffusivity of the material inside and outside the cylinders.
+% x(3) is the hindered diffusivity outside the cylinders in perpendicular directions.
+% x(4) is the radius of the cylinders.
+% x(5) is the concentration parameter of the Watson's distribution
+%
+% protocol is the object containing the acquisition protocol.
+%
+% fibredir is a unit vector along the symmetry axis of the Watson's
+% distribution.  It must be in Cartesian coordinates [x y z]' with size [3 1].
+%
+% roots contains solutions to the Bessel function equation from function
+% BesselJ_RootsCyl.
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+if(strcmp(protocol.pulseseq, 'PGSE') || strcmp(protocol.pulseseq, 'STEAM'))
+    if(nargout == 1)
+        [E] = SynthMeasWatsonSHCylSingleRadGPD_PGSE(x, protocol.grad_dirs, protocol.G', protocol.delta', protocol.smalldel', fibredir, roots);
+    else
+        [E J] = SynthMeasWatsonSHCylSingleRadGPD_PGSE(x, protocol.grad_dirs, protocol.G', protocol.delta', protocol.smalldel', fibredir, roots);
+    end
+elseif(strcmp(protocol.pulseseq, 'DSE'))
+    if(nargout == 1)
+        [E] = SynthMeasWatsonSHCylSingleRadGPD_DSE(x, protocol.grad_dirs, protocol.G', protocol.TE, protocol.delta1', protocol.delta2', protocol.delta3', protocol.t1', protocol.t2', protocol.t3', fibredir, roots);
+    else
+        [E J] = SynthMeasWatsonSHCylSingleRadGPD_DSE(x, protocol.grad_dirs, protocol.G', protocol.TE, protocol.delta1', protocol.delta2', protocol.delta3', protocol.t1', protocol.t2', protocol.t3', fibredir, roots);
+    end
+else
+    error(['Unknown pulse sequence: ' protocol.pulseseq]);
+end            
+
diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadGPD_PGSE.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadGPD_PGSE.m
new file mode 100644
index 0000000000000000000000000000000000000000..8d57d7352f3e6d3f182fa00f850e8a8cac8e7ff2
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadGPD_PGSE.m
@@ -0,0 +1,90 @@
+function [E,J]=SynthMeasWatsonSHCylSingleRadGPD_PGSE(x, grad_dirs, G, delta, smalldel, fibredir, roots)
+% Substrate: Impermeable cylinders with one radius in a homogeneous background.
+% Orientation distribution: Watson's distribution with SH approximation
+% Pulse sequence: Pulsed gradient spin echo
+% Signal approximation: Gaussian phase distribution.
+%
+% [E,J]=SynthMeasWatsonSHCylSingleRadGPD_PGSE(x, grad_dirs, G, delta, smalldel, fibredir, roots)
+% returns the measurements E according to the model and the Jacobian J of the
+% measurements with respect to the parameters.  The Jacobian does not
+% include derivates with respect to the fibre direction.
+%
+% x is the list of model parameters in SI units:
+% x(1) is the volume fraction of the intracellular space.
+% x(2) is the free diffusivity of the material inside and outside the cylinders.
+% x(3) is the hindered diffusivity outside the cylinders in perpendicular directions.
+% x(4) is the radius of the cylinders.
+% x(5) is the concentration parameter of the Watson's distribution
+%
+% grad_dirs is the gradient direction for each measurement.  It has size [N
+% 3] where N is the number of measurements.
+%
+% G, delta and smalldel are the gradient strength, pulse separation and
+% pulse length of each measurement in the protocol.  Each has
+% size [N 1].
+%
+% fibredir is a unit vector along the symmetry axis of the Watson's
+% distribution.  It must be in Cartesian coordinates [x y z]' with size [3 1].
+%
+% roots contains solutions to the Bessel function equation from function
+% BesselJ_RootsCyl.
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+
+% Duplication with SynthMeasDistributedRadVG remains, because of the
+% derivative computation.
+
+f=x(1);
+dPar=x(2);
+dPerp=x(3);
+R=x(4);
+kappa=x(5);
+
+% build the input x vector for hindered compartment
+x_h = [dPar dPerp kappa];
+
+% build the input x vector for restricted diffusion in Neuman cylinder model
+% set diffusion coeff in restricted compartment same as parallel one in
+% hindered.
+x_r = [dPar R kappa];
+
+% Synthesize measurements from model
+if (nargout>1)
+	[E_h, J_h] = SynthMeasWatsonHinderedDiffusion_PGSE(x_h, grad_dirs, G, delta, smalldel, fibredir);
+	[E_r, J_r] = SynthMeasWatsonSHCylNeuman_PGSE(x_r, grad_dirs, G, delta, smalldel, fibredir, roots);
+else
+	E_h = SynthMeasWatsonHinderedDiffusion_PGSE(x_h, grad_dirs, G, delta, smalldel, fibredir);
+	E_r = SynthMeasWatsonSHCylNeuman_PGSE(x_r, grad_dirs, G, delta, smalldel, fibredir, roots);
+end
+
+E=(1-f)*E_h+f*E_r;
+
+% Compute the Jacobian matrix
+if(nargout>1)
+    
+    % dE_tot/df = E_r - E_h
+    dEtdf = E_r - E_h;
+    
+    % dE_tot/ddPar
+    dEtddPar = (1-f)*J_h(:,1) + f*J_r(:,1);
+    
+    % dE_tot/ddPerp
+    dEtddPerp = (1-f)*J_h(:,2);
+    
+    % dE_tot/dR
+    dEtdr = f*J_r(:,2);
+    
+    % dE_tot/dk
+    dEtdk = (1-f)*J_h(:,3) + f*J_r(:,3);
+    
+    % Construct the jacobian matrix. 
+    J = zeros(length(E), 5);
+    J(:,1) = dEtdf;
+    J(:,2) = dEtddPar;
+    J(:,3) = dEtddPerp;
+    J(:,4) = dEtdr;
+    J(:,5) = dEtdk;
+end
+
diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD.m
new file mode 100644
index 0000000000000000000000000000000000000000..da5be9f3cb5f07ab45d0f6cc897a8cfdc331f9f5
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD.m
@@ -0,0 +1,54 @@
+function [E,J]=SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD(x, protocol, fibredir, roots)
+% Substrate: Impermeable cylinders with one radius in a homogeneous background.
+% Orientation distribution: Watson's distribution with SH approximation
+% Signal approximation: Gaussian phase distribution.
+% Notes: This version includes an isotropic diffusion compartment with its own
+% diffusivity.
+% This version includes a stationary water compartment.
+%
+% [E,J]=SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD(x, protocol, fibredir, roots)
+% returns the measurements E according to the model and the Jacobian J of the
+% measurements with respect to the parameters.  The Jacobian does not
+% include derivates with respect to the fibre direction.
+%
+% x is the list of model parameters in SI units:
+% x(1) is the volume fraction of the intracellular space.
+% x(2) is the free diffusivity of the material inside and outside the cylinders.
+% x(3) is the hindered diffusivity outside the cylinders in perpendicular directions.
+% x(4) is the radius of the cylinders.
+% x(5) is the concentration parameter of the Watson's distribution.
+% x(6) is the volume fraction of the isotropic compartment.
+% x(7) is the diffusivity of the isotropic compartment.
+% x(8) is the volume fraction of the isotropic restriction.
+%
+% protocol is the object containing the acquisition protocol.
+%
+% fibredir is a unit vector along the symmetry axis of the Watson's
+% distribution.  It must be in Cartesian coordinates [x y z]' with size [3 1].
+%
+% roots contains solutions to the Bessel function equation from function
+% BesselJ_RootsCyl.
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+irFrac = x(8);
+
+% Call the model w/o the isotropic restriction
+if(nargout == 1)
+    Ewo=SynthMeasWatsonSHCylSingleRadIsoV_GPD(x, protocol, fibredir, roots);
+else
+    [Ewo,Jwo]=SynthMeasWatsonSHCylSingleRadIsoV_GPD(x, protocol, fibredir, roots);
+end
+
+E = (1-irFrac)*Ewo + irFrac*1.0;
+
+if(nargout>1)
+    
+    % Update the component w/o isotropic restriction.
+    J = Jwo*(1-irFrac);
+    
+    % Add derivatives wrt isotropic restriction.
+    J(:,8) = 1.0 - Ewo;
+end
+
diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD_B0.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD_B0.m
new file mode 100644
index 0000000000000000000000000000000000000000..846e88374dda6b36a56e320da459d6574480e2dd
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD_B0.m
@@ -0,0 +1,52 @@
+function [E,J]=SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD_B0(x, protocol, fibredir, roots)
+% Substrate: Impermeable cylinders with one radius in a homogeneous background.
+% Orientation distribution: Watson's distribution with SH approximation
+% Signal approximation: Gaussian phase distribution.
+% Notes: This version includes an isotropic diffusion compartment with its own
+% diffusivity.
+% This version includes a stationary water compartment.
+% Includes a free parameter for the measurement at b=0.
+%
+% [E,J]=SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD_B0(x, protocol, fibredir, roots)
+% returns the measurements E according to the model and the Jacobian J of the
+% measurements with respect to the parameters.  The Jacobian does not
+% include derivates with respect to the fibre direction.
+%
+% x is the list of model parameters in SI units:
+% x(1) is the volume fraction of the intracellular space.
+% x(2) is the free diffusivity of the material inside and outside the cylinders.
+% x(3) is the hindered diffusivity outside the cylinders in perpendicular directions.
+% x(4) is the radius of the cylinders.
+% x(5) is the concentration parameter of the Watson's distribution.
+% x(6) is the volume fraction of the isotropic compartment.
+% x(7) is the diffusivity of the isotropic compartment.
+% x(8) is the volume fraction of the isotropic restriction.
+% x(9) is the measurement at b=0.
+%
+% protocol is the object containing the acquisition protocol.
+%
+% fibredir is a unit vector along the symmetry axis of the Watson's
+% distribution.  It must be in Cartesian coordinates [x y z]' with size [3 1].
+%
+% roots contains solutions to the Bessel function equation from function
+% BesselJ_RootsCyl.
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+S0 = x(9);
+
+% Call the other function to get normalized measurements.
+if(nargout == 1)
+    Enorm=SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD(x, protocol, fibredir, roots);
+else
+    [Enorm,Jnorm]=SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD(x, protocol, fibredir, roots);
+end
+
+E = Enorm*S0;
+
+if(nargout>1)
+    J = Jnorm*S0;
+    J(:,9) = Enorm;
+end
+
diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoV_GPD.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoV_GPD.m
new file mode 100644
index 0000000000000000000000000000000000000000..5799d60ba9db556962464ea78e9023cc854a8b8c
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoV_GPD.m
@@ -0,0 +1,58 @@
+function [E,J]=SynthMeasWatsonSHCylSingleRadIsoV_GPD(x, protocol, fibredir, roots)
+% Substrate: Impermeable cylinders with one radius in a homogeneous background.
+% Orientation distribution: Watson's distribution with SH approximation
+% Signal approximation: Gaussian phase distribution.
+% Notes: This version includes an isotropic diffusion compartment with its own
+% diffusivity.
+%
+% [E,J]=SynthMeasWatsonSHCylSingleRadIsoV_GPD(x, protocol, fibredir, roots)
+% returns the measurements E according to the model and the Jacobian J of the
+% measurements with respect to the parameters.  The Jacobian does not
+% include derivates with respect to the fibre direction.
+%
+% x is the list of model parameters in SI units:
+% x(1) is the volume fraction of the intracellular space.
+% x(2) is the free diffusivity of the material inside and outside the cylinders.
+% x(3) is the hindered diffusivity outside the cylinders in perpendicular directions.
+% x(4) is the radius of the cylinders.
+% x(5) is the concentration parameter of the Watson's distribution.
+% x(6) is the volume fraction of the isotropic compartment.
+% x(7) is the diffusivity of the isotropic compartment.
+%
+% protocol is the object containing the acquisition protocol.
+%
+% fibredir is a unit vector along the symmetry axis of the Watson's
+% distribution.  It must be in Cartesian coordinates [x y z]' with size [3 1].
+%
+% roots contains solutions to the Bessel function equation from function
+% BesselJ_RootsCyl.
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+fiso = x(6);
+dIso = x(7);
+
+% Call the model with no isotropic component to get the anisotropic component.
+if(nargout == 1)
+    Eaniso=SynthMeasWatsonSHCylSingleRadGPD(x, protocol, fibredir, roots);
+    Eiso = SynthMeasIsoGPD(dIso, protocol);
+else
+    [Eaniso,Janiso]=SynthMeasWatsonSHCylSingleRadGPD(x, protocol, fibredir, roots);
+    [Eiso, Jiso] = SynthMeasIsoGPD(dIso, protocol);
+end
+
+E = (1-fiso)*Eaniso + fiso*Eiso;
+
+if(nargout>1)
+    
+    % Update with anisotropic component.
+    J = Janiso*(1-fiso);
+    
+    % Add derivatives wrt isotropic fraction.
+    J(:,6) = Eiso - Eaniso;
+    
+    % Add entry for dIso
+    J(:,7) = fiso*Jiso;
+end
+
diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoV_GPD_B0.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoV_GPD_B0.m
new file mode 100644
index 0000000000000000000000000000000000000000..c4d19ccc4627dac593ca59a35086b5c998a2d0f6
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoV_GPD_B0.m
@@ -0,0 +1,51 @@
+function [E,J]=SynthMeasWatsonSHCylSingleRadIsoV_GPD_B0(x, protocol, fibredir, roots)
+% Substrate: Impermeable cylinders with one radius in a homogeneous background.
+% Orientation distribution: Watson's distribution with SH approximation
+% Signal approximation: Gaussian phase distribution.
+% Notes: This version includes an isotropic diffusion compartment with its own
+% diffusivity.
+% Includes a free parameter for the measurement at b=0.
+%
+% [E,J]=SynthMeasWatsonSHCylSingleRadIsoV_GPD_B0(x, protocol, fibredir, roots)
+% returns the measurements E according to the model and the Jacobian J of the
+% measurements with respect to the parameters.  The Jacobian does not
+% include derivates with respect to the fibre direction.
+%
+% x is the list of model parameters in SI units:
+% x(1) is the volume fraction of the intracellular space.
+% x(2) is the free diffusivity of the material inside and outside the cylinders.
+% x(3) is the hindered diffusivity outside the cylinders in perpendicular directions.
+% x(4) is the radius of the cylinders.
+% x(5) is the concentration parameter of the Watson's distribution.
+% x(6) is the volume fraction of the isotropic compartment.
+% x(7) is the diffusivity of the isotropic compartment.
+% x(8) is the measurement at b=0.
+%
+% protocol is the object containing the acquisition protocol.
+%
+% fibredir is a unit vector along the symmetry axis of the Watson's
+% distribution.  It must be in Cartesian coordinates [x y z]' with size [3 1].
+%
+% roots contains solutions to the Bessel function equation from function
+% BesselJ_RootsCyl.
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+S0 = x(8);
+
+% Call the other function to get normalized measurements.
+if(nargout == 1)
+    Enorm=SynthMeasWatsonSHCylSingleRadIsoV_GPD(x, protocol, fibredir, roots);
+else
+    [Enorm,Jnorm]=SynthMeasWatsonSHCylSingleRadIsoV_GPD(x, protocol, fibredir, roots);
+end
+
+E = Enorm*S0;
+
+if(nargout>1)
+    J = Jnorm*S0;
+    [meas, params] = size(J);
+    J(:,params+1) = Enorm;
+end
+
diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortGPD.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortGPD.m
new file mode 100644
index 0000000000000000000000000000000000000000..500288341b8ae955cdaffd8e5cca7ba4652d1d80
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortGPD.m
@@ -0,0 +1,53 @@
+function [E,J]=SynthMeasWatsonSHCylSingleRadTortGPD(x, protocol, fibredir, roots)
+% Substrate: Impermeable cylinders with one radius in a homogeneous background.
+% Orientation distribution: Watson's distribution with SH approximation
+% Pulse sequence: Any
+% Signal approximation: Gaussian phase distribution.
+% Notes: This version estimates the hindered diffusivity from the free diffusivity
+% and packing density using Szafer et al's tortuosity model for randomly
+% packed cylinders.
+%
+% [E,J]=SynthMeasWatsonSHCylSingleRadTortGPD(x, protocol, fibredir, roots)
+% returns the measurements E according to the model and the Jacobian J of the
+% measurements with respect to the parameters.  The Jacobian does not
+% include derivates with respect to the fibre direction.
+%
+% x is the list of model parameters in SI units:
+% x(1) is the volume fraction of the intracellular space.
+% x(2) is the free diffusivity of the material inside and outside the cylinders.
+% x(3) is the radius of the cylinders.
+% x(4) is the concentration parameter of the Watson's distribution.
+%
+% protocol is the object containing the acquisition protocol.
+%
+% fibredir is a unit vector along the symmetry axis of the Watson's
+% distribution.  It must be in Cartesian coordinates [x y z]' with size [3 1].
+%
+% roots contains solutions to the Bessel function equation from function
+% BesselJ_RootsCyl.
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+
+f=x(1);
+dPar=x(2);
+% This version is for cylinders with regular packing.
+%dPerp = dPar/((1 + f^(3/2))^2);
+% This one is for randomly packed cylinders
+dPerp = dPar*(1-f);
+R=[x(3)]; 
+kappa=x(4);
+
+x_full = [f dPar dPerp R kappa];
+
+% Call the model with no isotropic component to get the anisotropic component.
+if(nargout == 1)
+    E=SynthMeasWatsonSHCylSingleRadGPD(x_full, protocol, fibredir, roots);
+else
+    [E,J_full]=SynthMeasWatsonSHCylSingleRadGPD(x_full, protocol, fibredir, roots);
+    J(:,1) = J_full(:,1) - J_full(:,3)*dPar;
+    J(:,2) = J_full(:,2) + J_full(:,3)*(1-f);
+    J(:,3) = J_full(:,4);
+    J(:,4) = J_full(:,5);
+end
diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD.m
new file mode 100644
index 0000000000000000000000000000000000000000..a42e1290981d6baac09308f051cb8581787102bb
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD.m
@@ -0,0 +1,56 @@
+function [E,J]=SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD(x, protocol, fibredir, roots)
+% Substrate: Impermeable cylinders with one radius in a homogeneous background.
+% Orientation distribution: Watson's distribution with SH approximation
+% Signal approximation: Gaussian phase distribution.
+% Notes: This version estimates the hindered diffusivity from the free diffusivity
+% and packing density using Szafer et al's tortuosity model for randomly
+% packed cylinders.
+% This version includes an isotropic diffusion compartment with its own
+% diffusivity.
+% This version includes a stationary water compartment.
+%
+% [E,J]=SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD(x, protocol, fibredir, roots)
+% returns the measurements E according to the model and the Jacobian J of the
+% measurements with respect to the parameters.  The Jacobian does not
+% include derivates with respect to the fibre direction.
+%
+% x is the list of model parameters in SI units:
+% x(1) is the volume fraction of the intracellular space.
+% x(2) is the free diffusivity of the material inside and outside the cylinders.
+% x(3) is the radius of the cylinders.
+% x(4) is the concentration parameter of the Watson's distribution.
+% x(5) is the volume fraction of the isotropic compartment.
+% x(6) is the diffusivity of the isotropic compartment.
+% x(7) is the volume fraction of the isotropic restriction.
+%
+% protocol is the object containing the acquisition protocol.
+%
+% fibredir is a unit vector along the symmetry axis of the Watson's
+% distribution.  It must be in Cartesian coordinates [x y z]' with size [3 1].
+%
+% roots contains solutions to the Bessel function equation from function
+% BesselJ_RootsCyl.
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+irFrac = x(7);
+
+% Call the model w/o the isotropic restriction.
+if(nargout == 1)
+    Ewo=SynthMeasWatsonSHCylSingleRadTortIsoV_GPD(x, protocol, fibredir, roots);
+else
+   [Ewo,Jwo]=SynthMeasWatsonSHCylSingleRadTortIsoV_GPD(x, protocol, fibredir, roots);
+end
+
+E = (1-irFrac)*Ewo + irFrac*1.0;
+
+if(nargout>1)
+    
+    % Update the component w/o isotropic restriction.
+    J = Jwo*(1-irFrac);
+    
+    % Add derivatives wrt isotropic restriction.
+    J(:,7) = 1.0 - Ewo;
+end
+
diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD_B0.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD_B0.m
new file mode 100644
index 0000000000000000000000000000000000000000..8f2c15cb04007980a5195aa8c07448ef31628a7e
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD_B0.m
@@ -0,0 +1,54 @@
+function [E,J]=SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD_B0(x, protocol, fibredir, roots)
+% Substrate: Impermeable cylinders with one radius in a homogeneous background.
+% Orientation distribution: Watson's distribution with SH approximation
+% Signal approximation: Gaussian phase distribution.
+% Notes: This version estimates the hindered diffusivity from the free diffusivity
+% and packing density using Szafer et al's tortuosity model for randomly
+% packed cylinders.
+% This version includes an isotropic diffusion compartment with its own
+% diffusivity.
+% This version includes a stationary water compartment.
+% Includes a free parameter for the measurement at b=0.
+%
+% [E,J]=SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD_B0(x, protocol, fibredir, roots)
+% returns the measurements E according to the model and the Jacobian J of the
+% measurements with respect to the parameters.  The Jacobian does not
+% include derivates with respect to the fibre direction.
+%
+% x is the list of model parameters in SI units:
+% x(1) is the volume fraction of the intracellular space.
+% x(2) is the free diffusivity of the material inside and outside the cylinders.
+% x(3) is the radius of the cylinders.
+% x(4) is the concentration parameter of the Watson's distribution.
+% x(5) is the volume fraction of the isotropic compartment.
+% x(6) is the diffusivity of the isotropic compartment.
+% x(7) is the volume fraction of the isotropic restriction.
+% x(8) is the measurement at b=0.
+%
+% protocol is the object containing the acquisition protocol.
+%
+% fibredir is a unit vector along the symmetry axis of the Watson's
+% distribution.  It must be in Cartesian coordinates [x y z]' with size [3 1].
+%
+% roots contains solutions to the Bessel function equation from function
+% BesselJ_RootsCyl.
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+S0 = x(8);
+
+% Call the other function to get normalized measurements.
+if(nargout == 1)
+    Enorm=SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD(x, protocol, fibredir, roots);
+else
+   [Enorm,Jnorm]=SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD(x, protocol, fibredir, roots);
+end
+
+E = Enorm*S0;
+
+if(nargout>1)
+    J = Jnorm*S0;
+    J(:,8) = Enorm;
+end
+
diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoV_GPD.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoV_GPD.m
new file mode 100644
index 0000000000000000000000000000000000000000..b935e4f7e8e3ffcff2c3db25178485da563b78b9
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoV_GPD.m
@@ -0,0 +1,60 @@
+function [E,J]=SynthMeasWatsonSHCylSingleRadTortIsoV_GPD(x, protocol, fibredir, roots)
+% Substrate: Impermeable cylinders with one radius in a homogeneous background.
+% Orientation distribution: Watson's distribution with SH approximation
+% Signal approximation: Gaussian phase distribution.
+% Notes: This version estimates the hindered diffusivity from the free diffusivity
+% and packing density using Szafer et al's tortuosity model for randomly
+% packed cylinders.
+% This version includes an isotropic diffusion compartment with its own
+% diffusivity.
+%
+% [E,J]=SynthMeasWatsonSHCylSingleRadTortIsoV_GPD(x, protocol, fibredir, roots)
+% returns the measurements E according to the model and the Jacobian J of the
+% measurements with respect to the parameters.  The Jacobian does not
+% include derivates with respect to the fibre direction.
+%
+% x is the list of model parameters in SI units:
+% x(1) is the volume fraction of the intracellular space.
+% x(2) is the free diffusivity of the material inside and outside the cylinders.
+% x(3) is the radius of the cylinders.
+% x(4) is the concentration parameter of the Watson's distribution.
+% x(5) is the volume fraction of the isotropic compartment.
+% x(6) is the diffusivity of the isotropic compartment.
+%
+% protocol is the object containing the acquisition protocol.
+%
+% fibredir is a unit vector along the symmetry axis of the Watson's
+% distribution.  It must be in Cartesian coordinates [x y z]' with size [3 1].
+%
+% roots contains solutions to the Bessel function equation from function
+% BesselJ_RootsCyl.
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+
+fiso = x(5);
+dIso = x(6);
+
+% Call the model with no isotropic component to get the anisotropic component.
+if(nargout == 1)
+    Eaniso=SynthMeasWatsonSHCylSingleRadTortGPD(x, protocol, fibredir, roots);
+    Eiso = SynthMeasIsoGPD(dIso, protocol);
+else
+    [Eaniso,Janiso]=SynthMeasWatsonSHCylSingleRadTortGPD(x, protocol, fibredir, roots);
+    [Eiso, Jiso] = SynthMeasIsoGPD(dIso, protocol);
+end
+
+E = (1-fiso)*Eaniso + fiso*Eiso;
+
+if(nargout>1)
+    
+    % Update with anisotropic component.
+    J = Janiso*(1-fiso);
+    
+    % Add derivatives wrt isotropic fraction.
+    J(:,5) = Eiso - Eaniso;
+    
+    % Add entry for dIso
+    J(:,6) = fiso*Jiso;
+end
diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoV_GPD_B0.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoV_GPD_B0.m
new file mode 100644
index 0000000000000000000000000000000000000000..2a287ef3bc9aa06b74c6dc7d034179e7ad5d6f46
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoV_GPD_B0.m
@@ -0,0 +1,53 @@
+function [E,J]=SynthMeasWatsonSHCylSingleRadTortIsoV_GPD_B0(x, protocol, fibredir, roots)
+% Substrate: Impermeable cylinders with one radius in a homogeneous background.
+% Orientation distribution: Watson's distribution with SH approximation
+% Signal approximation: Gaussian phase distribution.
+% Notes: This version estimates the hindered diffusivity from the free diffusivity
+% and packing density using Szafer et al's tortuosity model for randomly
+% packed cylinders.
+% This version includes an isotropic diffusion compartment with its own
+% diffusivity.
+% Includes a free parameter for the measurement at b=0.
+%
+% [E,J]=SynthMeasWatsonSHCylSingleRadTortIsoV_GPD_B0(x, protocol, fibredir, roots)
+% returns the measurements E according to the model and the Jacobian J of the
+% measurements with respect to the parameters.  The Jacobian does not
+% include derivates with respect to the fibre direction.
+%
+% x is the list of model parameters in SI units:
+% x(1) is the volume fraction of the intracellular space.
+% x(2) is the free diffusivity of the material inside and outside the cylinders.
+% x(3) is the radius of the cylinders.
+% x(4) is the concentration parameter of the Watson's distribution.
+% x(5) is the volume fraction of the isotropic compartment.
+% x(6) is the diffusivity of the isotropic compartment.
+% x(7) is the measurement at b=0.
+%
+% protocol is the object containing the acquisition protocol.
+%
+% fibredir is a unit vector along the symmetry axis of the Watson's
+% distribution.  It must be in Cartesian coordinates [x y z]' with size [3 1].
+%
+% roots contains solutions to the Bessel function equation from function
+% BesselJ_RootsCyl.
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+S0 = x(7);
+
+% Call the other function to get normalized measurements.
+if(nargout == 1)
+    Enorm=SynthMeasWatsonSHCylSingleRadTortIsoV_GPD(x, protocol, fibredir, roots);
+else
+    [Enorm,Jnorm]=SynthMeasWatsonSHCylSingleRadTortIsoV_GPD(x, protocol, fibredir, roots);
+end
+
+E = Enorm*S0;
+
+if(nargout>1)
+    J = Jnorm*S0;
+    [meas, params] = size(J);
+    J(:,params+1) = Enorm;
+end
+
diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickIsoVIsoDot_B0.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickIsoVIsoDot_B0.m
new file mode 100644
index 0000000000000000000000000000000000000000..ce1b0d1837a4842d5d78259c3e9cfad5584506ca
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickIsoVIsoDot_B0.m
@@ -0,0 +1,52 @@
+function [E,J]=SynthMeasWatsonSHStickIsoVIsoDot_B0(x, protocol, fibredir)
+% Substrate: Impermeable sticks (cylinders with zero radius) in a homogeneous
+% background.
+% Orientation distribution: Watson's distribution with SH approximation
+% Signal approximation: Not applicable
+% This version includes an isotropic diffusion compartment with its own
+% diffusivity.
+% This version includes a stationary water compartment.
+% Includes a free parameter for the measurement at b=0.
+%
+% [E,J]=SynthMeasWatsonSHStickTortIsoV_B0(x, protocol, fibredir)
+% returns the measurements E according to the model and the Jacobian J of the
+% measurements with respect to the parameters.  The Jacobian does not
+% include derivates with respect to the fibre direction.
+%
+% x is the list of model parameters in SI units:
+% x(1) is the volume fraction of the intracellular space.
+% x(2) is the free diffusivity of the material inside and outside the cylinders.
+% x(3) is the hindered diffusivity outside the cylinders in perpendicular directions.
+% x(4) is the concentration parameter of the Watson's distribution.
+% x(5) is the volume fraction of the isotropic compartment.
+% x(6) is the diffusivity of the isotropic compartment.
+% x(7) is the volume fraction of the isotropic restriction.
+% x(8) is the measurement at b=0.
+%
+% protocol is the object containing the acquisition protocol.
+%
+% fibredir is a unit vector along the symmetry axis of the Watson's
+% distribution.  It must be in Cartesian coordinates [x y z]' with size [3 1].
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+xcyl=[x(1) x(2) x(3) 0 x(4) x(5) x(6) x(7) x(8)];
+
+if(nargout == 1)
+    E=SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD_B0(xcyl, protocol, fibredir, 0);
+else
+    [E,Jcyl]=SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD_B0(xcyl, protocol, fibredir, 0);
+end
+
+if(nargout>1)
+    J(:,1) = Jcyl(:,1);
+    J(:,2) = Jcyl(:,2);
+    J(:,3) = Jcyl(:,3);
+    J(:,4) = Jcyl(:,5);
+    J(:,5) = Jcyl(:,6);
+    J(:,6) = Jcyl(:,7);
+    J(:,7) = Jcyl(:,8);
+    J(:,8) = Jcyl(:,9);
+end
+
diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickIsoV_B0.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickIsoV_B0.m
new file mode 100644
index 0000000000000000000000000000000000000000..7a62870a1623cde90662d40486497bfce705a128
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickIsoV_B0.m
@@ -0,0 +1,49 @@
+function [E,J]=SynthMeasWatsonSHStickIsoV_B0(x, protocol, fibredir)
+% Substrate: Impermeable sticks (cylinders with zero radius) in a homogeneous
+% background.
+% Orientation distribution: Watson's distribution with SH approximation
+% Pulse sequence: Any
+% Signal approximation: Not applicable
+% Notes: This version includes an isotropic diffusion compartment with its own
+% Includes a free parameter for the measurement at b=0.
+%
+% [E,J]=SynthMeasWatsonSHStickIsoV_B0(x, protocol, fibredir)
+% returns the measurements E according to the model and the Jacobian J of the
+% measurements with respect to the parameters.  The Jacobian does not
+% include derivates with respect to the fibre direction.
+%
+% x is the list of model parameters in SI units:
+% x(1) is the volume fraction of the intracellular space.
+% x(2) is the free diffusivity of the material inside and outside the cylinders.
+% x(3) is the hindered diffusivity outside the cylinders in perpendicular directions.
+% x(4) is the concentration parameter of the Watson's distribution.
+% x(5) is the volume fraction of the isotropic compartment.
+% x(6) is the diffusivity of the isotropic compartment.
+% x(7) is the measurement at b=0.
+%
+% protocol is the object containing the acquisition protocol.
+%
+% fibredir is a unit vector along the symmetry axis of the Watson's
+% distribution.  It must be in Cartesian coordinates [x y z]' with size [3 1].
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+xcyl=[x(1) x(2) x(3) 0 x(4) x(5) x(6) x(7)];
+
+if(nargout == 1)
+    [E] = SynthMeasWatsonSHCylSingleRadIsoV_GPD_B0(xcyl, protocol, fibredir, 0);
+else
+    [E Jcyl] = SynthMeasWatsonSHCylSingleRadIsoV_GPD_B0(xcyl, protocol, fibredir, 0);
+end
+
+if (nargout == 2)
+    J(:,1) = Jcyl(:,1);
+    J(:,2) = Jcyl(:,2);
+    J(:,3) = Jcyl(:,3);
+    J(:,4) = Jcyl(:,5);
+    J(:,5) = Jcyl(:,6);
+    J(:,6) = Jcyl(:,7);
+    J(:,7) = Jcyl(:,8);
+end
+
diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickTortIsoVIsoDot_B0.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickTortIsoVIsoDot_B0.m
new file mode 100644
index 0000000000000000000000000000000000000000..2d00f444b8fecb10ab7d058001a1db6c0c63c7c9
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickTortIsoVIsoDot_B0.m
@@ -0,0 +1,53 @@
+function [E,J]=SynthMeasWatsonSHStickTortIsoVIsoDot_B0(x, protocol, fibredir)
+% Substrate: Impermeable sticks (cylinders with zero radius) in a homogeneous
+% background.
+% Orientation distribution: Watson's distribution with SH approximation
+% Signal approximation: Not applicable
+% Notes: This version estimates the hindered diffusivity from the free diffusivity
+% and packing density using Szafer et al's tortuosity model for randomly
+% packed cylinders.
+% This version includes an isotropic diffusion compartment with its own
+% diffusivity.
+% This version includes a stationary water compartment.
+% Includes a free parameter for the measurement at b=0.
+%
+% [E,J]=SynthMeasWatsonSHStickTortIsoV_B0(x, protocol, fibredir)
+% returns the measurements E according to the model and the Jacobian J of the
+% measurements with respect to the parameters.  The Jacobian does not
+% include derivates with respect to the fibre direction.
+%
+% x is the list of model parameters in SI units:
+% x(1) is the volume fraction of the intracellular space.
+% x(2) is the free diffusivity of the material inside and outside the cylinders.
+% x(3) is the concentration parameter of the Watson's distribution.
+% x(4) is the volume fraction of the isotropic compartment.
+% x(5) is the diffusivity of the isotropic compartment.
+% x(6) is the volume fraction of the isotropic restriction.
+% x(7) is the measurement at b=0.
+%
+% protocol is the object containing the acquisition protocol.
+%
+% fibredir is a unit vector along the symmetry axis of the Watson's
+% distribution.  It must be in Cartesian coordinates [x y z]' with size [3 1].
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+xcyl=[x(1) x(2) 0 x(3) x(4) x(5) x(6) x(7)];
+
+if(nargout == 1)
+    E=SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD_B0(xcyl, protocol, fibredir, 0);
+else
+    [E,Jcyl]=SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD_B0(xcyl, protocol, fibredir, 0);
+end
+
+if(nargout>1)
+    J(:,1) = Jcyl(:,1);
+    J(:,2) = Jcyl(:,2);
+    J(:,3) = Jcyl(:,4);
+    J(:,4) = Jcyl(:,5);
+    J(:,5) = Jcyl(:,6);
+    J(:,6) = Jcyl(:,7);
+    J(:,7) = Jcyl(:,8);
+end
+
diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickTortIsoV_B0.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickTortIsoV_B0.m
new file mode 100644
index 0000000000000000000000000000000000000000..15e2b092c8d2e624ac22fd7018d49d4c6ab862eb
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickTortIsoV_B0.m
@@ -0,0 +1,49 @@
+function [E,J]=SynthMeasWatsonSHStickTortIsoV_B0(x, protocol, fibredir)
+% Substrate: Impermeable sticks (cylinders with zero radius) in a homogeneous
+% background.
+% Orientation distribution: Watson's distribution with SH approximation
+% Signal approximation: Not applicable
+% Notes: This version estimates the hindered diffusivity from the free diffusivity
+% and packing density using Szafer et al's tortuosity model for randomly
+% packed cylinders.
+% This version includes an isotropic diffusion compartment with its own
+% diffusivity.
+% Includes a free parameter for the measurement at b=0.
+%
+% [E,J]=SynthMeasWatsonSHStickTortIsoV_B0(x, protocol, fibredir)
+% returns the measurements E according to the model and the Jacobian J of the
+% measurements with respect to the parameters.  The Jacobian does not
+% include derivates with respect to the fibre direction.
+%
+% x is the list of model parameters in SI units:
+% x(1) is the volume fraction of the intracellular space.
+% x(2) is the free diffusivity of the material inside and outside the cylinders.
+% x(3) is the concentration parameter of the Watson's distribution.
+% x(4) is the volume fraction of the isotropic compartment.
+% x(5) is the diffusivity of the isotropic compartment.
+% x(6) is the measurement at b=0.
+%
+% protocol is the object containing the acquisition protocol.
+%
+% fibredir is a unit vector along the symmetry axis of the Watson's
+% distribution.  It must be in Cartesian coordinates [x y z]' with size [3 1].
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+xcyl=[x(1) x(2) 0 x(3) x(4) x(5) x(6)];
+
+if(nargout == 1)
+    E=SynthMeasWatsonSHCylSingleRadTortIsoV_GPD_B0(xcyl, protocol, fibredir, 0);
+else
+    [E,Jcyl]=SynthMeasWatsonSHCylSingleRadTortIsoV_GPD_B0(xcyl, protocol, fibredir, 0);
+end
+
+if(nargout>1)
+    J(:,1) = Jcyl(:,1);
+    J(:,2) = Jcyl(:,2);
+    J(:,3) = Jcyl(:,4);
+    J(:,4) = Jcyl(:,5);
+    J(:,5) = Jcyl(:,6);
+    J(:,6) = Jcyl(:,7);
+end
diff --git a/NODDI_toolbox_v1.01/models/watson/WatsonHinderedDiffusionCoeff.m b/NODDI_toolbox_v1.01/models/watson/WatsonHinderedDiffusionCoeff.m
new file mode 100644
index 0000000000000000000000000000000000000000..aabecde3810ede74da0a56fd1330f4ecf327d4fb
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/watson/WatsonHinderedDiffusionCoeff.m
@@ -0,0 +1,51 @@
+function [dw, Jdw]=WatsonHinderedDiffusionCoeff(dPar, dPerp, kappa)
+% Substrate: Anisotropic hindered diffusion compartment
+% Orientation distribution: Watson's distribution
+%
+% [dw, Jdw]=WatsonHinderedDiffusionCoeff(dPar, dPerp, kappa)
+% returns the equivalent parallel and perpendicular diffusion coefficients
+% for hindered compartment with impermeable cylinder's oriented with a
+% Watson's distribution with a cocentration parameter of kappa
+%
+% dPar is the free diffusivity of the material inside and outside the cylinders.
+% dPerp is the hindered diffusivity outside the cylinders in perpendicular directions.
+% kappa is the concentration parameter of the Watson's distribution
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+% compute the equivalent diffusion coefficient after integrating
+% for all possible orientations
+dw = zeros(2,1);
+dParMdPerp = dPar - dPerp;
+
+if kappa < 1e-5
+	dParP2dPerp = dPar + 2*dPerp;
+	k2 = kappa*kappa;
+	dw(1) = dParP2dPerp/3 + 4*dParMdPerp*kappa/45 + 8*dParMdPerp*k2/945;
+	dw(2) = dParP2dPerp/3 - 2*dParMdPerp*kappa/45 - 4*dParMdPerp*k2/945;
+    if (nargout==2)
+        Jdw(1,1) = 1/3 + 4/45*kappa + 8/945*k2;
+        Jdw(1,2) = 2/3 - 4/45*kappa - 8/945*k2;
+        Jdw(1,3) = 4/45*dParMdPerp + 16/945*dParMdPerp*kappa;
+        Jdw(2,1) = 1/3 - 2/45*kappa - 4/945*k2;
+        Jdw(2,2) = 2/3 + 2/45*kappa + 4/945*k2;
+        Jdw(2,3) = -2/45*dParMdPerp - 8/945*dParMdPerp*kappa;
+    end
+else
+	sk = sqrt(kappa);
+	dawsonf = 0.5*exp(-kappa)*sqrt(pi)*NODDI_erfi(sk);
+	factor = sk/dawsonf;
+	dw(1) = (-dParMdPerp+2*dPerp*kappa+dParMdPerp*factor)/(2*kappa);
+	dw(2) = (dParMdPerp+2*(dPar+dPerp)*kappa-dParMdPerp*factor)/(4*kappa);
+    if (nargout==2)
+        % D[DawsonF(x),x] = 1 - 2xDawsonF(x)
+        dfactordk = ((1+2*kappa)*dawsonf - sk)/(2*sk*dawsonf*dawsonf);
+        Jdw(1,1) = (-1 + factor)/(2*kappa);
+        Jdw(1,2) = (1 + 2*kappa - factor)/(2*kappa);
+        Jdw(1,3) = (-2*dw(1) + 2*dPerp + dParMdPerp*dfactordk)/(2*kappa);
+        Jdw(2,1) = (1 + 2*kappa - factor)/(4*kappa);
+        Jdw(2,2) = (-1 + 2*kappa + factor)/(4*kappa);
+        Jdw(2,3) = (-4*dw(2) + 2*(dPar+dPerp) - dParMdPerp*dfactordk)/(4*kappa);
+    end
+end
diff --git a/NODDI_toolbox_v1.01/models/watson/WatsonSHCoeff.m b/NODDI_toolbox_v1.01/models/watson/WatsonSHCoeff.m
new file mode 100644
index 0000000000000000000000000000000000000000..ee26b76ff5271a72fc1367cfa5e74e9d7ef370d2
--- /dev/null
+++ b/NODDI_toolbox_v1.01/models/watson/WatsonSHCoeff.m
@@ -0,0 +1,191 @@
+function [C, D] = WatsonSHCoeff(k)
+% function [C, D] = WatsonSHCoeff(k)
+% Computes the spherical harmonic (SH) coefficients of the Watson's
+% distribution with the concentration parameter k (kappa) up to the 12th order
+% and the derivatives if requested.
+%
+% Truncating at the 12th order gives good approximation for kappa up to 64.
+%
+% INPUTS:
+%
+% k should be an array of positive numbers, specifying a set of
+% concentration parameters for the Watson's distribution.
+%
+% OUTPUTS:
+%
+% C will be a 2-D array and each row contains the SH coefficients of the
+% orders 0, 2, 4, ..., to 2n for the parameter in the corresponding row in
+% k.
+%
+% Note that the SH coefficients of the odd orders are always zero.
+%
+% D will be the 1st order derivative of C.
+%
+% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk)
+%
+
+large = find(k>30);
+exact = find(k>0.1);
+approx = find(k<=0.1);
+% Necessary to make matlab happy when k is a single value
+exact = exact(:);
+approx = approx(:);
+large = large(:);
+
+% The maximum order of SH coefficients (2n)
+n = 6;
+
+% Computing the SH coefficients
+C = zeros(length(k),n+1);
+
+% 0th order is a constant
+C(:,1) = 2*sqrt(pi);
+
+% Precompute the special function values
+sk = sqrt(k(exact));
+sk2 = sk.*k(exact);
+sk3 = sk2.*k(exact);
+sk4 = sk3.*k(exact);
+sk5 = sk4.*k(exact);
+sk6 = sk5.*k(exact);
+sk7 = sk6.*k(exact);
+k2 = k.^2;
+k3 = k2.*k;
+k4 = k3.*k;
+k5 = k4.*k;
+k6 = k5.*k;
+k7 = k6.*k;
+
+erfik = NODDI_erfi(sk);
+ierfik = 1./erfik;
+ek = exp(k(exact));
+dawsonk = 0.5*sqrt(pi)*erfik./ek;
+
+% for large enough kappa
+C(exact,2) = 3*sk - (3 + 2*k(exact)).*dawsonk;
+C(exact,2) = sqrt(5)*C(exact,2).*ek;
+C(exact,2) = C(exact,2).*ierfik./k(exact);
+
+C(exact,3) = (105 + 60*k(exact) + 12*k2(exact)).*dawsonk;
+C(exact,3) = C(exact,3) -105*sk + 10*sk2;
+C(exact,3) = .375*C(exact,3).*ek./k2(exact);
+C(exact,3) = C(exact,3).*ierfik;
+
+C(exact,4) = -3465 - 1890*k(exact) - 420*k2(exact) - 40*k3(exact);
+C(exact,4) = C(exact,4).*dawsonk;
+C(exact,4) = C(exact,4) + 3465*sk - 420*sk2 + 84*sk3;
+C(exact,4) = C(exact,4)*sqrt(13*pi)/64./k3(exact);
+C(exact,4) = C(exact,4)./dawsonk;
+
+C(exact,5) = 675675 + 360360*k(exact) + 83160*k2(exact) + 10080*k3(exact) + 560*k4(exact);
+C(exact,5) = C(exact,5).*dawsonk;
+C(exact,5) = C(exact,5) - 675675*sk + 90090*sk2 - 23100*sk3 + 744*sk4;
+C(exact,5) = sqrt(17)*C(exact,5).*ek;
+C(exact,5) = C(exact,5)/512./k4(exact);
+C(exact,5) = C(exact,5).*ierfik;
+
+C(exact,6) = -43648605 - 22972950*k(exact) - 5405400*k2(exact) - 720720*k3(exact) - 55440*k4(exact) - 2016*k5(exact);
+C(exact,6) = C(exact,6).*dawsonk;
+C(exact,6) = C(exact,6) + 43648605*sk - 6126120*sk2 + 1729728*sk3 - 82368*sk4 + 5104*sk5;
+C(exact,6) = sqrt(21*pi)*C(exact,6)/4096./k5(exact);
+C(exact,6) = C(exact,6)./dawsonk;
+
+C(exact,7) = 7027425405 + 3666482820*k(exact) + 872972100*k2(exact) + 122522400*k3(exact)  + 10810800*k4(exact) + 576576*k5(exact) + 14784*k6(exact);
+C(exact,7) = C(exact,7).*dawsonk;
+C(exact,7) = C(exact,7) - 7027425405*sk + 1018467450*sk2 - 302630328*sk3 + 17153136*sk4 - 1553552*sk5 + 25376*sk6;
+C(exact,7) = 5*C(exact,7).*ek;
+C(exact,7) = C(exact,7)/16384./k6(exact);
+C(exact,7) = C(exact,7).*ierfik;
+
+% for very large kappa
+if size(large,1) > 0
+  lnkd = log(k(large)) - log(30);
+  lnkd2 = lnkd.*lnkd;
+  lnkd3 = lnkd2.*lnkd;
+  lnkd4 = lnkd3.*lnkd;
+  lnkd5 = lnkd4.*lnkd;
+  lnkd6 = lnkd5.*lnkd;
+  C(large,2) = 7.52308 + 0.411538*lnkd - 0.214588*lnkd2 + 0.0784091*lnkd3 - 0.023981*lnkd4 + 0.00731537*lnkd5 - 0.0026467*lnkd6;
+  C(large,3) = 8.93718 + 1.62147*lnkd - 0.733421*lnkd2 + 0.191568*lnkd3 - 0.0202906*lnkd4 - 0.00779095*lnkd5 + 0.00574847*lnkd6;
+  C(large,4) = 8.87905 + 3.35689*lnkd - 1.15935*lnkd2 + 0.0673053*lnkd3 + 0.121857*lnkd4 - 0.066642*lnkd5 + 0.0180215*lnkd6;
+  C(large,5) = 7.84352 + 5.03178*lnkd - 1.0193*lnkd2 - 0.426362*lnkd3 + 0.328816*lnkd4 - 0.0688176*lnkd5 - 0.0229398*lnkd6;
+  C(large,6) = 6.30113 + 6.09914*lnkd - 0.16088*lnkd2 - 1.05578*lnkd3 + 0.338069*lnkd4 + 0.0937157*lnkd5 - 0.106935*lnkd6;
+  C(large,7) = 4.65678 + 6.30069*lnkd + 1.13754*lnkd2 - 1.38393*lnkd3 - 0.0134758*lnkd4 + 0.331686*lnkd5 - 0.105954*lnkd6;
+end
+
+% for small kappa
+C(approx,2) = 4/3*k(approx) + 8/63*k2(approx);
+C(approx,2) = C(approx,2)*sqrt(pi/5);
+
+C(approx,3) = 8/21*k2(approx) + 32/693*k3(approx);
+C(approx,3) = C(approx,3)*(sqrt(pi)*0.2);
+
+C(approx,4) = 16/693*k3(approx) + 32/10395*k4(approx);
+C(approx,4) = C(approx,4)*sqrt(pi/13);
+
+C(approx,5) = 32/19305*k4(approx);
+C(approx,5) = C(approx,5)*sqrt(pi/17);
+
+C(approx,6) = 64*sqrt(pi/21)*k5(approx)/692835;
+
+C(approx,7) = 128*sqrt(pi)*k6(approx)/152108775;
+
+if nargout == 1
+	return;
+end
+
+% Computing the derivatives
+dawsonk2 = dawsonk.^2;
+idawsonk2 = 1./dawsonk2;
+
+D = zeros(length(k),n+1);
+D(:,1) = 0.0;
+
+% exact
+D(exact,2) = -k(exact) + (2*sk2 -sk).*dawsonk + 2*dawsonk2;
+D(exact,2) = (.75*sqrt(5*pi))*D(exact,2)./k2(exact).*idawsonk2;
+
+D(exact,3) = 21*k(exact) - 2*k2(exact);
+D(exact,3) = D(exact,3) + (63*sk -44*sk2 + 4*sk3).*dawsonk;
+D(exact,3) = D(exact,3) - (84 + 24*k(exact)).*dawsonk2;
+D(exact,3) = D(exact,3)*(15*sqrt(pi)/32)./k3(exact).*idawsonk2;
+
+D(exact,4) = -165*k(exact) + 20*k2(exact) - 4*k3(exact);
+D(exact,4) = D(exact,4) + (-825*sk + 390*sk2 - 44*sk3 + 8*sk4).*dawsonk;
+D(exact,4) = D(exact,4) + (990 + 360*k(exact) + 40*k2(exact)).*dawsonk2;
+D(exact,4) = D(exact,4)*(21*sqrt(13*pi)/128)./k4(exact).*idawsonk2;
+
+D(exact,5) = 225225*k(exact) - 30030*k2(exact) + 7700*k3(exact) - 248*k4(exact);
+D(exact,5) = D(exact,5) + (1576575*sk - 600600*sk2 + 83160*sk3 - 15648*sk4 + 496*sk5).*dawsonk;
+D(exact,5) = D(exact,5) - (1801800 + 720720*k(exact) + 110880*k2(exact) + 6720*k3(exact)).*dawsonk2;
+D(exact,5) = D(exact,5)*(3*sqrt(17*pi)/2048)./k5(exact).*idawsonk2;
+
+D(exact,6) = -3968055*k(exact) + 556920*k2(exact) - 157248*k3(exact) + 7488*k4(exact) - 464*k5(exact);
+D(exact,6) = D(exact,6) + (-35712495*sk + 11834550*sk2 - 1900090*sk3 + 336960*sk4 - 15440*sk5 + 928*sk6).*dawsonk;
+D(exact,6) = D(exact,6) + (39680550 + 16707600*k(exact) + 2948400*k2(exact) + 262080*k3(exact) + 10080*k4(exact)).*dawsonk2;
+D(exact,6) = D(exact,6)*(11*sqrt(21*pi)/8192)./k6(exact).*idawsonk2;
+
+D(exact,7) = 540571185*k(exact) - 78343650*k2(exact) + 23279256*k3(exact) - 1319472*k4(exact) + 119504*k5(exact) - 1952*k6(exact);
+D(exact,7) = D(exact,7) + (5946283035*sk - 1786235220*sk2 + 319642092*sk3 - 53155872*sk4 + 2997456*sk5 - 240960*sk6 + 3904*sk7).*dawsonk;
+D(exact,7) = D(exact,7) - (6486854220 + 2820371400*k(exact) + 537213600*k2(exact) + 56548800*k3(exact) + 3326400*k4(exact) + 88704*k5(exact)).*dawsonk2;
+D(exact,7) = D(exact,7)*(65*sqrt(pi)/65536)./k7(exact).*idawsonk2;
+
+% approximation
+D(approx,2) = 4/3 + 16/63*k(approx) - 16/315*k2(approx) - 128/6237*k3(approx);
+D(approx,2) = D(approx,2)*sqrt(pi/5);
+
+D(approx,3) = 16/105*k(approx) + 32/1155*k2(approx) - 3712/675675*k3(approx) - 5888/2837835*k4(approx);
+D(approx,3) = D(approx,3)*sqrt(pi);
+
+D(approx,4) = 16/231*k2(approx) + 128/10395*k3(approx) - 256/106029*k4(approx);
+D(approx,4) = D(approx,4)*sqrt(pi/13);
+
+D(approx,5) = 128/19305*k3(approx) + 256/220077*k4(approx);
+D(approx,5) = D(approx,5)*sqrt(pi/17);
+
+D(approx,6) = 64/138567*k4(approx);
+D(approx,6) = D(approx,6)*sqrt(pi/21);
+
+D(approx,7) = 256/50702925*k5(approx);
+D(approx,7) = D(approx,7)*sqrt(pi);
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/README.txt b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/README.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1577d2291d230e04664584be637510d9af4e7a19
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/README.txt
@@ -0,0 +1,237 @@
+
+1. Overview
+
+The nifti1 matlab i/o code is written using matlab object oriented
+data structures (in matlab, see help datatypes).  The two
+main structures are the nifti object, that primarily manages the
+metadata (header information) and the file_array object, that manages
+the data array and disk files.
+
+The nifti1 matlab code was provided by John Ashburner, Functional
+Imaging Laboratory, Wellcome Department of Imaging Neuroscience, London.  
+This code is released under the GNU public license, see the license.txt 
+and gpl.txt files in the distribution.
+This niftimatlib release was pulled in March 2012 from the spm8  
+release: "Version 4667 (SPM8) 27-Feb-12"
+
+
+2. Install/Build
+
+The nifti1 matlab i/o code was written to run under MATLAB version 6.5 or higher.
+To install, just make sure that the niftimatlib/matlab directory is in your MATLAB
+path.  For example. in matlab you can run the addpath command:
+addpath('/usr/local/pkg/niftimatlib/matlab')
+Or, you can copy the contents of the niftimatlib/matlab directory to your <home>/matlab directory.
+
+There are two C program files included in the distribution: file2mat.c and mat2file.c
+to handle file i/o.  These need to be compiled into MATLAB mex files.  
+Precompiled mex files, taken from the spm8 distribution courtesy of the FIL, are included in 
+this distribution for the following platforms: 
+mexglx  	glnx86		Linux on x86	
+mexa64  	glnxa64		Linux on x86_64
+mexmaci 	maci		Apple Mac OS X on x86
+mexmaci64       maci64		Apple Mac OS X on x86_64
+mexw32  	win32		Microsoft Windows on x86
+mexw64  	win64		Microsoft Windows on x64
+So, you may not need to do the mex compile.  If you do compile,
+a Makefile is in the matlab directory.  Instructions are in the Makefile, a simple
+"make all" should work.  Note that you must have a MATLAB version 6.5 or higher mex compiler.
+Alternately, a make.m file for calling mex from matlab was contributed by Alle Meije Wink.
+Optional C code for a mex interface to Robert Cox's (NIH) nifti_stats.c code is provided
+in the @nifti/private/src directory.
+
+
+3. Tiny Example
+
+Short example for those who want to see something in a hurry (longer example below):
+For access to the avg152T1_LR_nifti.nii image see
+http://nifti.nimh.nih.gov/nifti-1/data
+
+
+To open an existing nifti1 file:
+
+>> % be sure to rmpath any paths that point to any spm version
+>> % after removing spm paths, clear all, then add niftimatlib path
+>> % eg:
+>> rmpath(genpath('/usr/local/pkg/spm8'))
+>> clear all
+>> addpath /usr/local/pkg/niftimatlib-1.2/matlab
+
+
+>> f = nifti('avg152T1_LR_nifti.nii');
+>> disp(f)
+NIFTI object: 1-by-1
+           dat: [91x109x91 file_array]
+           mat: [4x4 double]
+    mat_intent: 'MNI152'
+          mat0: [4x4 double]
+        timing: [1x1 struct]
+       descrip: 'FSL3.2beta'
+           cal: [0 255]
+      aux_file: 'none'
+
+
+
+>> size(f.dat)
+
+ans =
+
+    91   109    91
+
+
+3. nifti1 i/o Class Structures
+
+
+  NIFTI Object
+  ------------
+  
+  Constructor:
+  
+  a = nifti(filename);
+    a		- nifti object
+    filename	- filename for nifti1 dataset.  Optional parameter,
+    		  if omitted and empty nifti object is returned.
+  
+
+  Methods:
+ 
+    create     - Create a NIFTI-1 file
+    disp       - Disp a NIFTI-1 object
+    display    - Display a NIFTI-1 object
+    fieldnames - Fieldnames of a NIFTI-1 object
+    nifti      - Create a NIFTI-1 object
+    subsasgn   - Subscript assignment
+    subsref    - Subscript referencing
+    
+  Fields:
+      
+    aux_file
+    cal
+    dat
+    descrip
+    diminfo
+    intent
+    mat
+    mat0
+    mat0_intent
+    mat_intent
+    timing
+
+
+
+  FILE_ARRAY Object
+  -----------------
+ 
+  Constructor:
+   
+  a = file_array(fname,dim,dtype,offset,scl_slope,scl_inter)
+  a         - file_array object
+  fname     - filename
+  dim       - dimensions (default = [0 0] )
+  dtype     - datatype   (default = 'uint8-le')
+  offset    - offset into file (default = 0)
+  scl_slope - scalefactor (default = 1)
+  scl_inter - DC offset, such that dat = raw*scale + inter (default = 0)
+
+
+  Methods:
+
+	cat		-  Concatenate file_array objects.        
+	disp 		-  Display a file_array object      
+	display 	-  Display a file_array object   
+	double 		-  Convert to double precision     
+	end 		-  Overloaded end function for file_array objects        
+	fieldnames	-  Fieldnames of a file-array object 
+	horzcat		-  Horizontal concatenation of file_array objects     
+	length 		-  Overloaded length function for file_array objects
+	ndims 		-  Number of dimensions
+	numel 		-  Number of simple file arrays involved
+	numeric 	-  Convert to numeric form  
+	reshape 	-  Overloaded reshape function for file_array objects   
+	size 		-  Overloaded size function for file_array objects     
+	subsasgn 	-  Overloaded subsasgn function for file_array objects
+	subsref		-  Subscripted reference.
+	vertcat		-  Vertical concatenation of file_array objects
+	
+  Disallowed file_array methods:
+	ctranspose	-  Complex conjugate transposing is not allowed
+	permute		-  Permuting is not allowed
+	transpose 	-  Transposing is not allowed
+
+  Fields:
+
+    fname
+    dim
+    dtype
+    offset
+    scl_inter
+    scl_slope
+	
+	
+	 
+4. Examples
+
+  % Example of creating a simulated .nii file.
+  dat         = file_array;
+  dat.fname   = 'junk.nii';
+  dat.dim     = [64 64 32];
+  dat.dtype   = 'FLOAT64-LE';
+  dat.offset  = ceil(348/8)*8;
+
+  % alternatively:
+  % dat = file_array( 'junk.nii',dim,dtype,off,scale,inter)
+  
+  disp(dat)
+  
+  % Create an empty NIFTI structure
+  N = nifti;
+  
+  fieldnames(N) % Dump fieldnames
+  
+  % Creating all the NIFTI header stuff
+  N.dat = dat;
+  N.mat = [2 0 0 -110 ; 0 2 0 -110; 0 0 -2 92; 0 0 0 1];
+  N.mat_intent = 'xxx'; % dump possibilities
+  N.mat_intent = 'Scanner';
+  N.mat0 = N.mat;
+  N.mat0_intent = 'Aligned';
+  
+  N.diminfo.slice = 3;
+  N.diminfo.phase = 2;
+  N.diminfo.frequency = 2;
+  N.diminfo.slice_time.code='xxx'; % dump possibilities 
+  N.diminfo.slice_time.code = 'sequential_increasing';
+  N.diminfo.slice_time.start = 1;
+  N.diminfo.slice_time.end = 32;
+  N.diminfo.slice_time.duration = 3/32;
+  
+  N.intent.code='xxx' ; % dump possibilities
+  N.intent.code='FTEST'; % or N.intent.code=4;
+  N.intent.param = [4 8];
+  
+  N.timing.toffset = 28800;
+  N.timing.tspace=3;
+  N.descrip = 'This is a NIFTI-1 file';
+  N.aux_file='aux-file-name.txt';
+  N.cal = [0 1];
+  
+  create(N); % Writes hdr info
+  
+  %% Note that this call writes the data to the disk file
+  dat(:,:,:)=0; % Write out the data as all zeros
+
+  [i,j,k] = ndgrid(1:64,1:64,1:32);
+  dat(find((i-32).^2+(j-32).^2+(k*2-32).^2 < 30^2))=1; % Write some ones in the file
+  dat(find((i-32).^2+(j-32).^2+(k*2-32).^2 < 15^2))=2;
+  
+
+  % displaying a slice
+  imagesc(dat(:,:,12));colorbar
+  
+  % get a handle to 'junk.nii';
+  M=nifti('junk.nii');
+  
+  imagesc(M.dat(:,:,12));
+ 
+
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/gpl.txt b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/gpl.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6d45519c8c6cc926a7d6d96ebc45de7226f66099
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/gpl.txt
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/license.txt b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/license.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c224bbbb14631845777fd7494d558f11a3751328
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/license.txt
@@ -0,0 +1,96 @@
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+===================================================================
+The GNU General Public License (gpl.txt) is available from:
+    http://www.gnu.org/copyleft/gpl.html
+
+Note: The niftilib matlab files are taken, with permission,  from the 
+      SPM8 software package (http://www.fil.ion.ucl.ac.uk/spm/).  
+      Please note that this license pertains only to the files listed below, 
+      dealing with nifti1 i/o methods, and has no bearing at all on the SPM
+      software package.
+===================================================================
+matlab/Makefile
+matlab/@file_array/numel.m
+matlab/@file_array/permute.m
+matlab/@file_array/reshape.m
+matlab/@file_array/subsasgn.m
+matlab/@file_array/subsref.m
+matlab/@file_array/vertcat.m
+matlab/@file_array/private/src/README
+matlab/@file_array/private/src/file2mat.c
+matlab/@file_array/private/src/mat2file.c
+matlab/@file_array/private/datatypes.m
+matlab/@file_array/private/dim.m
+matlab/@file_array/private/dtype.m
+matlab/@file_array/private/file2mat.m
+matlab/@file_array/private/fname.m
+matlab/@file_array/private/mat2file.m
+matlab/@file_array/private/mystruct.m
+matlab/@file_array/private/offset.m
+matlab/@file_array/private/permission.m
+matlab/@file_array/private/resize_scales.m
+matlab/@file_array/private/scl_inter.m
+matlab/@file_array/private/scl_slope.m
+matlab/@file_array/cat.m
+matlab/@file_array/Contents.m
+matlab/@file_array/ctranspose.m
+matlab/@file_array/display.m
+matlab/@file_array/disp.m
+matlab/@file_array/double.m
+matlab/@file_array/end.m
+matlab/@file_array/fieldnames.m
+matlab/@file_array/file_array.m
+matlab/@file_array/horzcat.m
+matlab/@file_array/isnan.m
+matlab/@file_array/length.m
+matlab/@file_array/loadobj.m
+matlab/@file_array/ndims.m
+matlab/@file_array/numeric.m
+matlab/@file_array/size.m
+matlab/@file_array/transpose.m
+matlab/@nifti/private/spm_fileparts.m
+matlab/@nifti/private/decode_qform0.m
+matlab/@nifti/private/empty_hdr.m
+matlab/@nifti/private/encode_qform0.m
+matlab/@nifti/private/findindict.m
+matlab/@nifti/private/getdict.m
+matlab/@nifti/private/M2Q.m
+matlab/@nifti/private/mayo2nifti1.m
+matlab/@nifti/private/mayostruc.m
+matlab/@nifti/private/nifti_stats.m
+matlab/@nifti/private/niftistruc.m
+matlab/@nifti/private/Q2M.m
+matlab/@nifti/private/read_extras.m
+matlab/@nifti/private/read_hdr.m
+matlab/@nifti/private/read_hdr_raw.m
+matlab/@nifti/private/write_extras.m
+matlab/@nifti/private/write_hdr_raw.m
+matlab/@nifti/private/src/nifti_stats.c
+matlab/@nifti/private/src/nifti_stats_mex.c
+matlab/@nifti/private/src/nifti1.h
+matlab/@nifti/private/src/README
+matlab/@nifti/private/spm_existfile.m
+matlab/@nifti/Contents.m
+matlab/@nifti/create.m
+matlab/@nifti/display.m
+matlab/@nifti/disp.m
+matlab/@nifti/fieldnames.m
+matlab/@nifti/nifti.m
+matlab/@nifti/structn.m
+matlab/@nifti/subsasgn.m
+matlab/@nifti/subsref.m
+matlab/spm_flip_analyze_images.m
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/Contents.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/Contents.m
new file mode 100644
index 0000000000000000000000000000000000000000..0180f20db129a45c67940203853acd2864b76c63
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/Contents.m
@@ -0,0 +1,55 @@
+% File Array Object
+%
+%   file_array   - create a file_array
+%   horzcat      - horizontal concatenation
+%   vertcat      - vertical concatenation
+%   size         - size of array
+%   length       - length of longest dimension
+%   subsref      - subscripted reference
+%   end          - last index in an indexing expression
+%   resize       - resize (but only of simple file_array structures)
+%
+%   other operations are unlikely to work.
+%
+% Example usage.
+%
+% % Create a file array object by mapping test_le.img
+% % to a 256x256x100 array, of datatype float32, stored
+% % in a little-endian way starting at byte 0.
+% fa0 = file_array('test_le.img',[256 256 100], 'FLOAT32-LE',0)
+%
+% % Creating an object from test_be.img, but skipping
+% % the first plane of data.  Data stored as big-endian
+% fa1 = file_array('test_be.img',[256 256 99], 'FLOAT32-BE',4*256*256)
+%
+% % Reshape procedure
+% fa2 = reshape(fa1,[128 2 256 99])
+%
+% % Concatenation
+% fa3 = [[fa0 fa0]; [fa0 fa0]]
+% fa4 = cat(3,fa0,fa1)
+%
+% % Note that reshape will not work on the above
+% % concatenated objects
+%
+% % Accessing values from the objects
+% img    = fa1(:,:,40);
+% pixval = fa4(50,50,:);
+% small  = fa1(1:2:end,1:2:end,40);
+%
+% % Determining dimensions
+% size(fa4)
+% size(fa2)
+% length(fa0)
+% _________________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: Contents.m 2696 2009-02-05 20:29:48Z guillaume 
+
+%
+% niftilib $Id: Contents.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/cat.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/cat.m
new file mode 100644
index 0000000000000000000000000000000000000000..bc3c37e10243df562a7da6adce8fe02299ca3e53
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/cat.m
@@ -0,0 +1,44 @@
+function o = cat(dr,varargin)
+% Concatenate file_array objects.  The result is a non-simple object
+% that can no longer be reshaped.
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: cat.m 4136 2010-12-09 22:22:28Z guillaume 
+
+%
+% niftilib $Id: cat.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+if dr>32 || dr<0, error('Unknown command option.'); end;
+dr   = max(round(dr),1);
+d    = ones(nargin-1,16);
+tmp  = {};
+dpos = 0;
+for i=1:nargin-1,
+    vi = varargin{i};
+    if strcmp(class(vi),'file_array')
+        sz                = size(vi);
+        d(i,1:length(sz)) = sz;
+        svi               = struct(vi);
+        svi               = svi(:);
+        for j=1:length(svi(:)),
+            if length(svi(j).pos)<dr
+                svi(j).pos((length(svi(j).pos)+1):dr) = 1;
+            end
+            svi(j).pos(dr)= svi(j).pos(dr) + dpos;
+        end;
+        dpos              = dpos + d(i,dr);
+        tmp{i}            = svi;
+    else
+        error(['Conversion to file_array from ' class(vi) ' is not possible.']);
+    end;
+end;
+if any(diff(d(:,[1:(dr-1) (dr+1):end]),1,1))
+    error('All matrices on a row in the bracketed expression must have the same number of rows.');
+else
+    o = vertcat(tmp{:});
+    o = file_array(o);
+end;
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/ctranspose.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/ctranspose.m
new file mode 100644
index 0000000000000000000000000000000000000000..6cc309036d450674815b983abc6daa639ccf0248
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/ctranspose.m
@@ -0,0 +1,14 @@
+function varargout = ctranspose(varargin)
+% Transposing not allowed
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: ctranspose.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: ctranspose.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+error('file_array objects can not be transposed.');
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/disp.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/disp.m
new file mode 100644
index 0000000000000000000000000000000000000000..f33b2fc6a64faa272f5fb584aefa954648704b0e
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/disp.m
@@ -0,0 +1,39 @@
+function disp(obj)
+% Display a file_array object
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: disp.m 4136 2010-12-09 22:22:28Z guillaume 
+
+%
+% niftilib $Id: disp.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+if numel(struct(obj))>1,
+    fprintf('       %s object: ', class(obj));
+    sz = size(obj);
+    if length(sz)>4,
+        fprintf('%d-D\n',length(sz));
+    else
+        for i=1:(length(sz)-1),
+            fprintf('%d-by-',sz(i));
+        end;
+        fprintf('%d\n',sz(end));
+    end;
+else
+    disp(mystruct(obj))
+end;
+return;
+%=======================================================================
+
+%=======================================================================
+function t = mystruct(obj)
+fn = fieldnames(obj);
+for i=1:length(fn)
+    t.(fn{i}) = subsref(obj,struct('type','.','subs',fn{i}));
+end;
+return;
+%=======================================================================
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/display.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/display.m
new file mode 100644
index 0000000000000000000000000000000000000000..f36a8fdf4e2c23735d25e76f4c8649928b849015
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/display.m
@@ -0,0 +1,19 @@
+function display(obj)
+% Display a file_array object
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: display.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: display.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+disp(' ');
+disp([inputname(1),' = '])
+disp(' ');
+disp(obj)
+disp(' ')
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/double.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/double.m
new file mode 100644
index 0000000000000000000000000000000000000000..dcee922442919845d641add493685c87c2d7a1c2
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/double.m
@@ -0,0 +1,17 @@
+function out = double(fa)
+% Convert to double precision
+% FORMAT double(fa)
+% fa - a file_array
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: double.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: double.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+out = double(numeric(fa));
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/end.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/end.m
new file mode 100644
index 0000000000000000000000000000000000000000..39f2bb82fd3370f3b5f0732fd1ab68d5553d29ad
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/end.m
@@ -0,0 +1,22 @@
+function en = end(a,k,n)
+% Overloaded end function for file_array objects.
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: end.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: end.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+dim = size(a);
+if k>length(dim)
+    en = 1;
+else
+    if n<length(dim),
+    dim = [dim(1:(n-1)) prod(dim(n:end))];
+    end;
+    en = dim(k);
+end;
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/fieldnames.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/fieldnames.m
new file mode 100644
index 0000000000000000000000000000000000000000..7ef162bd5577745da70bbeac62cc3684fb838d10
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/fieldnames.m
@@ -0,0 +1,21 @@
+function t = fieldnames(obj)
+% Fieldnames of a file-array object
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: fieldnames.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: fieldnames.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+t = {...
+    'fname'
+    'dim'
+    'dtype'
+    'offset'
+    'scl_slope'
+    'scl_inter'
+};
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/file_array.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/file_array.m
new file mode 100644
index 0000000000000000000000000000000000000000..44fbe2fb36f0832e6ad81ef19cdb0d3a75395ba5
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/file_array.m
@@ -0,0 +1,47 @@
+function a = file_array(varargin)
+% Function for creating file_array objects.
+% FORMAT a = file_array(fname,dim,dtype,offset,scl_slope,scl_inter,permission)
+% a          - file_array object
+% fname      - filename
+% dim        - dimensions (default = [0 0] )
+% dtype      - datatype   (default = 'uint8-le')
+% offset     - offset into file (default = 0)
+% scl_slope  - scalefactor (default = 1)
+% scl_inter  - DC offset, such that dat = raw*scale + inter (default = 0)
+% permission - Write permission, either 'rw' or 'ro' (default = 'rw')
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: file_array.m 4136 2010-12-09 22:22:28Z guillaume 
+
+%
+% niftilib $Id: file_array.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+if nargin==1
+    if isstruct(varargin{1}),
+        a = class(varargin{1},'file_array');
+        return;
+    elseif isa(varargin{1},'file_array'),
+        a = varargin{1};
+        return;
+    end;
+end;
+a = struct('fname','','dim',[0 0],'dtype',2,...
+           'be',0,'offset',0,'pos',[],'scl_slope',[],'scl_inter',[], 'permission','rw');
+%a = class(a,'file_array');
+
+if nargin>=1, a =     fname(a,varargin{1}); end;
+if nargin>=2, a =       dim(a,varargin{2}); end;
+if nargin>=3, a =     dtype(a,varargin{3}); end;
+if nargin>=4, a =    offset(a,varargin{4}); end;
+if nargin>=5, a = scl_slope(a,varargin{5}); end;
+if nargin>=6, a = scl_inter(a,varargin{6}); end;
+if nargin>=7, a = permission(a,varargin{7}); end;
+
+a.pos = ones(size(a.dim));
+a     = file_array(a);
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/horzcat.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/horzcat.m
new file mode 100644
index 0000000000000000000000000000000000000000..46b997c852cec8cc1982a924d15ed08a87e9028c
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/horzcat.m
@@ -0,0 +1,16 @@
+function o = horzcat(varargin)
+% Horizontal concatenation of file_array objects
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: horzcat.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: horzcat.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+o    = cat(2,varargin{:});
+return;
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/isnan.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/isnan.m
new file mode 100644
index 0000000000000000000000000000000000000000..986846b5130189291f214a75a4c5a65911f77622
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/isnan.m
@@ -0,0 +1,26 @@
+function out = isnan(fa)
+% Convert to numeric form
+% FORMAT isnan(fa)
+% fa - a file_array
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: isnan.m 1301 2008-04-03 13:21:44Z john 
+
+%
+% niftilib $Id: isnan.m,v 1.1 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+bs  = 10240;
+m   = size(fa);
+fa  = reshape(fa,prod(m),1);
+n   = prod(m);
+out = false(m);
+for i=1:ceil(n/bs),
+    ii      = ((((i-1)*bs)+1):min((i*bs),n))';
+    tmp     = subsref(fa,struct('type','()','subs',{{ii}}));
+    out(ii) = isnan(tmp);
+end
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/length.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/length.m
new file mode 100644
index 0000000000000000000000000000000000000000..a375b3c0cf411743bd92ab7925590da46ab31704
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/length.m
@@ -0,0 +1,16 @@
+function l = length(x)
+% Overloaded length function for file_array objects
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: length.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: length.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+l = max(size(x));
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/loadobj.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/loadobj.m
new file mode 100644
index 0000000000000000000000000000000000000000..dafc535fe8de5e16ba9456e5191ae685acb384c8
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/loadobj.m
@@ -0,0 +1,19 @@
+function b = loadobj(a)
+% loadobj for file_array class
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: loadobj.m 1544 2008-05-06 10:34:36Z guillaume 
+
+%
+% niftilib $Id: loadobj.m,v 1.1 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+if isa(a,'file_array')
+    b = a;
+else
+    a = permission(a, 'rw');
+    b = file_array(a);
+end
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/ndims.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/ndims.m
new file mode 100644
index 0000000000000000000000000000000000000000..c76163b6d25da76c33ed6a2471669ade5e337cd6
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/ndims.m
@@ -0,0 +1,17 @@
+function out = ndims(fa)
+% Number of dimensions
+%_______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: ndims.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: ndims.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+out = size(fa);
+out = length(out);
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/numel.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/numel.m
new file mode 100644
index 0000000000000000000000000000000000000000..d7931ab0dbbfa3dcb92d9c9fe251c22ff0936e4c
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/numel.m
@@ -0,0 +1,19 @@
+function t = numel(obj)
+% Number of simple file arrays involved.
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: numel.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: numel.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+% Should be this, but it causes problems when accessing
+% obj as a structure.
+%t = prod(size(obj));
+
+t  = numel(struct(obj));
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/numeric.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/numeric.m
new file mode 100644
index 0000000000000000000000000000000000000000..3e6872083158ffdc34b0e07170195e93b89b719b
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/numeric.m
@@ -0,0 +1,19 @@
+function out = numeric(fa)
+% Convert to numeric form
+% FORMAT numeric(fa)
+% fa - a file_array
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: numeric.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: numeric.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+[vo{1:ndims(fa)}] = deal(':');
+out = subsref(fa,struct('type','()','subs',{vo}));
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/permute.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/permute.m
new file mode 100644
index 0000000000000000000000000000000000000000..dd119d05dc9250a5bb6a2d4304b57559a953f6b0
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/permute.m
@@ -0,0 +1,15 @@
+function varargout = permute(varargin)
+% Can not be permuted.
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: permute.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: permute.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+error('file_array objects can not be permuted.');
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/datatypes.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/datatypes.m
new file mode 100644
index 0000000000000000000000000000000000000000..d8ee22db8b0183ef227299cb7e9b5c80403599f7
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/datatypes.m
@@ -0,0 +1,61 @@
+function dt = datatypes
+% Datatype
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: datatypes.m 4136 2010-12-09 22:22:28Z guillaume 
+
+
+% 
+% niftilib $Id: datatypes.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+persistent dtype
+if isempty(dtype),
+    t = true;
+    f = false;
+    table = {...
+        0   ,'UNKNOWN'   ,'uint8'   ,@uint8  ,1,1  ,t,t,f
+        1   ,'BINARY'    ,'uint1'   ,@logical,1,1/8,t,t,f
+        256 ,'INT8'      ,'int8'    ,@int8   ,1,1  ,t,f,t
+        2   ,'UINT8'     ,'uint8'   ,@uint8  ,1,1  ,t,t,t
+        4   ,'INT16'     ,'int16'   ,@int16  ,1,2  ,t,f,t
+        512 ,'UINT16'    ,'uint16'  ,@uint16 ,1,2  ,t,t,t
+        8   ,'INT32'     ,'int32'   ,@int32  ,1,4  ,t,f,t
+        768 ,'UINT32'    ,'uint32'  ,@uint32 ,1,4  ,t,t,t
+        1024,'INT64'     ,'int64'   ,@int64  ,1,8  ,t,f,f
+        1280,'UINT64'    ,'uint64'  ,@uint64 ,1,8  ,t,t,f
+        16  ,'FLOAT32'   ,'float32' ,@single ,1,4  ,f,f,t
+        64  ,'FLOAT64'   ,'double'  ,@double ,1,8  ,f,f,t
+        1536,'FLOAT128'  ,'float128',@error  ,1,16 ,f,f,f
+        32  ,'COMPLEX64' ,'float32' ,@single ,2,4  ,f,f,f
+        1792,'COMPLEX128','double'  ,@double ,2,8  ,f,f,f
+        2048,'COMPLEX256','float128',@error  ,2,16 ,f,f,f
+        128 ,'RGB24'     ,'uint8'   ,@uint8  ,3,1  ,t,t,f};
+    dtype = struct(...
+        'code'     ,table(:,1),...
+        'label'    ,table(:,2),...
+        'prec'     ,table(:,3),...
+        'conv'     ,table(:,4),...
+        'nelem'    ,table(:,5),...
+        'size'     ,table(:,6),...
+        'isint'    ,table(:,7),...
+        'unsigned' ,table(:,8),...
+        'min',-Inf,'max',Inf',...
+        'supported',table(:,9));
+    for i=1:length(dtype),
+        if dtype(i).isint
+            if dtype(i).unsigned
+                dtype(i).min =  0;
+                dtype(i).max =  2^(8*dtype(i).size)-1;
+            else
+                dtype(i).min = -2^(8*dtype(i).size-1);
+                dtype(i).max =  2^(8*dtype(i).size-1)-1;
+            end;
+        end;
+    end;
+end;
+
+dt = dtype;
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/dim.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/dim.m
new file mode 100644
index 0000000000000000000000000000000000000000..e4a1438cf637f26345549c40f834ecd5396d7307
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/dim.m
@@ -0,0 +1,42 @@
+function varargout = dim(varargin)
+% Format
+% For getting the value
+% dat = dim(obj)
+%
+% For setting the value
+% obj = dim(obj,dat)
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: dim.m 1143 2008-02-07 19:33:33Z spm 
+
+% 
+% niftilib $Id: dim.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+if nargin==2,
+    varargout{1} = asgn(varargin{:});
+elseif nargin==1,
+    varargout{1} = ref(varargin{:});
+else
+    error('Wrong number of arguments.');
+end;
+return;
+
+function dat = ref(obj)
+dat = obj.dim;
+return;
+
+function obj = asgn(obj,dat)
+if isnumeric(dat) && all(dat>=0) && all(rem(dat,1)==0),
+    dat = [double(dat(:)') 1 1];
+    lim = max([2 find(dat~=1)]);
+    dat = dat(1:lim);
+    obj.dim = dat;
+else
+    error('"dim" must be a vector of positive integers.');
+end;
+return;
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/dtype.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/dtype.m
new file mode 100644
index 0000000000000000000000000000000000000000..dca0a23b99178aa1cbae66ba682917a55f2511b2
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/dtype.m
@@ -0,0 +1,91 @@
+function varargout = dtype(varargin)
+% Format
+% For getting the value
+% dat = dtype(obj)
+%
+% For setting the value
+% obj = dtype(obj,dat)
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: dtype.m 1143 2008-02-07 19:33:33Z spm 
+
+% 
+% niftilib $Id: dtype.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+
+if nargin==2,
+    varargout{1} = asgn(varargin{:});
+elseif nargin==1,
+    varargout{1} = ref(varargin{:});
+else
+    error('Wring number of arguments.');
+end;
+return;
+
+function t = ref(obj)
+d   = datatypes;
+mch = find(cat(1,d.code)==obj.dtype);
+if isempty(mch), t = 'UNKNOWN'; else t = d(mch).label; end;
+if obj.be, t = [t '-BE']; else t = [t '-LE']; end;
+return;
+
+function obj = asgn(obj,dat)
+d   = datatypes;
+if isnumeric(dat)
+    if numel(dat)>=1,
+        mch = find(cat(1,d.code)==dat(1));
+        if isempty(mch) || mch==0,
+            fprintf('Invalid datatype (%d).', dat(1));
+            disp('First part of datatype should be of one of the following');
+            disp(sortrows([num2str(cat(1,d.code)) ...
+                repmat(' ',numel(d),2) strvcat(d.label)]));
+            %error(['Invalid datatype (' num2str(dat(1)) ').']);
+            return;
+        end;
+        obj.dtype = double(dat(1));
+    end;
+    if numel(dat)>=2,
+        obj.be = double(dat(2)~=0);
+    end;
+    if numel(dat)>2,
+        error('Too many elements in numeric datatype.');
+    end;
+elseif ischar(dat),
+    dat1 = lower(dat);
+    sep  = find(dat1=='-' | dat1=='/');
+    sep  = sep(sep~=1);
+    if ~isempty(sep),
+        c1 = dat1(1:(sep(1)-1));
+        c2 = dat1((sep(1)+1):end);
+    else
+        c1 = dat1;
+        c2 = '';
+    end;
+    mch = find(strcmpi(c1,lower({d.label})));
+    if isempty(mch),
+        disp('First part of datatype should be of one of the following');
+        disp(sortrows([num2str(cat(1,d.code)) ...
+            repmat(' ',numel(d),2) strvcat(d.label)]));
+        %error(['Invalid datatype (' c1 ').']);
+        return;
+    else
+        obj.dtype = double(d(mch(1)).code);
+    end;
+    if any(c2=='b'),
+        if any(c2=='l'),
+            error('Cannot be both big and little endian.');
+        end;
+        obj.be = 1;
+    elseif any(c2=='l'),
+        obj.be = 0;
+    end;
+else
+    error('Invalid datatype.');
+end;
+return;
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.m
new file mode 100644
index 0000000000000000000000000000000000000000..819946828648509a09ac1471bcc8947de13fccaf
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.m
@@ -0,0 +1,21 @@
+function val = file2mat(a,varargin)
+% Function for reading from file_array objects.
+% FORMAT val = file2mat(a,ind1,ind2,ind3,...)
+% a      - file_array object
+% indx   - indices for dimension x (int32)
+% val    - the read values
+%
+% This function is normally called by file_array/subsref
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+% John Ashburner
+% Id: file2mat.m 1530 2008-04-30 19:28:22Z guillaume 
+
+% 
+% niftilib $Id: file2mat.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+%-This is merely the help file for the compiled routine
+error('file2mat.c not compiled - see Makefile');
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexa64 b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexa64
new file mode 100644
index 0000000000000000000000000000000000000000..e0f76658c7a7e87b895864d43b19ba06af2946ea
Binary files /dev/null and b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexa64 differ
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexglx b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexglx
new file mode 100644
index 0000000000000000000000000000000000000000..745b68660baaf9c0dccc97a116fa006c54497345
Binary files /dev/null and b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexglx differ
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexmaci b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexmaci
new file mode 100644
index 0000000000000000000000000000000000000000..b932e4f334a808e12e28dd27a8bf1d24ab0e3e0c
Binary files /dev/null and b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexmaci differ
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexmaci64 b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexmaci64
new file mode 100755
index 0000000000000000000000000000000000000000..d5a41f9db23b8d54e56afb6fe4ba26047766c8ca
Binary files /dev/null and b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexmaci64 differ
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexw32 b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexw32
new file mode 100755
index 0000000000000000000000000000000000000000..1eb71ec9216aef2d33bc4b25fd14b7d3d294dd77
Binary files /dev/null and b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexw32 differ
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexw64 b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexw64
new file mode 100644
index 0000000000000000000000000000000000000000..9f06847197ed239024918faf2aa3b39ce735a1f5
Binary files /dev/null and b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexw64 differ
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/fname.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/fname.m
new file mode 100644
index 0000000000000000000000000000000000000000..42ea71267d0cd47f06049689b95bae750330936e
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/fname.m
@@ -0,0 +1,40 @@
+function varargout = fname(varargin)
+% Format
+% For getting the value
+% dat = fname(obj)
+%
+% For setting the value
+% obj = fname(obj,dat)
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: fname.m 1143 2008-02-07 19:33:33Z spm 
+
+% 
+% niftilib $Id: fname.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+
+if nargin==2,
+    varargout{1} = asgn(varargin{:});
+elseif nargin==1,
+    varargout{1} = ref(varargin{:});
+else
+    error('Wrong number of arguments.');
+end;
+return;
+
+function dat = ref(obj)
+dat = obj.fname;
+return;
+
+function obj = asgn(obj,dat)
+if ischar(dat)
+    obj.fname = deblank(dat(:)');
+else
+    error('"fname" must be a character string.');
+end;
+return;
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.m
new file mode 100644
index 0000000000000000000000000000000000000000..12f140c848b431bc527677a3834da4595875c85a
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.m
@@ -0,0 +1,21 @@
+function mat2file(a,val,varargin)
+% Function for writing to file_array objects.
+% FORMAT mat2file(a,val,ind1,ind2,ind3,...)
+% a      - file_array object
+% val    - values to write
+% indx   - indices for dimension x (int32)
+%
+% This function is normally called by file_array/subsasgn
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+% John Ashburner
+% Id: mat2file.m 1530 2008-04-30 19:28:22Z guillaume 
+
+% 
+% niftilib $Id: mat2file.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+%-This is merely the help file for the compiled routine
+error('mat2file.c not compiled - see Makefile');
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexa64 b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexa64
new file mode 100644
index 0000000000000000000000000000000000000000..4b264678e6136c7085d9281e5c2e616b87238ac0
Binary files /dev/null and b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexa64 differ
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexglx b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexglx
new file mode 100644
index 0000000000000000000000000000000000000000..3f277ed0ec84038e43efa73429ba9b77f58aef9a
Binary files /dev/null and b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexglx differ
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexmaci b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexmaci
new file mode 100644
index 0000000000000000000000000000000000000000..56a9a2f3f2dd1328171202d058c0e8762f77a6b1
Binary files /dev/null and b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexmaci differ
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexmaci64 b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexmaci64
new file mode 100755
index 0000000000000000000000000000000000000000..6c7da4370ea201514ca6a5527b38dd2f5d49c705
Binary files /dev/null and b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexmaci64 differ
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexw32 b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexw32
new file mode 100755
index 0000000000000000000000000000000000000000..783d6fb855cac0e53be08c0acb2c7291ba53e9e2
Binary files /dev/null and b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexw32 differ
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexw64 b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexw64
new file mode 100644
index 0000000000000000000000000000000000000000..2ba10482c90dae85d8b375aa47c5d5b85517c2ea
Binary files /dev/null and b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexw64 differ
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mystruct.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mystruct.m
new file mode 100644
index 0000000000000000000000000000000000000000..124b802395c1d045856789427d735123598ccbcd
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mystruct.m
@@ -0,0 +1,21 @@
+function t = mystruct(obj)
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: mystruct.m 1143 2008-02-07 19:33:33Z spm 
+
+% 
+% niftilib $Id: mystruct.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+if numel(obj)~=1,
+    error('Too many elements to convert');
+end;
+fn = fieldnames(obj);
+for i=1:length(fn)
+    t.(fn{i}) = subsref(obj,struct('type','.','subs',fn{i}));
+end;
+return;
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/offset.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/offset.m
new file mode 100644
index 0000000000000000000000000000000000000000..258487bfea1bc08ba0b58613e6c413bb67ed7feb
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/offset.m
@@ -0,0 +1,40 @@
+function varargout = offset(varargin)
+% Format
+% For getting the value
+% dat = offset(obj)
+%
+% For setting the value
+% obj = offset(obj,dat)
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: offset.m 1143 2008-02-07 19:33:33Z spm 
+
+% 
+% niftilib $Id: offset.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+
+if nargin==2,
+    varargout{1} = asgn(varargin{:});
+elseif nargin==1,
+    varargout{1} = ref(varargin{:});
+else
+    error('Wrong number of arguments.');
+end;
+return;
+
+function dat = ref(obj)
+dat = obj.offset;
+return;
+
+function obj = asgn(obj,dat)
+if isnumeric(dat) && numel(dat)==1 && dat>=0 && rem(dat,1)==0,
+    obj.offset = double(dat);
+else
+    error('"offset" must be a positive integer.');
+end;
+return;
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/permission.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/permission.m
new file mode 100644
index 0000000000000000000000000000000000000000..270187192d289436f35189e6f2ff70fd0b1170d9
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/permission.m
@@ -0,0 +1,48 @@
+function varargout = permission(varargin)
+% Format
+% For getting the value
+% dat = permission(obj)
+%
+% For setting the value
+% obj = permission(obj,dat)
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: permission.m 1340 2008-04-09 17:11:23Z john 
+
+% 
+% niftilib $Id: permission.m,v 1.1 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+
+if nargin==2,
+    varargout{1} = asgn(varargin{:});
+elseif nargin==1,
+    varargout{1} = ref(varargin{:});
+else
+    error('Wrong number of arguments.');
+end;
+return;
+
+function dat = ref(obj)
+dat = obj.permission;
+return;
+
+function obj = asgn(obj,dat)
+if ischar(dat)
+    tmp = lower(deblank(dat(:)'));
+    switch tmp,
+    case 'ro',
+    case 'rw',
+    otherwise,
+        error('Permission must be either "ro" or "rw"');
+    end
+    obj.permission = tmp;
+else
+    error('"permission" must be a character string.');
+end;
+return;
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/resize_scales.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/resize_scales.m
new file mode 100644
index 0000000000000000000000000000000000000000..99f6fe8f3ca2f2406076949ea0f355ae06e13b8d
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/resize_scales.m
@@ -0,0 +1,29 @@
+function s1 = resize_scales(s0,dim,args)
+% Resize scalefactors 
+% _________________________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: resize_scales.m 1143 2008-02-07 19:33:33Z spm 
+
+% 
+% niftilib $Id: resize_scales.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+dim = [dim ones(1,max(numel(args)-numel(dim),0))];
+args1 = cell(1,numel(args));
+for i=1:numel(args),
+    if max(args{i})>dim(i) || min(args{i})<1,
+        error('Index exceeds matrix dimensions (1).');
+    end;
+
+    if size(s0,i)==1,
+        args1{i} = ones(size(args{i}));
+    else
+        args1{i} = args{i};
+    end;
+end;
+
+s1 = s0(args1{:});
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/scl_inter.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/scl_inter.m
new file mode 100644
index 0000000000000000000000000000000000000000..2fad537ec6b09eed8f8db69f8fe8e1d1c72ee64b
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/scl_inter.m
@@ -0,0 +1,41 @@
+function varargout = scl_inter(varargin)
+% Format
+% For getting the value
+% dat = scl_inter(obj)
+%
+% For setting the value
+% obj = scl_inter(obj,dat)
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: scl_inter.m 1143 2008-02-07 19:33:33Z spm 
+
+% 
+% niftilib $Id: scl_inter.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+
+if nargin==2,
+    varargout{1} = asgn(varargin{:});
+elseif nargin==1,
+    varargout{1} = ref(varargin{:});
+else
+    error('Wrong number of arguments.');
+end;
+return;
+
+function dat = ref(obj)
+dat = obj.scl_inter;
+return;
+
+function obj = asgn(obj,dat)
+if isnumeric(dat), % && numel(dat)<=1,
+    obj.scl_inter = double(dat);
+else
+    error('"scl_inter" must be numeric.');
+end;
+return;
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/scl_slope.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/scl_slope.m
new file mode 100644
index 0000000000000000000000000000000000000000..75d66179ea7721629732864b6db9d25867ea5d5a
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/scl_slope.m
@@ -0,0 +1,40 @@
+function varargout = scl_slope(varargin)
+% Format
+% For getting the value
+% dat = scl_slope(obj)
+%
+% For setting the value
+% obj = scl_slope(obj,dat)
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: scl_slope.m 1143 2008-02-07 19:33:33Z spm 
+
+% 
+% niftilib $Id: scl_slope.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+
+if nargin==2,
+    varargout{1} = asgn(varargin{:});
+elseif nargin==1,
+    varargout{1} = ref(varargin{:});
+else
+    error('Wrong number of arguments.');
+end;
+return;
+
+function dat = ref(obj)
+dat = obj.scl_slope;
+return;
+
+function obj = asgn(obj,dat)
+if isnumeric(dat), % && numel(dat)<=1,
+    obj.scl_slope = double(dat);
+else
+    error('"scl_slope" must be numeric.');
+end;
+return;
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/src/README b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/src/README
new file mode 100644
index 0000000000000000000000000000000000000000..6e5df6286e3de280dfcfe288fb001a092c4da792
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/src/README
@@ -0,0 +1,12 @@
+To compile on a big-endian machine
+	mex -O -DBIGENDIAN file2mat.c
+	mex -O -DBIGENDIAN mat2file.c
+
+On a little-endian machine
+	mex -O file2mat.c
+	mex -O mat2file.c
+
+On a Windows machine
+	mex -O -DSPM_WIN32 file2mat.c
+	mex -O -DSPM_WIN32 mat2file.c
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/src/file2mat.c b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/src/file2mat.c
new file mode 100644
index 0000000000000000000000000000000000000000..6e96cf20a170f3c42b97b2ccb5ab1f038b14cb52
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/src/file2mat.c
@@ -0,0 +1,644 @@
+/*
+ * Id: file2mat.c 4136 2010-12-09 22:22:28Z guillaume 
+ * John Ashburner
+ */
+
+/* 
+ * niftilib $Id: file2mat.c,v 1.3 2012/03/22 18:36:33 fissell Exp $ 
+ */
+
+/*
+Memory mapping is used by this module. For more information on this, see:
+http://www.mathworks.com/company/newsletters/digest/mar04/memory_map.html
+*/
+
+#define _FILE_OFFSET_BITS 64
+
+#include <math.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdio.h>
+#include "mex.h"
+
+#ifdef SPM_WIN32
+#include <windows.h>
+#include <memory.h>
+#include <io.h>
+HANDLE hFile, hMapping;
+typedef char *caddr_t;
+#if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS == 64
+#define stat _stati64
+#define fstat _fstati64
+#define open _open
+#define close _close
+#if defined _MSC_VER
+#define size_t __int64
+#else
+#define size_t unsigned long long
+#endif
+#endif
+#else
+#include <sys/mman.h>
+#include <unistd.h>
+#include <errno.h>
+#define size_t unsigned long long
+#endif
+
+/*
+http://en.wikipedia.org/wiki/Page_(computing)#Determining_the_page_size_in_a_program
+http://msdn.microsoft.com/en-us/library/aa366763(VS.85).aspx
+*/
+int page_size()
+{
+int size = 0;
+
+#if defined (_WIN32) || defined (_WIN64)
+    SYSTEM_INFO info;
+    GetSystemInfo (&info);
+    size = (int)info.dwAllocationGranularity;
+#else
+    size = sysconf(_SC_PAGESIZE);
+#endif 
+
+return size;
+}
+
+
+#define MXDIMS 256
+
+static long long icumprod[MXDIMS], ocumprod[MXDIMS];
+
+static void get_1_sat(int ndim, int idim[], int *iptr[], unsigned char idat[], int odim[], unsigned char odat[], int indi, int indo)
+{
+    int i;
+    if (ndim == 0)
+    {
+        for(i=0; i<odim[0]; i++)
+        {
+            int tmp      = indi+iptr[0][i]-1;
+            odat[indo++] = (idat[tmp>>3]>>(tmp&7))&1;
+        }
+    }
+    else
+    {
+        for(i=0; i<odim[ndim]; i++)
+            get_1_sat(ndim-1, idim, iptr, idat, odim, odat,
+                indi+icumprod[ndim]*(iptr[ndim][i]-1), indo+ocumprod[ndim]*i);
+    }
+}
+
+void get_1(int ndim, int idim[], int *iptr[], unsigned char idat[], int odim[], unsigned char odat[])
+{
+    get_1_sat(ndim, idim, iptr, idat, odim, odat, 0, 0);
+}
+
+void get_8(int ndim, int idim[], int *iptr[], unsigned char idat[], int odim[], unsigned char odat[])
+{
+    int i;
+    if (!ndim)
+    {
+        for(i=0; i<odim[0]; i++)
+            odat[i] = idat[iptr[0][i]-1];
+    }
+    else
+    {
+        for(i=0; i<odim[ndim]; i++)
+            get_8(ndim-1, idim, iptr, idat+icumprod[ndim]*(iptr[ndim][i]-1),
+                odim, odat+ocumprod[ndim]*i);
+    }
+}
+
+void get_16(int ndim, int idim[], int *iptr[], unsigned short idat[], int odim[], unsigned short odat[])
+{
+    int i;
+    if (!ndim)
+    {
+        for(i=0; i<odim[0]; i++)
+            odat[i] = idat[iptr[0][i]-1];
+    }
+    else
+    {
+        for(i=0; i<odim[ndim]; i++)
+            get_16(ndim-1, idim, iptr, idat+icumprod[ndim]*(iptr[ndim][i]-1),
+                odim, odat+ocumprod[ndim]*i);
+    }
+}
+
+void get_32(int ndim, int idim[], int *iptr[], unsigned int idat[], int odim[], unsigned int odat[])
+{
+    int i;
+    if (!ndim)
+    {
+        for(i=0; i<odim[0]; i++)
+            odat[i] = idat[iptr[0][i]-1];
+    }
+    else
+    {
+        for(i=0; i<odim[ndim]; i++)
+            get_32(ndim-1, idim, iptr, idat+icumprod[ndim]*(iptr[ndim][i]-1),
+                odim, odat+ocumprod[ndim]*i);
+    }
+}
+
+void get_64(int ndim, int idim[], int *iptr[], unsigned long long idat[], int odim[], unsigned long long odat[])
+{
+    int i;
+    if (ndim == 0)
+    {
+        for(i=0; i<odim[0]; i++)
+            odat[i] = idat[iptr[0][i]-1];
+    }
+    else
+    {
+        for(i=0; i<odim[ndim]; i++)
+            get_64(ndim-1, idim, iptr, idat+icumprod[ndim]*(iptr[ndim][i]-1),
+                odim, odat+ocumprod[ndim]*i);
+    }
+}
+
+void get_w8(int ndim, int idim[], int *iptr[], unsigned char idat[],
+             int odim[], unsigned char odat_r[], unsigned char odat_i[])
+{
+    int i;
+    if (ndim == 0)
+    {
+        int off;
+        for(i=0; i<odim[0]; i++)
+        {
+            off       = 2*(iptr[0][i]-1);
+            odat_r[i] = idat[off  ];
+            odat_i[i] = idat[off+1];
+        }
+    }
+    else
+    {
+        for(i=0; i<odim[ndim]; i++)
+            get_w8(ndim-1, idim, iptr, idat+icumprod[ndim]*(iptr[ndim][i]-1),
+                odim, odat_r+ocumprod[ndim]*i,odat_i+ocumprod[ndim]*i);
+    }
+}
+
+void get_w16(int ndim, int idim[], int *iptr[], unsigned short idat[],
+             int odim[], unsigned short odat_r[], unsigned short odat_i[])
+{
+    int i;
+    if (ndim == 0)
+    {
+        int off;
+        for(i=0; i<odim[0]; i++)
+        {
+            off       = 2*(iptr[0][i]-1);
+            odat_r[i] = idat[off  ];
+            odat_i[i] = idat[off+1];
+        }
+    }
+    else
+    {
+        for(i=0; i<odim[ndim]; i++)
+            get_w16(ndim-1, idim, iptr, idat+icumprod[ndim]*(iptr[ndim][i]-1),
+                odim, odat_r+ocumprod[ndim]*i,odat_i+ocumprod[ndim]*i);
+    }
+}
+
+void get_w32(int ndim, int idim[], int *iptr[], unsigned int idat[],
+             int odim[], unsigned int odat_r[], unsigned int odat_i[])
+{
+    int i;
+    if (ndim == 0)
+    {
+        int off;
+        for(i=0; i<odim[0]; i++)
+        {
+            off       = 2*(iptr[0][i]-1);
+            odat_r[i] = idat[off  ];
+            odat_i[i] = idat[off+1];
+        }
+    }
+    else
+    {
+        for(i=0; i<odim[ndim]; i++)
+            get_w32(ndim-1, idim, iptr, idat+icumprod[ndim]*(iptr[ndim][i]-1),
+                odim, odat_r+ocumprod[ndim]*i,odat_i+ocumprod[ndim]*i);
+    }
+}
+
+void get_w64(int ndim, int idim[], int *iptr[], unsigned long long idat[],
+             int odim[], unsigned long long odat_r[], unsigned long long odat_i[])
+{
+    int i;
+    if (ndim == 0)
+    {
+        int off;
+        for(i=0; i<odim[0]; i++)
+        {
+            off       = 2*(iptr[0][i]-1);
+            odat_r[i] = idat[off  ];
+            odat_i[i] = idat[off+1];
+        }
+    }
+    else
+    {
+        for(i=0; i<odim[ndim]; i++)
+            get_w64(ndim-1, idim, iptr, idat+icumprod[ndim]*(iptr[ndim][i]-1),
+                odim, odat_r+ocumprod[ndim]*i, odat_i+ocumprod[ndim]*i);
+    }
+}
+
+void swap8(long long n, unsigned char d[])
+{ /* DO NOTHING */}
+
+void swap16(long long n, unsigned char d[])
+{
+    unsigned char tmp, *de;
+    for(de=d+2*n; d<de; d+=2)
+    {
+        tmp = d[0]; d[0] = d[1]; d[1] = tmp;
+    }
+}
+
+void swap32(long long n, unsigned char d[])
+{
+    unsigned char tmp, *de;
+    for(de=d+4*n; d<de; d+=4)
+    {
+        tmp = d[0]; d[0] = d[3]; d[3] = tmp;
+        tmp = d[1]; d[1] = d[2]; d[2] = tmp;
+    }
+}
+
+void swap64(long long n, unsigned char d[])
+{
+    unsigned char tmp, *de;
+    for(de=d+8*n; d<de; d+=8)
+    {
+        tmp = d[0]; d[0] = d[7]; d[7] = tmp;
+        tmp = d[1]; d[1] = d[6]; d[6] = tmp;
+        tmp = d[2]; d[2] = d[5]; d[5] = tmp;
+        tmp = d[3]; d[3] = d[4]; d[4] = tmp;
+    }
+}
+
+typedef struct dtype {
+    int code;
+    void (*func)();
+    void (*swap)();
+    int clss;
+    int bytes;
+    int channels;
+} Dtype;
+
+Dtype table[] = {
+{   1,get_1  , swap8 , mxLOGICAL_CLASS, 1,1},
+{   2,get_8  , swap8 , mxUINT8_CLASS  , 8,1},
+{   4,get_16 , swap16, mxINT16_CLASS  ,16,1},
+{   8,get_32 , swap32, mxINT32_CLASS  ,32,1},
+{  16,get_32 , swap32, mxSINGLE_CLASS ,32,1},
+{  32,get_w32, swap32, mxSINGLE_CLASS ,32,2},
+{  64,get_64 , swap64, mxDOUBLE_CLASS ,64,1},
+{ 256,get_8  , swap8 , mxINT8_CLASS   , 8,1},
+{ 512,get_16 , swap16, mxUINT16_CLASS ,16,1},
+{ 768,get_32 , swap32, mxUINT32_CLASS ,32,1},
+{1792,get_w64, swap64, mxDOUBLE_CLASS ,64,2}
+};
+
+typedef struct mtype {
+    int     ndim;
+    int     dim[MXDIMS];
+    Dtype  *dtype;
+    int     swap;
+    caddr_t addr;
+    size_t  len;
+#ifdef SPM_WIN32
+    ULONGLONG off;
+#else
+    off_t   off;
+#endif
+    void   *data;
+} MTYPE;
+
+#ifdef SPM_WIN32
+void werror(char *where, DWORD last_error)
+{
+    char buf[512];
+    char s[1024];
+    int i;
+    i = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,
+                       NULL,
+                       last_error,
+                       0,
+                       buf,
+                       512/sizeof(TCHAR),
+                       NULL );
+    buf[i-2] =  '\0'; /* remove \r\n */
+    (void)sprintf(s,"%s: %s", where, buf);
+    mexErrMsgTxt(s);
+    return;
+}
+#else
+void werror(char *where, int last_error)
+{
+    char s[1024];
+    
+    (void)sprintf(s,"%s: %s", where, strerror(last_error));
+    mexErrMsgTxt(s);
+    return;
+}
+#endif
+
+void do_unmap_file(MTYPE *map)
+{
+    int sts;
+    if (map->addr)
+    {
+#ifdef SPM_WIN32
+        sts = UnmapViewOfFile((LPVOID)(map->addr));
+        if (sts == 0)
+            werror("Memory Map (UnmapViewOfFile)",GetLastError());
+#else
+        sts = munmap(map->addr, map->len);
+        if (sts == -1)
+            werror("Memory Map (munmap)",errno);
+#endif
+        map->addr = NULL;
+    }
+}
+
+const double *getpr(const mxArray *ptr, const char nam[], int len, int *n)
+{
+    char s[128];
+    mxArray *arr;
+
+    arr = mxGetField(ptr,0,nam);
+    if (arr == (mxArray *)0)
+    {
+        (void)sprintf(s,"'%s' field is missing.", nam);
+        mexErrMsgTxt(s);
+    }
+    if (!mxIsNumeric(arr) && !mxIsLogical(arr))
+    {
+        (void)sprintf(s,"'%s' field is non-numeric.", nam);
+        mexErrMsgTxt(s);
+    }
+    if (!mxIsDouble(arr))
+    {
+        (void)sprintf(s,"'%s' field is not double precision.", nam);
+        mexErrMsgTxt(s);
+    }
+    if (len>=0)
+    {
+        *n = mxGetM(arr)*mxGetN(arr);
+        if (*n != len)
+        {
+            (void)sprintf(s,"'%s' field should have %d elements (has %d).", nam, len, *n);
+            mexErrMsgTxt(s);
+        }
+    }
+    else
+    {
+        *n = mxGetM(arr)*mxGetN(arr);
+        if (*n > -len)
+        {
+            (void)sprintf(s,"'%s' field should have a maximum of %d elements (has %d).", nam, -len, *n);
+            mexErrMsgTxt(s);
+        }
+    }
+    return (double *)mxGetData(arr);
+}
+
+void do_map_file(const mxArray *ptr, MTYPE *map)
+{
+    int n;
+    int i, dtype;
+#ifdef SPM_WIN32
+    ULONGLONG offset = 0;
+#else
+    off_t offset = 0;
+#endif
+    const double *pr;
+    mxArray *arr;
+    size_t siz;
+    if (!mxIsStruct(ptr)) mexErrMsgTxt("Not a structure.");
+
+    dtype = (int)(getpr(ptr, "dtype", 1, &n)[0]);
+    for(i=0; i<sizeof(table)/sizeof(Dtype); i++)
+    {
+        if (table[i].code == dtype)
+        {
+            map->dtype = &table[i];
+            break;
+        }
+    }
+    if (map->dtype == NULL) mexErrMsgTxt("Unrecognised 'dtype' value.");
+    pr        = getpr(ptr, "dim", -MXDIMS, &n);
+    map->ndim = n;
+    siz       = 1;
+    for(i=0; i<map->ndim; i++)
+    {
+        map->dim[i] = (int)fabs(pr[i]);
+        siz  = siz*map->dim[i];
+    }
+
+    /* Avoid overflow if possible */
+    if (map->dtype->bytes % 8)
+        siz = (map->dtype->bytes*siz+7)/8;
+    else
+        siz = siz*(map->dtype->bytes/8);
+    
+    /* On 32bit platforms, cannot map more than 2^31-1 bytes */
+    if ((sizeof(map->data) == 4) && (siz > 2147483647ULL))
+         mexErrMsgTxt("The total number of bytes mapped is too large.");
+
+    pr       = getpr(ptr, "be",1, &n);
+#ifdef SPM_BIGENDIAN
+    map->swap = (int)pr[0]==0;
+#else
+    map->swap = (int)pr[0]!=0;
+#endif
+    pr       = getpr(ptr, "offset",1, &n);
+#ifdef SPM_WIN32
+    map->off = (ULONGLONG)pr[0];
+#else
+    map->off = (off_t)pr[0];
+#endif
+    if (map->off < 0) map->off = 0;
+
+    arr = mxGetField(ptr,0,"fname");
+    if (arr == (mxArray *)0) mexErrMsgTxt("Cant find fname.");
+    if (mxIsChar(arr))
+    {
+        int buflen;
+        char *buf;
+        int fd;
+        struct stat stbuf;
+        buflen = mxGetN(arr)*mxGetM(arr)+1;
+        buf    = mxCalloc(buflen,sizeof(char));
+        if (mxGetString(arr,buf,buflen))
+        {
+            mxFree(buf);
+            mexErrMsgTxt("Cant get filename.");
+        }
+        if ((fd = open(buf, O_RDONLY)) == -1)
+        {
+            mxFree(buf);
+            mexErrMsgTxt("Cant open file.");
+        }
+        if (fstat(fd, &stbuf) == -1)
+        {
+            (void)close(fd);
+            mxFree(buf);
+            mexErrMsgTxt("Cant get file size.");
+        }
+        if (stbuf.st_size < siz + map->off)
+        {
+            (void)close(fd);
+            mxFree(buf);
+            mexErrMsgTxt("File is smaller than the dimensions say it should be.");
+        }
+        offset = map->off % page_size();
+        map->len = siz + (size_t)offset;
+        map->off = map->off - offset;
+#ifdef SPM_WIN32
+        (void)close(fd);
+
+        /* http://msdn.microsoft.com/library/default.asp?
+               url=/library/en-us/fileio/base/createfile.asp */
+        hFile = CreateFile(
+            buf,
+            GENERIC_READ,
+            FILE_SHARE_READ,
+            NULL,
+            OPEN_EXISTING,
+            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
+            NULL);
+        mxFree(buf);
+        if (hFile == NULL)
+            werror("Memory Map (CreateFile)",GetLastError());
+
+        /* http://msdn.microsoft.com/library/default.asp?
+               url=/library/en-us/fileio/base/createfilemapping.asp */
+        hMapping = CreateFileMapping(
+            hFile,
+            NULL,
+            PAGE_READONLY,
+            0,
+            0,
+            NULL);
+        (void)CloseHandle(hFile);
+        if (hMapping == NULL)
+            werror("Memory Map (CreateFileMapping)",GetLastError());
+
+        /* http://msdn.microsoft.com/library/default.asp?
+               url=/library/en-us/fileio/base/mapviewoffile.asp */
+        map->addr    = (caddr_t)MapViewOfFile(
+            hMapping,
+            FILE_MAP_READ,
+            (DWORD)(map->off >> 32),
+            (DWORD)(map->off),
+            map->len);
+        (void)CloseHandle(hMapping);
+        if (map->addr == NULL)
+            werror("Memory Map (MapViewOfFile)",GetLastError());
+#else
+        map->addr = mmap(
+            (caddr_t)0,
+            map->len,
+            PROT_READ,
+            MAP_SHARED,
+            fd,
+            map->off);
+        (void)close(fd);
+        mxFree(buf);
+        if (map->addr == (void *)-1)
+            werror("Memory Map (mmap)",errno);
+#endif
+    }
+    map->data = (void *)((caddr_t)map->addr + offset);
+}
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+    MTYPE map;
+    void *idat;
+    int i;
+    int *iptr[MXDIMS], odim[MXDIMS], *idim, ndim;
+    int one[1];
+    one[0] = 1;
+
+    if (nrhs<2 || nlhs>1) mexErrMsgTxt("Incorrect usage.");
+
+    do_map_file(prhs[0], &map);
+
+    ndim = map.ndim;
+    idim = map.dim;
+    idat = map.data;
+
+    if (ndim >= MXDIMS) mexErrMsgTxt("Too many dimensions.");
+
+    /* if (nrhs > ndim+1) mexErrMsgTxt("Index exceeds matrix dimensions (1)."); */
+
+    for(i=0;i<nrhs-1; i++)
+    {
+        int j;
+        if (!mxIsNumeric(prhs[i+1]) || !mxIsInt32(prhs[i+1]) || mxIsComplex(prhs[i+1]))
+        {
+            do_unmap_file(&map);
+            mexErrMsgTxt("Indices must be int32.");
+        }
+        odim[i] = mxGetM(prhs[i+1])*mxGetN(prhs[i+1]);
+        iptr[i] = (int *)mxGetData(prhs[i+1]);
+        for(j=0; j<odim[i]; j++)
+            if (iptr[i][j]<1 || iptr[i][j]>((i<ndim)?idim[i]:1))
+            {
+                do_unmap_file(&map);
+                mexErrMsgTxt("Index exceeds matrix dimensions (1).");
+            }
+    }
+
+    for(i=nrhs-1; i<ndim; i++)
+    {
+        odim[i] = 1;
+        iptr[i] = one;
+    }
+    if (ndim<nrhs-1)
+    {
+        for(i=ndim; i<nrhs-1; i++)
+            idim[i] = 1;
+        ndim = nrhs-1;
+    }
+
+    icumprod[0] = map.dtype->channels;
+    ocumprod[0] = 1;
+    for(i=0; i<ndim; i++)
+    {
+        icumprod[i+1] = icumprod[i]*(long long)idim[i];
+        ocumprod[i+1] = ocumprod[i]*(long long)odim[i];
+
+        /* Fix for each plane of 1 bit Analyze images being
+           padded out to a whole number of bytes */
+        if (map.dtype->bytes==1 && i==1)
+            icumprod[i+1] = ((icumprod[i+1]+7)/8)*8;
+    }
+
+    if (map.dtype->channels == 1)
+    {
+        plhs[0] = mxCreateNumericArray(ndim,odim,map.dtype->clss,mxREAL);
+        map.dtype->func(ndim-1, idim, iptr, idat, odim, mxGetData(plhs[0]));
+        if (map.swap)
+            map.dtype->swap(ocumprod[ndim],mxGetData(plhs[0]));
+    }
+    else if (map.dtype->channels == 2)
+    {
+        plhs[0] = mxCreateNumericArray(ndim,odim,map.dtype->clss,mxCOMPLEX);
+        (map.dtype->func)(ndim-1, idim, iptr, idat, odim, mxGetData(plhs[0]),mxGetImagData(plhs[0]));
+        if (map.swap)
+        {
+            map.dtype->swap(ocumprod[ndim],mxGetData(plhs[0]));
+            map.dtype->swap(ocumprod[ndim],mxGetImagData(plhs[0]));
+        }
+    }
+
+    do_unmap_file(&map);
+}
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/src/mat2file.c b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/src/mat2file.c
new file mode 100644
index 0000000000000000000000000000000000000000..09ae79548205251d48fda31d232da228702f2f3d
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/src/mat2file.c
@@ -0,0 +1,385 @@
+/*
+ * Id: mat2file.c 2896 2009-03-18 20:43:48Z guillaume 
+ * John Ashburner
+ */
+
+/* 
+ * niftilib $Id: mat2file.c,v 1.3 2012/03/22 18:36:33 fissell Exp $ 
+ */
+
+
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE64_SOURCE
+#define _FILE_OFFSET_BITS 64
+
+#include <math.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "mex.h"
+#ifdef SPM_WIN32
+#include <windows.h>
+#include <memory.h>
+#include <io.h>
+#if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS == 64
+#if defined _MSC_VER
+#define off_t __int64
+#define fseeko _fseeki64
+#else
+#define off_t off64_t
+#define fseeko fseeko64
+#endif
+#endif
+#endif
+
+#define MXDIMS 256
+
+typedef struct dtype {
+    int code;
+    void (*swap)();
+    mxClassID clss;
+    int bits;
+    int channels;
+} Dtype;
+
+#define copy swap8
+
+void swap8(int n, unsigned char id[], unsigned char od[])
+{
+    unsigned char *de;
+    for(de=id+n; id<de; id++, od++)
+    {
+        *od = *id;
+    }
+}
+
+void swap16(int n, unsigned char id[], unsigned char od[])
+{
+    unsigned char tmp, *de;
+    for(de=id+n; id<de; id+=2, od+=2)
+    {
+        tmp = id[0]; od[0] = id[1]; od[1] = tmp;
+    }
+}
+
+void swap32(int n, unsigned char id[], unsigned char od[])
+{
+    unsigned char tmp, *de;
+    for(de=id+n; id<de; id+=4, od+=4)
+    {
+        tmp = id[0]; od[0] = id[3]; od[3] = tmp;
+        tmp = id[1]; od[1] = id[2]; od[2] = tmp;
+    }
+}
+
+void swap64(int n, unsigned char id[], unsigned char od[])
+{
+    unsigned char tmp, *de;
+    for(de=id+n; id<de; id+=8, od+=8)
+    {
+        tmp = id[0]; od[0] = id[7]; od[7] = tmp;
+        tmp = id[1]; od[1] = id[6]; od[6] = tmp;
+        tmp = id[2]; od[2] = id[5]; od[5] = tmp;
+        tmp = id[3]; od[3] = id[4]; od[4] = tmp;
+    }
+}
+
+
+Dtype table[] = {
+{   1, swap8 , mxLOGICAL_CLASS, 1,1},
+{   2, swap8 , mxUINT8_CLASS  , 8,1},
+{   4, swap16, mxINT16_CLASS  ,16,1},
+{   8, swap32, mxINT32_CLASS  ,32,1},
+{  16, swap32, mxSINGLE_CLASS ,32,1},
+{  32, swap32, mxSINGLE_CLASS ,32,2},
+{  64, swap64, mxDOUBLE_CLASS ,64,1},
+{ 256, swap8 , mxINT8_CLASS   , 8,1},
+{ 512, swap16, mxUINT16_CLASS ,16,1},
+{ 768, swap32, mxUINT32_CLASS ,32,1},
+{1792, swap64, mxDOUBLE_CLASS ,64,2}
+};
+
+typedef struct ftype {
+    int     ndim;
+    int     dim[MXDIMS];
+    Dtype  *dtype;
+    int     swap;
+    FILE   *fp;
+    off_t   off;
+} FTYPE;
+
+off_t icumprod[MXDIMS], ocumprod[MXDIMS];
+off_t poff;
+long len;
+#define BLEN 131072
+unsigned char wbuf[BLEN], *dptr;
+
+void put_bytes(int ndim, FILE *fp, int *ptr[], int idim[], unsigned char idat[], off_t indo, off_t indi, void (*swap)())
+{
+    int i;
+    off_t nb = ocumprod[ndim];
+
+    if (ndim == 0)
+    {
+        off_t off;
+        for(i=0; i<idim[ndim]; i++)
+        {
+            off = indo+(ptr[ndim][i]-1)*nb;
+            if (((off-poff)!=nb) || (len == BLEN))
+            {
+                swap(len,dptr,wbuf);
+                if (len && (fwrite(wbuf,1,len,fp) != len))
+                {
+                    /* Problem */
+                    (void)fclose(fp);
+                    (void)mexErrMsgTxt("Problem writing data (1).");
+                }
+                if (fseeko(fp, off, SEEK_SET) == -1)
+                {
+                    /* Problem */
+                    (void)fclose(fp);
+                    (void)mexErrMsgTxt("Problem writing data (2).");
+                }
+                dptr   = idat+indi+i*nb;
+                len    = 0;
+            }
+            len += nb;
+            poff = off;
+        }
+    }
+    else
+    {
+        for(i=0; i<idim[ndim]; i++)
+        {
+            put_bytes(ndim-1, fp, ptr, idim,
+                idat, indo+nb*(ptr[ndim][i]-1), indi+icumprod[ndim]*i, swap);
+        }
+    }
+}
+
+void put(FTYPE map, int *ptr[], int idim[], void *idat)
+{
+    int i, nbytes;
+    void (*swap)();
+
+    dptr   = idat;
+    nbytes = map.dtype->bits/8;
+    len    = 0;
+    poff   = -999999;
+    ocumprod[0] = nbytes*map.dtype->channels;
+    icumprod[0] = nbytes*1;
+    for(i=0; i<map.ndim; i++)
+    {
+        icumprod[i+1] = icumprod[i]*idim[i];
+        ocumprod[i+1] = ocumprod[i]*map.dim[i];
+    }
+
+    if (map.swap)
+        swap = map.dtype->swap;
+    else
+        swap = copy;
+
+    put_bytes(map.ndim-1, map.fp, ptr, idim, (unsigned char *)idat, map.off, 0,swap);
+
+    swap(len,dptr,wbuf);
+    if (fwrite(wbuf,1,len,map.fp) != len)
+    {
+        /* Problem */
+       (void)fclose(map.fp);
+       (void)mexErrMsgTxt("Problem writing data (3).");
+    }
+}
+
+const double *getpr(const mxArray *ptr, const char nam[], int len, int *n)
+{
+    char s[256];
+    mxArray *arr;
+
+    arr = mxGetField(ptr,0,nam);
+    if (arr == (mxArray *)0)
+    {
+        (void)sprintf(s,"'%s' field is missing.", nam);
+        mexErrMsgTxt(s);
+    }
+    if (!mxIsNumeric(arr))
+    {
+        (void)sprintf(s,"'%s' field is non-numeric.", nam);
+        mexErrMsgTxt(s);
+    }
+    if (!mxIsDouble(arr))
+    {
+        (void)sprintf(s,"'%s' field is not double precision.", nam);
+        mexErrMsgTxt(s);
+    }
+    if (len>=0)
+    {
+        *n = mxGetM(arr)*mxGetN(arr);
+        if (*n != len)
+        {
+            (void)sprintf(s,"'%s' field should have %d elements (has %d).", nam, len, *n);
+            mexErrMsgTxt(s);
+        }
+    }
+    else
+    {
+        *n = mxGetNumberOfElements(arr);
+        if (*n > -len)
+        {
+            (void)sprintf(s,"'%s' field should have a maximum of %d elements (has %d).", nam, -len, *n);
+            mexErrMsgTxt(s);
+        }
+    }
+    return (double *)mxGetData(arr);
+}
+
+
+void open_file(const mxArray *ptr, FTYPE *map)
+{
+    int n;
+    int i, dtype;
+    const double *pr;
+    mxArray *arr;
+
+    if (!mxIsStruct(ptr)) mexErrMsgTxt("Not a structure.");
+
+    dtype = (int)(getpr(ptr, "dtype", 1, &n)[0]);
+    map->dtype = NULL;
+    for(i=0; i<sizeof(table)/sizeof(Dtype); i++)
+    {
+        if (table[i].code == dtype)
+        {
+            map->dtype = &table[i];
+            break;
+        }
+    }
+    if (map->dtype == NULL)        mexErrMsgTxt("Unrecognised 'dtype' value.");
+    if (map->dtype->bits % 8)      mexErrMsgTxt("Can not yet write logical data.");
+    if (map->dtype->channels != 1) mexErrMsgTxt("Can not yet write complex data.");
+    pr        = getpr(ptr, "dim", -MXDIMS, &n);
+    map->ndim = n;
+    for(i=0; i<map->ndim; i++)
+    {
+        map->dim[i] = (int)fabs(pr[i]);
+    }
+    pr       = getpr(ptr, "be",1, &n);
+#ifdef SPM_BIGENDIAN
+    map->swap = (int)pr[0]==0;
+#else
+    map->swap = (int)pr[0]!=0;
+#endif
+    pr       = getpr(ptr, "offset",1, &n);
+    map->off = (off_t)pr[0];
+ /* if (map->off < 0) map->off = 0; Unsigned, so not necessary */
+
+    arr = mxGetField(ptr,0,"fname");
+    if (arr == (mxArray *)0) mexErrMsgTxt("Cant find 'fname' field.");
+
+    if (mxIsChar(arr))
+    {
+        int buflen;
+        char *buf;
+        buflen = mxGetNumberOfElements(arr)+1;
+        buf    = mxCalloc(buflen+1,sizeof(char));
+        if (mxGetString(arr,buf,buflen))
+        {
+            mxFree(buf);
+            mexErrMsgTxt("Cant get 'fname'.");
+        }
+        map->fp = fopen(buf,"rb+");
+        if (map->fp == (FILE *)0)
+        {
+            map->fp = fopen(buf,"wb");
+            if (map->fp == (FILE *)0)
+            {
+                mxFree(buf);
+                mexErrMsgTxt("Cant open file.");
+            }
+        }
+
+        mxFree(buf);
+    }
+    else
+        mexErrMsgTxt("Wrong type of 'fname' field.");
+}
+
+
+void close_file(FTYPE map)
+{
+    (void)fclose(map.fp);
+}
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+    FTYPE map;
+    void *idat;
+    int i;
+    int *ptr[MXDIMS], *odim, ndim, idim[MXDIMS];
+    int one[1];
+    const mxArray *curr;
+    one[0] = 1;
+
+    if (nrhs<3 || nlhs>0) mexErrMsgTxt("Incorrect usage.");
+
+    curr = prhs[0];
+    open_file(curr, &map);
+
+    ndim = map.ndim;
+    odim = map.dim;
+
+    if (ndim >= MXDIMS)
+    {
+        close_file(map);
+        mexErrMsgTxt("Too many dimensions.");
+    }
+    curr  = prhs[1];
+    if (mxGetClassID(curr) != map.dtype->clss)
+    {
+        close_file(map);
+        mexErrMsgTxt("Incompatible class types.");
+    }
+    idat  = mxGetData(curr);
+
+    for(i=0;i<nrhs-2; i++)
+    {
+        int j;
+        curr = prhs[i+2];
+        if (!mxIsInt32(curr))
+        {
+            close_file(map);
+            mexErrMsgTxt("Indices must be int32.");
+        }
+        if (i< mxGetNumberOfDimensions(prhs[1]))
+            idim[i] = mxGetDimensions(prhs[1])[i];
+        else
+            idim[i] = 1;
+            
+        if (mxGetNumberOfElements(curr) != idim[i])
+        {
+            close_file(map);
+            mexErrMsgTxt("Subscripted assignment dimension mismatch (2).");
+        }
+
+        ptr[i] = (int *)mxGetData(curr);
+        for(j=0; j<idim[i]; j++)
+            if (ptr[i][j]<1 || ptr[i][j]> ((i<ndim)?odim[i]:1))
+            {
+                close_file(map);
+                mexErrMsgTxt("Index exceeds matrix dimensions (2).");
+            }
+    }
+
+    for(i=nrhs-2; i<ndim; i++)
+    {
+        idim[i] = 1;
+        ptr[i]  = one;
+    }
+    if (ndim<nrhs-2)
+    {
+        for(i=ndim; i<nrhs-2; i++)
+            map.dim[i] = 1;
+        map.ndim = nrhs-2;
+    }
+    put(map, ptr, idim, idat);
+    close_file(map);
+}
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/reshape.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/reshape.m
new file mode 100644
index 0000000000000000000000000000000000000000..c2d7a561122802937feb5041c87f047a3a3deb51
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/reshape.m
@@ -0,0 +1,26 @@
+function a = reshape(b,varargin)
+% Overloaded reshape function for file_array objects
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: reshape.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: reshape.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+if length(struct(b))~=1, error('Can only reshape simple file_array objects.'); end;
+
+args = [];
+for i=1:length(varargin),
+    args = [args varargin{i}(:)'];
+end;
+if prod(args)~=prod(b.dim),
+    error('To RESHAPE the number of elements must not change.');
+end;
+a = b;
+a.dim = args;
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/size.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/size.m
new file mode 100644
index 0000000000000000000000000000000000000000..e1dfdebba6e033af1e10e1a35c095c7282f6492d
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/size.m
@@ -0,0 +1,49 @@
+function d = size(a,varargin)
+% overloaded size function for file_array objects.
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: size.m 3730 2010-02-17 13:24:26Z john 
+
+%
+% niftilib $Id: size.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+sa  = struct(a);
+nd  = 0;
+for i=1:numel(sa),
+    nd = max(nd,numel(sa(i).dim));
+    nd = max(nd,max(find(sa(i).pos==1)));
+end
+nd = nd+1;
+
+dim = ones(length(sa),nd);
+pos = ones(length(sa),nd);
+
+for i=1:length(sa)
+    sz = sa(i).dim;
+    dim(i,1:length(sz)) = sz;
+    ps = sa(i).pos;
+    pos(i,1:length(ps)) = ps;
+end
+
+tmp = pos==1;
+d   = zeros(1,nd);
+for i=1:nd,
+    ind  = all(tmp(:,[1:(i-1) (i+1):nd]),2);
+    d(i) = sum(dim(ind,i));
+end;
+lim = max(max(find(d~=1)),2);
+d   = d(1:lim);
+
+if nargin>1,
+    if varargin{1}<=length(d),
+        d = d(varargin{1});
+    else
+        d = 1;
+    end;
+end;
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/subsasgn.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/subsasgn.m
new file mode 100644
index 0000000000000000000000000000000000000000..a8eb1f369810a1c7d4ab7d7db7343e48acdbf141
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/subsasgn.m
@@ -0,0 +1,158 @@
+function obj = subsasgn(obj,subs,dat)
+% Overloaded subsasgn function for file_array objects.
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: subsasgn.m 4136 2010-12-09 22:22:28Z guillaume 
+
+%
+% niftilib $Id: subsasgn.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+if isempty(subs)
+    return;
+end;
+if ~strcmp(subs(1).type,'()'),
+    if strcmp(subs(1).type,'.'),
+        %error('Attempt to reference field of non-structure array.');
+        if numel(struct(obj))~=1,
+            error('Can only change the fields of simple file_array objects.');
+        end;
+        switch(subs(1).subs)
+        case 'fname',      obj = asgn(obj,@fname,     subs(2:end),dat); %fname(obj,dat);
+        case 'dtype',      obj = asgn(obj,@dtype,     subs(2:end),dat); %dtype(obj,dat);
+        case 'offset',     obj = asgn(obj,@offset,    subs(2:end),dat); %offset(obj,dat);
+        case 'dim',        obj = asgn(obj,@dim,       subs(2:end),dat); %obj = dim(obj,dat);
+        case 'scl_slope',  obj = asgn(obj,@scl_slope, subs(2:end),dat); %scl_slope(obj,dat);
+        case 'scl_inter',  obj = asgn(obj,@scl_inter, subs(2:end),dat); %scl_inter(obj,dat);
+        case 'permission', obj = asgn(obj,@permission,subs(2:end),dat); %permission(obj,dat);
+        otherwise, error(['Reference to non-existent field "' subs.subs '".']);
+        end;
+        return;
+    end;
+    if strcmp(subs(1).type,'{}'), error('Cell contents reference from a non-cell array object.'); end;
+end;
+
+if numel(subs)~=1, error('Expression too complicated');end;
+dm   = size(obj);
+sobj = struct(obj);
+
+if length(subs.subs) < length(dm),
+    l   = length(subs.subs);
+    dm  = [dm(1:(l-1)) prod(dm(l:end))];
+    if numel(sobj) ~= 1,
+        error('Can only reshape simple file_array objects.');
+    end;
+    if numel(sobj.scl_slope)>1 || numel(sobj.scl_inter)>1,
+        error('Can not reshape file_array objects with multiple slopes and intercepts.');
+    end;
+end;
+
+dm   = [dm ones(1,16)];
+di   = ones(1,16);
+args = {};
+for i=1:length(subs.subs),
+    if ischar(subs.subs{i}),
+        if ~strcmp(subs.subs{i},':'), error('This shouldn''t happen....'); end;
+        args{i} = int32(1:dm(i));
+    else
+        args{i} = int32(subs.subs{i});
+    end;
+    di(i) = length(args{i});
+end;
+for j=1:length(sobj),
+    if strcmp(sobj(j).permission,'ro'),
+        error('Array is read-only.');
+    end
+end
+
+if length(sobj)==1
+    sobj.dim = dm;
+    if numel(dat)~=1,
+        subfun(sobj,double(dat),args{:});
+    else
+        dat1 = double(dat) + zeros(di);
+        subfun(sobj,dat1,args{:});
+    end;
+else
+    for j=1:length(sobj),
+        ps  = [sobj(j).pos ones(1,length(args))];
+        dm  = [sobj(j).dim ones(1,length(args))];
+        siz = ones(1,16);
+        for i=1:length(args),
+            msk      = args{i}>=ps(i) & args{i}<(ps(i)+dm(i));
+            args2{i} = find(msk);
+            args3{i} = int32(double(args{i}(msk))-ps(i)+1);
+            siz(i)   = numel(args2{i});
+        end;
+        if numel(dat)~=1,
+            dat1 = double(subsref(dat,struct('type','()','subs',{args2})));
+        else
+            dat1 = double(dat) + zeros(siz);
+        end;
+        subfun(sobj(j),dat1,args3{:});
+    end
+end
+return
+
+function sobj = subfun(sobj,dat,varargin)
+va = varargin;
+
+dt  = datatypes;
+ind = find(cat(1,dt.code)==sobj.dtype);
+if isempty(ind), error('Unknown datatype'); end;
+if dt(ind).isint, dat(~isfinite(dat)) = 0; end;
+
+if ~isempty(sobj.scl_inter),
+    inter = sobj.scl_inter;
+    if numel(inter)>1,
+        inter = resize_scales(inter,sobj.dim,varargin);
+    end;
+    dat = double(dat) - inter;
+end;
+
+if ~isempty(sobj.scl_slope),
+    slope = sobj.scl_slope;
+    if numel(slope)>1,
+        slope = resize_scales(slope,sobj.dim,varargin);
+        dat   = double(dat)./slope;
+    else
+        dat   = double(dat)/slope;
+    end;
+end;
+
+if dt(ind).isint, dat = round(dat); end;
+
+% Avoid warning messages in R14 SP3
+wrn = warning;
+warning('off');
+dat   = feval(dt(ind).conv,dat);
+warning(wrn);
+
+nelem = dt(ind).nelem;
+if nelem==1,
+    mat2file(sobj,dat,va{:});
+elseif nelem==2,
+    sobj1       = sobj;
+    sobj1.dim   = [2 sobj.dim];
+    sobj1.dtype = dt(find(strcmp(dt(ind).prec,{dt.prec}) & (cat(2,dt.nelem)==1))).code;
+    dat         = reshape(dat,[1 size(dat)]);
+    dat         = [real(dat) ; imag(dat)];
+    mat2file(sobj1,dat,int32([1 2]),va{:});
+else
+    error('Inappropriate number of elements per voxel.');
+end;
+return
+
+function obj = asgn(obj,fun,subs,dat)
+if ~isempty(subs),
+    tmp = feval(fun,obj);
+    tmp = subsasgn(tmp,subs,dat);
+    obj = feval(fun,obj,tmp);
+else
+    obj = feval(fun,obj,dat);
+end;
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/subsref.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/subsref.m
new file mode 100644
index 0000000000000000000000000000000000000000..7e1df1356de3a6ff8813f042bd8bbb66776714b7
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/subsref.m
@@ -0,0 +1,186 @@
+function varargout=subsref(obj,subs)
+% SUBSREF Subscripted reference
+% An overloaded function...
+%__________________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: subsref.m 4136 2010-12-09 22:22:28Z guillaume 
+
+%
+% niftilib $Id: subsref.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+if isempty(subs), return; end
+
+switch subs(1).type
+    case '{}'
+        error('Cell contents reference from a non-cell array object.');
+    case '.'
+        varargout = access_fields(obj,subs);
+        return;
+end
+
+if numel(subs)~=1, error('Expression too complicated'); end;
+
+dim  = [size(obj) ones(1,16)];
+nd   = find(dim>1,1,'last')-1;
+sobj = struct(obj);
+
+if ~numel(subs.subs)
+    [subs.subs{1:nd+1}] = deal(':');
+elseif length(subs.subs) < nd
+    l   = length(subs.subs);
+    dim = [dim(1:(l-1)) prod(dim(l:end))];
+    if numel(sobj) ~= 1
+        error('Can only reshape simple file_array objects.');
+    else
+        if numel(sobj.scl_slope)>1 || numel(sobj.scl_inter)>1
+            error('Can not reshape file_array objects with multiple slopes and intercepts.');
+        end
+        sobj.dim = dim;
+    end
+end
+
+di   = ones(16,1);
+args = cell(1,length(subs.subs));
+for i=1:length(subs.subs)
+    if ischar(subs.subs{i})
+        if ~strcmp(subs.subs{i},':'), error('This shouldn''t happen....'); end
+        if length(subs.subs) == 1
+            args{i} = 1:prod(dim); % possible overflow when int32()
+            k = 0;
+            for j=1:length(sobj)
+                sobj(j).dim = [prod(sobj(j).dim) 1];
+                sobj(j).pos = [k+1 1];
+                k           = k + sobj(j).dim(1);
+            end
+        else
+            args{i} = 1:dim(i);
+        end
+    else
+        args{i} = subs.subs{i};
+    end
+    di(i) = length(args{i});
+end
+
+if length(sobj)==1
+    t = subfun(sobj,args{:});
+else
+    dt  = datatypes;
+    dt  = dt([dt.code]==sobj(1).dtype); % assuming identical datatypes
+    t = zeros(di',func2str(dt.conv));
+    for j=1:length(sobj)
+        ps = [sobj(j).pos ones(1,length(args))];
+        dm = [sobj(j).dim ones(1,length(args))];
+        for i=1:length(args)
+            msk      = find(args{i}>=ps(i) & args{i}<(ps(i)+dm(i)));
+            args2{i} = msk;
+            args3{i} = double(args{i}(msk))-ps(i)+1;
+        end
+
+        t  = subsasgn(t,struct('type','()','subs',{args2}),subfun(sobj(j),args3{:}));
+    end
+end
+varargout = {t};
+
+
+%==========================================================================
+% function t = subfun(sobj,varargin)
+%==========================================================================
+function t = subfun(sobj,varargin)
+
+%sobj.dim = [sobj.dim ones(1,16)];
+try
+    args = cell(size(varargin));
+    for i=1:length(varargin)
+        args{i} = int32(varargin{i});
+    end
+    t = file2mat(sobj,args{:});
+catch
+    t = multifile2mat(sobj,varargin{:});
+end
+if ~isempty(sobj.scl_slope) || ~isempty(sobj.scl_inter)
+    slope = 1;
+    inter = 0;
+    if ~isempty(sobj.scl_slope), slope = sobj.scl_slope; end
+    if ~isempty(sobj.scl_inter), inter = sobj.scl_inter; end
+    if numel(slope)>1
+        slope = resize_scales(slope,sobj.dim,varargin);
+        t     = double(t).*slope;
+    else
+        t     = double(t)*slope;
+    end
+    if numel(inter)>1
+        inter = resize_scales(inter,sobj.dim,varargin);
+    end;
+    t = t + inter;
+end
+
+
+%==========================================================================
+% function c = access_fields(obj,subs)
+%==========================================================================
+function c = access_fields(obj,subs)
+
+sobj = struct(obj);
+c    = cell(1,numel(sobj));
+for i=1:numel(sobj)
+    %obj = class(sobj(i),'file_array');
+    obj = sobj(i);
+    switch(subs(1).subs)
+        case 'fname',      t = fname(obj);
+        case 'dtype',      t = dtype(obj);
+        case 'offset',     t = offset(obj);
+        case 'dim',        t = dim(obj);
+        case 'scl_slope',  t = scl_slope(obj);
+        case 'scl_inter',  t = scl_inter(obj);
+        case 'permission', t = permission(obj);
+        otherwise
+            error(['Reference to non-existent field "' subs(1).subs '".']);
+    end
+    if numel(subs)>1
+        t = subsref(t,subs(2:end));
+    end
+    c{i} = t;
+end
+
+
+%==========================================================================
+% function val = multifile2mat(sobj,varargin)
+%==========================================================================
+function val = multifile2mat(sobj,varargin)
+
+% Convert subscripts into linear index
+[indx2{1:length(varargin)}] = ndgrid(varargin{:},1);
+ind = sub2ind(sobj.dim,indx2{:});
+
+% Work out the partition
+dt  = datatypes;
+dt  = dt([dt.code]==sobj.dtype);
+sz  = dt.size;
+try
+    mem = spm('Memory'); % in bytes, has to be a multiple of 16 (max([dt.size]))
+catch
+    mem = 200 * 1024 * 1024;
+end
+s   = ceil(prod(sobj.dim) * sz / mem);
+
+% Assign indices to partitions
+[x,y] = ind2sub([mem/sz s],ind(:));
+c     = histc(y,1:s);
+cc    = [0 reshape(cumsum(c),1,[])];
+
+% Read data in relevant partitions
+obj = sobj;
+val = zeros(length(x),1,func2str(dt.conv));
+for i=reshape(find(c),1,[])
+    obj.offset = sobj.offset + mem*(i-1);
+    obj.dim = [1 min(mem/sz, prod(sobj.dim)-(i-1)*mem/sz)];
+    val(cc(i)+1:cc(i+1)) = file2mat(obj,int32(1),int32(x(y==i)));
+end
+r   = cellfun('length',varargin);
+if numel(r) == 1, r = [r 1]; end
+val = reshape(val,r);
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/transpose.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/transpose.m
new file mode 100644
index 0000000000000000000000000000000000000000..6451efef058c1c9f4be493bdfd4bbdd25fcf38b3
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/transpose.m
@@ -0,0 +1,15 @@
+function varargout = transpose(varargin)
+% Transposing is not allowed.
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: transpose.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: transpose.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+error('file_array objects can not be transposed.');
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/vertcat.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/vertcat.m
new file mode 100644
index 0000000000000000000000000000000000000000..28b6ed1363315ba4fdb87eba16f9b8aad3512b47
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/vertcat.m
@@ -0,0 +1,16 @@
+function o = vertcat(varargin)
+% Vertical concatenation of file_array objects.
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: vertcat.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: vertcat.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+o = cat(1,varargin{:});
+return;
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/Contents.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/Contents.m
new file mode 100644
index 0000000000000000000000000000000000000000..b1a0903b302ec4f72d8720ba4bf2948ac8aa0e39
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/Contents.m
@@ -0,0 +1,84 @@
+% NIFTI Object
+%
+%   create     - Create a NIFTI-1 file
+%   disp       - Disp a NIFTI-1 object
+%   display    - Display a NIFTI-1 object
+%   fieldnames - Fieldnames of a NIFTI-1 object
+%   nifti      - Create a NIFTI-1 object
+%   subsasgn   - Subscript assignment
+%   subsref    - Subscript referencing
+%
+%   other operations are unlikely to work.
+%
+% Example usage.
+%
+% % Example of creating a simulated .nii file.
+% dat            = file_array;
+% dat.fname = 'junk.nii';
+% dat.dim     = [64 64 32];
+% dat.dtype  = 'FLOAT64-BE';
+% dat.offset  = ceil(348/8)*8;
+% 
+% % alternatively:
+% % dat = file_array( 'junk.nii',dim,dtype,off,scale,inter)
+% 
+% disp(dat)
+% 
+% % Create an empty NIFTI structure
+% N = nifti;
+% 
+% fieldnames(N) % Dump fieldnames
+% 
+% % Creating all the NIFTI header stuff
+% N.dat = dat;
+% N.mat = [2 0 0 -110 ; 0 2 0 -110; 0 0 -2 92; 0 0 0 1];
+% N.mat_intent = 'xxx'; % dump possibilities
+% N.mat_intent = 'Scanner';
+% N.mat0 = N.mat;
+% N.mat0_intent = 'Aligned';
+% 
+% N.diminfo.slice = 3;
+% N.diminfo.phase = 2;
+% N.diminfo.frequency = 2;
+% N.diminfo.slice_time.code='xxx'; % dump possibilities 
+% N.diminfo.slice_time.code = 'sequential_increasing';
+% N.diminfo.slice_time.start = 1;
+% N.diminfo.slice_time.end = 32;
+% N.diminfo.slice_time.duration = 3/32;
+% 
+% N.intent.code='xxx' ; % dump possibilities
+% N.intent.code='FTEST'; % or N.intent.code=4;
+% N.intent.param = [4 8];
+% 
+% N.timing.toffset = 28800;
+% N.timing.tspace=3;
+% N.descrip = 'This is a NIFTI-1 file';
+% N.aux_file='aux-file-name.txt';
+% N.cal = [0 1];
+% 
+% create(N); % Writes hdr info
+% 
+% dat(:,:,:)=0; % Write out the data as all zeros
+% 
+% [i,j,k] = ndgrid(1:64,1:64,1:32);
+% dat(find((i-32).^2+(j-32).^2+(k*2-32).^2 < 30^2))=1; % Write some ones in the file
+% dat(find((i-32).^2+(j-32).^2+(k*2-32).^2 < 15^2))=2;
+% 
+% 
+% % displaying a slice
+% imagesc(dat(:,:,12));colorbar
+% 
+% % get a handle to 'junk.nii';
+% M=nifti('junk.nii');
+% 
+% imagesc(M.dat(:,:,12));
+%
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: Contents.m 2696 2009-02-05 20:29:48Z guillaume 
+
+%
+% niftilib $Id: Contents.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/create.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/create.m
new file mode 100644
index 0000000000000000000000000000000000000000..1d9099ff861dea45eae36802f4486aab95c15d8f
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/create.m
@@ -0,0 +1,78 @@
+function create(obj,wrt)
+% Create a NIFTI-1 file
+% FORMAT create(obj)
+% This writes out the header information for the nifti object
+%
+% create(obj,wrt)
+% This also writes out an empty image volume if wrt==1
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: create.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: create.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+for i=1:numel(obj)
+    create_each(obj(i));
+end;
+
+function create_each(obj)
+if ~isa(obj.dat,'file_array'),
+    error('Data must be a file-array');
+end;
+fname = obj.dat.fname;
+if isempty(fname),
+    error('No filename to write to.');
+end;
+dt = obj.dat.dtype;
+ok = write_hdr_raw(fname,obj.hdr,dt(end-1)=='B');
+if ~ok,
+    error(['Unable to write header for "' fname '".']);
+end;
+
+write_extras(fname,obj.extras);
+
+if nargin>2 && any(wrt==1),
+    % Create an empty image file if necessary
+    d   = findindict(obj.hdr.datatype, 'dtype');
+    dim = double(obj.hdr.dim(2:end));
+    dim((double(obj.hdr.dim(1))+1):end) = 1;
+    nbytes = ceil(d.size*d.nelem*prod(dim(1:2)))*prod(dim(3:end))+double(obj.hdr.vox_offset);
+    [pth,nam,ext] = fileparts(obj.dat.fname);
+
+    if any(strcmp(deblank(obj.hdr.magic),{'n+1','nx1'})),
+        ext = '.nii';
+    else
+        ext = '.img';
+    end;
+    iname = fullfile(pth,[nam ext]);
+    fp    = fopen(iname,'a+');
+    if fp==-1,
+        error(['Unable to create image for "' fname '".']);
+    end;
+
+    fseek(fp,0,'eof');
+    pos = ftell(fp);
+    if pos<nbytes,
+        bs      = 2048; % Buffer-size
+        nbytes  = nbytes - pos;
+        buf     = uint8(0);
+        buf(bs) = 0;
+        while(nbytes>0)
+            if nbytes<bs, buf = buf(1:nbytes); end;
+            nw = fwrite(fp,buf,'uint8');
+            if nw<min(bs,nbytes),
+                fclose(fp);
+                error(['Problem while creating image for "' fname '".']);
+            end;
+            nbytes = nbytes - nw;
+        end;
+    end;
+    fclose(fp);
+end;
+
+return;
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/disp.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/disp.m
new file mode 100644
index 0000000000000000000000000000000000000000..09563f2cb8a38525983b63f87a26af50e8a33f9b
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/disp.m
@@ -0,0 +1,27 @@
+function disp(obj)
+% Disp a NIFTI-1 object
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: disp.m 4136 2010-12-09 22:22:28Z guillaume 
+
+%
+% niftilib $Id: disp.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+sz = size(obj);
+fprintf('NIFTI object: ');
+if length(sz)>4,
+    fprintf('%d-D\n',length(sz));
+else
+    for i=1:(length(sz)-1),
+        fprintf('%d-by-',sz(i));
+    end;
+    fprintf('%d\n',sz(end));
+end;
+if prod(sz)==1,
+    disp(structn(obj))
+end;
+return;
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/display.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/display.m
new file mode 100644
index 0000000000000000000000000000000000000000..38383ab81c828f47841550b5553e179c0f728754
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/display.m
@@ -0,0 +1,18 @@
+function display(obj)
+% Display a NIFTI-1 object
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: display.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: display.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+disp(' ');
+disp([inputname(1),' = '])
+disp(' ');
+disp(obj)
+disp(' ')
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/fieldnames.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/fieldnames.m
new file mode 100644
index 0000000000000000000000000000000000000000..25739257debbe05b9b1b3835e2921f1ab06e56a0
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/fieldnames.m
@@ -0,0 +1,30 @@
+function t = fieldnames(obj)
+% Fieldnames of a NIFTI-1 object
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: fieldnames.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: fieldnames.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+if isfield(obj.hdr,'magic')
+    t = {...
+        'dat'
+        'mat'
+        'mat_intent'
+        'mat0'
+        'mat0_intent'
+        'intent'
+        'diminfo'
+        'timing'
+        'descrip'
+        'cal'
+        'aux_file'
+    };
+else
+    error('This should not happen.');
+end;
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/nifti.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/nifti.m
new file mode 100644
index 0000000000000000000000000000000000000000..6bd71b1b911bc6965ddb226983c8c6f2e21ae8aa
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/nifti.m
@@ -0,0 +1,95 @@
+function h = nifti(varargin)
+% Create a NIFTI-1 object
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: nifti.m 4270 2011-03-29 16:26:26Z john 
+
+%
+% niftilib $Id: nifti.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+switch nargin
+case 0,
+    org = niftistruc;
+    hdr = [];
+    for i=1:length(org),
+        hdr.(org(i).label) = feval(org(i).dtype.conv,org(i).def);
+    end;
+    h = struct('hdr',hdr,'dat',[],'extras',struct);
+    h = class(h,'nifti');
+
+case 1
+    if ischar(varargin{1})
+        if size(varargin{1},1)>1,
+            h = nifti(cellstr(varargin{1}));
+            return;
+        end;
+        fname  = deblank(varargin{1});
+        vol    = read_hdr(fname);
+        extras = read_extras(fname);
+
+        if ~isfield(vol.hdr,'magic'),
+            vol.hdr = mayo2nifti1(vol.hdr);
+
+            % For SPM99 compatibility
+            if isfield(extras,'M') && ~isfield(extras,'mat'),
+                 extras.mat = extras.M;
+                 if spm_flip_analyze_images,
+                     extras.mat = diag([-1 1 1 1])*extras.mat;
+                 end;
+            end;
+
+            % Over-ride sform if a .mat file exists
+            if isfield(extras,'mat') && size(extras.mat,3)>=1,
+                mat            = extras.mat(:,:,1);
+                mat1           = mat*[eye(4,3) [1 1 1 1]'];
+                vol.hdr.srow_x = mat1(1,:);
+                vol.hdr.srow_y = mat1(2,:);
+                vol.hdr.srow_z = mat1(3,:);
+                vol.hdr.sform_code = 2;
+                vol.hdr.qform_code = 2;
+                vol.hdr = encode_qform0(mat,vol.hdr);
+            end;
+        end;
+
+        if isfield(extras,'M'), extras = rmfield(extras,'M'); end;
+        if isfield(extras,'mat') && size(extras.mat,3)<=1,
+            extras = rmfield(extras,'mat');
+        end;
+
+        dim   = double(vol.hdr.dim);
+        dim   = dim(2:(dim(1)+1));
+        dt    = double(vol.hdr.datatype);
+        offs  = max(double(vol.hdr.vox_offset),0);
+
+        if ~vol.hdr.scl_slope && ~vol.hdr.scl_inter,
+            vol.hdr.scl_slope = 1;
+        end;
+        slope = double(vol.hdr.scl_slope);
+        inter = double(vol.hdr.scl_inter);
+
+        dat   = file_array(vol.iname,dim,[dt,vol.be],offs,slope,inter);
+        h     = struct('hdr',vol.hdr,'dat',dat,'extras',extras);
+        h     = class(h,'nifti');
+
+    elseif isstruct(varargin{1})
+        h     = class(varargin{1},'nifti');
+
+    elseif iscell(varargin{1})
+        fnames = varargin{1};
+        h(numel(fnames)) = struct('hdr',[],'dat',[],'extras',struct);
+        h     = class(h,'nifti');
+        for i=1:numel(fnames),
+            h(i) = nifti(fnames{i});
+        end;
+
+    else
+        error('Dont know what to do yet.');
+    end;
+otherwise
+    error('Dont know what to do yet');
+end;
+return;
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/M2Q.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/M2Q.m
new file mode 100644
index 0000000000000000000000000000000000000000..1b453d6287c591292cf0cc1a39da389e8067b2f4
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/M2Q.m
@@ -0,0 +1,38 @@
+function Q = M2Q(M)
+% Convert from rotation matrix to quaternion form
+% See: http://skal.planet-d.net/demo/matrixfaq.htm
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: M2Q.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: M2Q.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+d = diag(M(1:3,1:3));
+t = sum(d) + 1;
+if t>0.5,
+    s = sqrt(t)*2;
+    Q = [(M(3,2)-M(2,3))/s (M(1,3)-M(3,1))/s (M(2,1)-M(1,2))/s 0.25*s]';
+else
+    t = find(d==max(d));
+    t = t(1);
+    switch(t),
+    case 1,
+        s = 2*sqrt(1 + M(1,1) - M(2,2) - M(3,3));
+        Q = [0.25*s (M(1,2)+M(2,1))/s (M(3,1)+M(1,3))/s (M(3,2)-M(2,3))/s]';
+    case 2,
+        s = 2*sqrt(1 + M(2,2) - M(1,1) - M(3,3));
+        Q = [(M(1,2)+M(2,1))/s 0.25*s (M(2,3)+M(3,2))/s (M(1,3)-M(3,1))/s ]';
+    case 3,
+        s = 2*sqrt(1 + M(3,3) - M(1,1) - M(2,2));
+        Q = [(M(3,1)+M(1,3))/s (M(2,3)+M(3,2))/s 0.25*s (M(2,1)-M(1,2))/s]';
+    end;
+end;
+if Q(4)<0, Q = -Q; end; % w must be +ve
+return;
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/Q2M.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/Q2M.m
new file mode 100644
index 0000000000000000000000000000000000000000..4d4caf1b08a681747fc512a904f2f440f0025f11
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/Q2M.m
@@ -0,0 +1,36 @@
+function M = Q2M(Q)
+% Generate a rotation matrix from a quaternion xi+yj+zk+w,
+% where Q = [x y z], and w = 1-x^2-y^2-z^2.
+% See: http://skal.planet-d.net/demo/matrixfaq.htm
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: Q2M.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: Q2M.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+Q = Q(1:3); % Assume rigid body
+w = sqrt(1 - sum(Q.^2));
+x = Q(1); y = Q(2); z = Q(3);
+if w<1e-7,
+    w = 1/sqrt(x*x+y*y+z*z);
+    x = x*w;
+    y = y*w;
+    z = z*w;
+    w = 0;
+end;
+xx = x*x; yy = y*y; zz = z*z; ww = w*w;
+xy = x*y; xz = x*z; xw = x*w;
+yz = y*z; yw = y*w; zw = z*w;
+M = [...
+(xx-yy-zz+ww)      2*(xy-zw)      2*(xz+yw) 0
+    2*(xy+zw) (-xx+yy-zz+ww)      2*(yz-xw) 0
+    2*(xz-yw)      2*(yz+xw) (-xx-yy+zz+ww) 0
+           0              0              0  1];
+return;
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/decode_qform0.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/decode_qform0.m
new file mode 100644
index 0000000000000000000000000000000000000000..08ba04619f8d24f98bc65147910e3899311c2f96
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/decode_qform0.m
@@ -0,0 +1,65 @@
+function M = decode_qform0(hdr)
+% Decode qform info from NIFTI-1 headers.
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: decode_qform0.m 3131 2009-05-18 15:54:10Z guillaume 
+
+%
+% niftilib $Id: decode_qform0.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+dim    = double(hdr.dim);
+pixdim = double(hdr.pixdim);
+if ~isfield(hdr,'magic') || hdr.qform_code <= 0,
+    flp = spm_flip_analyze_images;
+    %disp('------------------------------------------------------');
+    %disp('The images are in a form whereby it is not possible to');
+    %disp('tell the left and right sides of the brain apart.');
+    %if flp,
+    %    disp('They are assumed to be stored left-handed.');
+    %else
+    %    disp('They are assumed to be stored right-handed.');
+    %end;
+    %disp('------------------------------------------------------');
+
+    %R     = eye(4);
+    n      = min(dim(1),3);
+    vox    = [pixdim(2:(n+1)) ones(1,3-n)];
+
+    if ~isfield(hdr,'origin') || ~any(hdr.origin(1:3)),
+       origin = (dim(2:4)+1)/2;
+    else
+        origin = double(hdr.origin(1:3));
+    end;
+    off     = -vox.*origin;
+    M       = [vox(1) 0 0 off(1) ; 0 vox(2) 0 off(2) ; 0 0 vox(3) off(3) ; 0 0 0 1];
+
+    % Stuff for default orientations
+    if flp, M = diag([-1 1 1 1])*M; end;
+else
+
+    % Rotations from quaternions
+    R = Q2M(double([hdr.quatern_b hdr.quatern_c hdr.quatern_d]));
+
+    % Translations
+    T = [eye(4,3) double([hdr.qoffset_x hdr.qoffset_y hdr.qoffset_z 1]')];
+
+    % Zooms.  Note that flips are derived from the first
+    % element of pixdim, which is normally unused.
+    n = min(dim(1),3);
+    Z = [pixdim(2:(n+1)) ones(1,4-n)];
+    Z(Z<0) = 1;
+    if pixdim(1)<0, Z(3) = -Z(3); end;
+    Z = diag(Z);
+
+    M = T*R*Z;
+
+    % Convert from first voxel at [1,1,1]
+    % to first voxel at [0,0,0]
+    M = M * [eye(4,3) [-1 -1 -1 1]'];
+end;
+return;
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/empty_hdr.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/empty_hdr.m
new file mode 100644
index 0000000000000000000000000000000000000000..db269333b3c96626f9544f34b11412a476fc5987
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/empty_hdr.m
@@ -0,0 +1,20 @@
+function hdr = empty_hdr
+% Create an empty NIFTI-1 header
+% FORMAT hdr = empty_hdr
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: empty_hdr.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: empty_hdr.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+org = niftistruc;
+for i=1:length(org),
+    hdr.(org(i).label) = org(i).def;
+end;
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/encode_qform0.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/encode_qform0.m
new file mode 100644
index 0000000000000000000000000000000000000000..7649ed60d2502d14cf4825410adeb09f286d5cc7
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/encode_qform0.m
@@ -0,0 +1,50 @@
+function hdr = encode_qform0(M,hdr)
+% Encode an affine transform into qform
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: encode_qform0.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: encode_qform0.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+% Convert from first voxel at [1,1,1] to first voxel at [0,0,0]
+M = M * [eye(4,3) [1 1 1 1]'];
+
+% Translations
+hdr.qoffset_x = M(1,4);
+hdr.qoffset_y = M(2,4);
+hdr.qoffset_z = M(3,4);
+
+% Rotations and zooms
+R         = M(1:3,1:3);
+vx        = sqrt(sum(M(1:3,1:3).^2));
+vx(vx==0) = 1;
+R         = R * diag(1./vx);
+
+% Ensure that R is O(3)
+[U,S,V] = svd(R);
+R       = U*V';
+if any(abs(diag(S)-1)>1e-3), warning('QFORM0 representation has been rounded.'); end;
+
+% Ensure that R is SO(3)
+if det(R)>0
+    hdr.pixdim(1:4) = [ 1 vx];
+else
+    R               = R*diag([1 1 -1]);
+    hdr.pixdim(1:4) = [-1 vx];
+end;
+
+% Convert to quaternions
+Q             = M2Q(R);
+hdr.quatern_b = Q(1);
+hdr.quatern_c = Q(2);
+hdr.quatern_d = Q(3);
+
+if hdr.qform_code == 0, hdr.qform_code = 2; end;
+return;
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/findindict.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/findindict.m
new file mode 100644
index 0000000000000000000000000000000000000000..7fd41d9c187d75a936222faa6bd2d56f9df90766
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/findindict.m
@@ -0,0 +1,42 @@
+function entry = findindict(c,dcode)
+% Look up an entry in the dictionary
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: findindict.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: findindict.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+entry = [];
+d = getdict;
+d = d.(dcode);
+if ischar(c)
+    for i=1:length(d),
+        if strcmpi(d(i).label,c),
+            entry = d(i);
+            break;
+        end;
+    end;
+elseif isnumeric(c) && numel(c)==1
+    for i=1:length(d),
+        if d(i).code==c,
+            entry = d(i);
+            break;
+        end;
+    end;
+else
+    error(['Inappropriate code for ' dcode '.']);
+end;
+if isempty(entry)
+    fprintf('\nThis is not an option.  Try one of these:\n');
+    for i=1:length(d)
+        fprintf('%5d) %s\n', d(i).code, d(i).label);
+    end;
+    %fprintf('\nNO CHANGES MADE\n');
+end;
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/getdict.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/getdict.m
new file mode 100644
index 0000000000000000000000000000000000000000..acdfa4d481eb6428961e0cc5f045c9d495ecf928
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/getdict.m
@@ -0,0 +1,158 @@
+function d = getdict
+% Dictionary of NIFTI stuff
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: getdict.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: getdict.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+persistent dict;
+if ~isempty(dict),
+    d = dict;
+    return;
+end;
+
+% Datatype
+t = true;
+f = false;
+table = {...
+    0   ,'UNKNOWN'   ,'uint8'   ,@uint8  ,1,1  ,t,t,f
+    1   ,'BINARY'    ,'uint1'   ,@logical,1,1/8,t,t,f
+    256 ,'INT8'      ,'int8'    ,@int8   ,1,1  ,t,f,t
+    2   ,'UINT8'     ,'uint8'   ,@uint8  ,1,1  ,t,t,t
+    4   ,'INT16'     ,'int16'   ,@int16  ,1,2  ,t,f,t
+    512 ,'UINT16'    ,'uint16'  ,@uint16 ,1,2  ,t,t,t
+    8   ,'INT32'     ,'int32'   ,@int32  ,1,4  ,t,f,t
+    768 ,'UINT32'    ,'uint32'  ,@uint32 ,1,4  ,t,t,t
+    1024,'INT64'     ,'int64'   ,@int64  ,1,8  ,t,f,f
+    1280,'UINT64'    ,'uint64'  ,@uint64 ,1,8  ,t,t,f
+    16  ,'FLOAT32'   ,'float32' ,@single ,1,4  ,f,f,t
+    64  ,'FLOAT64'   ,'double'  ,@double ,1,8  ,f,f,t
+    1536,'FLOAT128'  ,'float128',@crash  ,1,16 ,f,f,f
+    32  ,'COMPLEX64' ,'float32' ,@single ,2,4  ,f,f,f
+    1792,'COMPLEX128','double'  ,@double ,2,8  ,f,f,f
+    2048,'COMPLEX256','float128',@crash  ,2,16 ,f,f,f
+    128 ,'RGB24'     ,'uint8'   ,@uint8  ,3,1  ,t,t,f};
+
+dtype = struct(...
+    'code'     ,table(:,1),...
+    'label'    ,table(:,2),...
+    'prec'     ,table(:,3),...
+    'conv'     ,table(:,4),...
+    'nelem'    ,table(:,5),...
+    'size'     ,table(:,6),...
+    'isint'    ,table(:,7),...
+    'unsigned' ,table(:,8),...
+    'min',-Inf,'max',Inf',...
+    'supported',table(:,9));
+for i=1:length(dtype),
+    if dtype(i).isint
+        if dtype(i).unsigned
+            dtype(i).min =  0;
+            dtype(i).max =  2^(8*dtype(i).size)-1;
+        else
+            dtype(i).min = -2^(8*dtype(i).size-1);
+            dtype(i).max =  2^(8*dtype(i).size-1)-1;
+        end;
+    end;
+end;
+% Intent
+table = {...
+    0   ,'NONE'         ,'None',{}
+    2   ,'CORREL'       ,'Correlation statistic',{'DOF'}
+    3   ,'TTEST'        ,'T-statistic',{'DOF'}
+    4   ,'FTEST'        ,'F-statistic',{'numerator DOF','denominator DOF'}
+    5   ,'ZSCORE'       ,'Z-score',{}
+    6   ,'CHISQ'        ,'Chi-squared distribution',{'DOF'}
+    7   ,'BETA'         ,'Beta distribution',{'a','b'}
+    8   ,'BINOM'        ,'Binomial distribution',...
+        {'number of trials','probability per trial'}
+    9   ,'GAMMA'        ,'Gamma distribution',{'shape','scale'}
+    10  ,'POISSON'      ,'Poisson distribution',{'mean'}
+    11  ,'NORMAL'       ,'Normal distribution',{'mean','standard deviation'}
+    12  ,'FTEST_NONC'   ,'F-statistic noncentral',...
+        {'numerator DOF','denominator DOF','numerator noncentrality parameter'}
+    13  ,'CHISQ_NONC'   ,'Chi-squared noncentral',{'DOF','noncentrality parameter'}
+    14  ,'LOGISTIC'     ,'Logistic distribution',{'location','scale'}
+    15  ,'LAPLACE'      ,'Laplace distribution',{'location','scale'}
+    16  ,'UNIFORM'      ,'Uniform distribition',{'lower end','upper end'}
+    17  ,'TTEST_NONC'   ,'T-statistic noncentral',{'DOF','noncentrality parameter'}
+    18  ,'WEIBULL'      ,'Weibull distribution',{'location','scale','power'}
+    19  ,'CHI'          ,'Chi distribution',{'DOF'}
+    20  ,'INVGAUSS'     ,'Inverse Gaussian distribution',{'mu','lambda'}
+    21  ,'EXTVAL'       ,'Extreme Value distribution',{'location','scale'}
+    22  ,'PVAL'         ,'P-value',{}
+    23  ,'LOGPVAL'      ,'Log P-value',{}
+    24  ,'LOG10PVAL'    ,'Log_10 P-value',{}
+    1001,'ESTIMATE'     ,'Estimate',{}
+    1002,'LABEL'        ,'Label index',{}
+    1003,'NEURONAMES'   ,'NeuroNames index',{}
+    1004,'MATRIX'       ,'General matrix',{'M','N'}
+    1005,'MATRIX_SYM'   ,'Symmetric matrix',{}
+    1006,'DISPLACEMENT' ,'Displacement vector',{}
+    1007,'VECTOR'       ,'Vector',{}
+    1008,'POINTS'       ,'Pointset',{}
+    1009,'TRIANGLE'     ,'Triangle',{}
+    1010,'QUATERNION'   ,'Quaternion',{}
+    1011,'DIMLESS'      ,'Dimensionless',{}
+};
+intent = struct('code',table(:,1),'label',table(:,2),...
+    'fullname',table(:,3),'param',table(:,4));
+
+% Units
+table = {...
+     0,   1,'UNKNOWN'
+     1,1000,'m'
+     2,   1,'mm'
+     3,1e-3,'um'
+     8,   1,'s'
+    16,1e-3,'ms'
+    24,1e-6,'us'
+    32,   1,'Hz'
+    40,   1,'ppm'
+    48,   1,'rads'};
+units = struct('code',table(:,1),'label',table(:,3),'rescale',table(:,2));
+
+% Reference space
+% code  = {0,1,2,3,4};
+table = {...
+    0,'UNKNOWN'
+    1,'Scanner Anat'
+    2,'Aligned Anat'
+    3,'Talairach'
+    4,'MNI_152'};
+anat  = struct('code',table(:,1),'label',table(:,2));
+
+% Slice Ordering
+table = {...
+    0,'UNKNOWN'
+    1,'sequential_increasing'
+    2,'sequential_decreasing'
+    3,'alternating_increasing'
+    4,'alternating_decreasing'};
+sliceorder = struct('code',table(:,1),'label',table(:,2));
+
+% Q/S Form Interpretation
+table = {...
+    0,'UNKNOWN'
+    1,'Scanner'
+    2,'Aligned'
+    3,'Talairach'
+    4,'MNI152'};
+xform = struct('code',table(:,1),'label',table(:,2));
+
+dict = struct('dtype',dtype,'intent',intent,'units',units,...
+    'space',anat,'sliceorder',sliceorder,'xform',xform);
+
+d = dict;
+return;
+
+function varargout = crash(varargin)
+error('There is a NIFTI-1 data format problem (an invalid datatype).');
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/mayo2nifti1.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/mayo2nifti1.m
new file mode 100644
index 0000000000000000000000000000000000000000..6c18e8ee781b7489d4acbe827e4c9f824a05b61e
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/mayo2nifti1.m
@@ -0,0 +1,72 @@
+function hdr = mayo2nifti1(ohdr,mat)
+% Convert from an ANALYZE to a NIFTI-1 header
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: mayo2nifti1.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: mayo2nifti1.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+if isfield(ohdr,'magic'),
+    hdr = ohdr;
+    return;
+end;
+hdr            = empty_hdr;
+hdr.dim        = ohdr.dim;
+hdr.datatype   = ohdr.datatype;
+hdr.bitpix     = ohdr.bitpix;
+hdr.pixdim     = ohdr.pixdim;
+hdr.vox_offset = ohdr.vox_offset;
+hdr.scl_slope  = ohdr.roi_scale;
+hdr.scl_inter  = ohdr.funused1;
+hdr.descrip    = ohdr.descrip;
+hdr.aux_file   = ohdr.aux_file;
+hdr.glmax      = ohdr.glmax;
+hdr.glmin      = ohdr.glmin;
+hdr.cal_max    = ohdr.cal_max;
+hdr.cal_min    = ohdr.cal_min;
+hdr.magic      = 'ni1';
+
+switch hdr.datatype,
+case 130, hdr.datatype = 256; %  int8
+case 132, hdr.datatype = 512; % uint16
+case 136, hdr.datatype = 768; % uint32
+end;
+
+if nargin<2,
+    % No mat, so create the equivalent from the hdr...
+    if any(ohdr.origin(1:3)), origin = double(ohdr.origin(1:3));
+    else                      origin = (double(ohdr.dim(2:4))+1)/2; end;
+    vox    = double(ohdr.pixdim(2:4));
+    if vox(1)<0,
+        % Assume FSL orientation
+        flp    = 0;
+    else
+        % Assume SPM or proper Analyze
+        flp    = spm_flip_analyze_images;
+    end;
+    if all(vox == 0), vox = [1 1 1]; end;
+    off    = -vox.*origin;
+    mat    = [vox(1) 0 0 off(1) ; 0 vox(2) 0 off(2) ; 0 0 vox(3) off(3) ; 0 0 0 1];
+    if flp,
+        %disp(['Assuming that image is stored left-handed']);
+        mat = diag([-1 1 1 1])*mat;
+    else
+        %disp(['Assuming that image is stored right-handed']);
+    end;
+end;
+
+hdr            = encode_qform0(mat,hdr);
+mat            = mat*[eye(4,3) [1 1 1 1]'];
+hdr.srow_x     = mat(1,:);
+hdr.srow_y     = mat(2,:);
+hdr.srow_z     = mat(3,:);
+hdr.qform_code = 2;
+hdr.sform_code = 2;
+return;
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/mayostruc.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/mayostruc.m
new file mode 100644
index 0000000000000000000000000000000000000000..e18578d47eeee4abffca0e602816db02050b616c
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/mayostruc.m
@@ -0,0 +1,85 @@
+function o = mayostruc
+% Create a data structure describing Analyze headers
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: mayostruc.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: mayostruc.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+persistent org;
+if ~isempty(org),
+    o = org;
+    return;
+end;
+t = struct('conv',{ @char, @int16, @int32, @single },...
+           'prec',{'uint8','int16','int32','single'},...
+           'size',{      1,      2,      4,       4});
+c = t(1);
+s = t(2);
+i = t(3);
+f = t(4);
+table = {...
+    i, 1,'sizeof_hdr',348
+    c,10,'data_type',[]
+    c,18,'db_name',[]
+    i, 1,'extents',[]
+    s, 1,'session_error',[]
+    c, 1,'regular','r'
+    c, 1,'hkey_un0',[]
+    s, 8,'dim',[3 1 1 1  1 1 1 1 1]
+    c, 4,'vox_units',[]
+    c, 8,'cal_units',[]
+    s, 1,'unused1',[]
+    s, 1,'datatype',[]
+    s, 1,'bitpix',[]
+    s, 1,'dim_un0',[]
+    f, 8,'pixdim',[]
+    f, 1,'vox_offset',0
+    f, 1,'roi_scale',1
+    f, 1,'funused1',0
+    f, 1,'funused2',[]
+    f, 1,'cal_max',[]
+    f, 1,'cal_min',[]
+    i, 1,'compressed',[]
+    i, 1,'verified',[]
+    i, 1,'glmax',[]
+    i, 1,'glmin',[]
+    c,80,'descrip','Analyze Image'
+    c,24,'aux_file',''
+    c, 1,'orient',[]
+%    c,10,'originator',[]
+    s, 5,'origin',[] % SPM version
+    c,10,'generated',[]
+    c,10,'scannum',[]
+    c,10,'patient_id',[]
+    c,10,'exp_date',[]
+    c,10,'exp_time',[]
+    c, 3,'hist_un0',[]
+    i, 1,'views',[]
+    i, 1,'vols_added',[]
+    i, 1,'start_field',[]
+    i, 1,'field_skip',[]
+    i, 1,'omax',[]
+    i, 1,'omin',[]
+    i, 1,'smax',[]
+    i, 1,'smin',[]};
+org = struct('label',table(:,3),'dtype',table(:,1),'len',table(:,2),...
+    'offset',0,'def',table(:,4));
+os  = 0;
+for j=1:length(org)
+    os  = os + org(j).dtype.size*ceil(os/org(j).dtype.size);
+    fun = org(j).dtype.conv;
+    def = [org(j).def zeros(1,org(j).len-length(org(j).def))];
+    org(j).def    = feval(fun,def);
+    org(j).offset = os;
+    os  = os + org(j).len*org(j).dtype.size;
+end;
+o = org;
+return;
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/nifti_stats.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/nifti_stats.m
new file mode 100644
index 0000000000000000000000000000000000000000..975f1af8836a44a687a31143aa3171dc5cc75f72
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/nifti_stats.m
@@ -0,0 +1,46 @@
+function varargout = nifti_stats(varargin)
+% Conversion among various statistics
+% FORMAT P = nifti_stats(VAL,CODE,OPT,PARAM)
+%   CODE can be one of
+%     'CORREL'      'TTEST'       'FTEST'       'ZSCORE'
+%     'CHISQ'       'BETA'        'BINOM'       'GAMMA'
+%     'POISSON'     'NORMAL'      'FTEST_NONC'  'CHISQ_NONC'
+%     'LOGISTIC'    'LAPLACE'     'UNIFORM'     'TTEST_NONC'
+%     'WEIBULL'     'CHI'         'INVGAUSS'    'EXTVAL'
+%     'PVAL'
+%   With only one input argument, CODE defaults to 'ZSCORE'
+%
+%   OPT can be one of
+%     '-p' ==> output P = Prob(statistic < VAL).
+%     '-q' ==> output is 1-p.
+%     '-d' ==> output is probability density.
+%     '-1' ==> output is X such that Prob(statistic < x) = VAL.
+%     '-z' ==> output is Z such that Normal cdf(Z) = p(VAL).
+%     '-h' ==> output is Z such that 1/2-Normal cdf(Z) = p(VAL).
+%   With less than three input arguments, OPT defaults to '-p'.
+%
+%   PARAM are up to three distribution parameters.
+%   These default to zero if unspecified.
+%
+%   P is an array with the same dimensions as VAL.
+%
+%_______________________________________________________________________
+% 99.99% of the work by RW Cox - SSCC/NIMH/NIH/DHHS/USA/EARTH - March 2004
+%  0.01% of the work (the mex wrapper) by John Ashburner - FIL/ION/UCL
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: nifti_stats.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: nifti_stats.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+fprintf('******************************************\n');
+fprintf('Compile the nifti_stats function with\n');
+fprintf('    mex nifti_stats.c nifti_stats_mex.c -O\n');
+fprintf('******************************************\n');
+
+error('nifti_stats is not compiled.');
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/niftistruc.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/niftistruc.m
new file mode 100644
index 0000000000000000000000000000000000000000..38dd12733c39ae6612b911880693036997cbe415
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/niftistruc.m
@@ -0,0 +1,86 @@
+function o = niftistruc
+% Create a data structure describing NIFTI headers
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: niftistruc.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: niftistruc.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+persistent org;
+if ~isempty(org),
+    o = org;
+    return;
+end;
+t = struct('conv',{ @char , @uint8 , @int16 , @int32 , @single },...
+           'prec',{'uint8', 'uint8', 'int16', 'int32', 'single'},...
+           'size',{       1,      1,      2,      4,       4 });
+c = t(1);
+b = t(2);
+s = t(3);
+i = t(4);
+f = t(5);
+
+table = {...
+    i, 1,'sizeof_hdr',348
+    c,10,'data_type',[]
+    c,18,'db_name',[]
+    i, 1,'extents',[]
+    s, 1,'session_error',[]
+    c, 1,'regular','r'
+    b, 1,'dim_info',[]
+    s, 8,'dim',[3 0 0 0  1 1 1 1 1]
+    f, 1,'intent_p1',0
+    f, 1,'intent_p2',0
+    f, 1,'intent_p3',0
+    s, 1,'intent_code',0
+    s, 1,'datatype',2
+    s, 1,'bitpix',8
+    s, 1,'slice_start',[]
+    f, 8,'pixdim',[0 1 1 1]
+    f, 1,'vox_offset',0
+    f, 1,'scl_slope',1
+    f, 1,'scl_inter',0
+    s, 1,'slice_end',[]
+    b, 1,'slice_code',[]
+    b, 1,'xyzt_units',10
+    f, 1,'cal_max',[]
+    f, 1,'cal_min',[]
+    f, 1,'slice_duration',[]
+    f, 1,'toffset',[]
+    i, 1,'glmax',[]
+    i, 1,'glmin',[]
+    c,80,'descrip','NIFTI-1 Image'
+    c,24,'aux_file',''
+    s, 1,'qform_code',0
+    s, 1,'sform_code',0
+    f, 1,'quatern_b',0
+    f, 1,'quatern_c',0
+    f, 1,'quatern_d',0
+    f, 1,'qoffset_x',0
+    f, 1,'qoffset_y',0
+    f, 1,'qoffset_z',0
+    f, 4,'srow_x',[1 0 0 0]
+    f, 4,'srow_y',[0 1 0 0]
+    f, 4,'srow_z',[0 0 1 0]
+    c,16,'intent_name',''
+    c, 4,'magic','ni1'};
+org = struct('label',table(:,3),'dtype',table(:,1),'len',table(:,2),...
+    'offset',0,'def',table(:,4));
+os  = 0;
+for j=1:length(org)
+    os  = os + org(j).dtype.size*ceil(os/org(j).dtype.size);
+    fun = org(j).dtype.conv;
+    def = [org(j).def zeros(1,org(j).len-length(org(j).def))];
+    org(j).def    = feval(fun,def);
+    org(j).offset = os;
+    os  = os + org(j).len*org(j).dtype.size;
+end;
+o = org;
+return;
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/read_extras.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/read_extras.m
new file mode 100644
index 0000000000000000000000000000000000000000..5047979ef83c9ebc4ce231536f3a80f7e657bc99
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/read_extras.m
@@ -0,0 +1,32 @@
+function extras = read_extras(fname)
+% Read extra bits of information
+%_______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: read_extras.m 2237 2008-09-29 17:39:53Z guillaume 
+
+%
+% niftilib $Id: read_extras.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+extras = struct;
+[pth,nam,ext] = fileparts(fname);
+switch ext
+case {'.hdr','.img','.nii'}
+    mname = fullfile(pth,[nam '.mat']);
+case {'.HDR','.IMG','.NII'}
+    mname = fullfile(pth,[nam '.MAT']);
+otherwise
+    mname = fullfile(pth,[nam '.mat']);
+end
+
+if spm_existfile(mname),
+    try,
+        extras = load(mname);
+    catch,
+        warning('Can not load "%s" as a binary MAT file.\n', mname);
+    end;
+end;
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/read_hdr.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/read_hdr.m
new file mode 100644
index 0000000000000000000000000000000000000000..e25c9498c545df9535614273ca8f5b8a31bd6331
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/read_hdr.m
@@ -0,0 +1,90 @@
+function vol = read_hdr(fname)
+% Get a variety of information from a NIFTI-1 header.
+% FORMAT vol = read_hdr(fname)
+% fname - filename of image
+% vol   - various bits of information
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: read_hdr.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: read_hdr.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+persistent d
+if isempty(d), d = getdict; end;
+
+[pth,nam,ext,num] = spm_fileparts(fname);
+switch ext
+case '.hdr'
+    hname = fullfile(pth,[nam '.hdr']);
+case '.HDR'
+    hname = fullfile(pth,[nam '.HDR']);
+case '.img'
+    hname = fullfile(pth,[nam '.hdr']);
+case '.IMG'
+    hname = fullfile(pth,[nam '.HDR']);
+case '.nii'
+    hname = fullfile(pth,[nam '.nii']);
+case '.NII'
+    hname = fullfile(pth,[nam '.NII']);
+otherwise
+    hname = fullfile(pth,[nam ext]);
+end
+[hdr,be] = read_hdr_raw(hname);
+if isempty(hdr)
+    error(['Error reading header file "' hname '"']);
+end;
+
+if ~isfield(hdr,'magic'),
+    % A patch for some possible SPM2 datatypes
+    switch hdr.datatype,
+    case 130, hdr.datatype = 256; %  int8
+    case 132, hdr.datatype = 512; % uint16
+    case 136, hdr.datatype = 768; % uint32
+    end;
+end;
+
+dt = [];
+for i=1:length(d.dtype)
+    if hdr.datatype == d.dtype(i).code
+        dt = d.dtype(i);
+        break;
+    end;
+end;
+if isempty(dt)
+    error(['Unrecognised datatype (' num2str(double(hdr.datatype)) ') for "' fname '.'] );
+end
+if isfield(hdr,'magic')
+    switch deblank(hdr.magic)
+    case {'n+1'}
+        iname = hname;
+        if hdr.vox_offset < hdr.sizeof_hdr
+            error(['Bad vox_offset (' num2str(double(hdr.vox_offset)) ') for "' fname '.'] );
+        end
+    case {'ni1'}
+        if strcmp(ext,lower(ext)),
+            iname = fullfile(pth,[nam '.img']);
+        else
+            iname = fullfile(pth,[nam '.IMG']);
+        end;
+    otherwise
+        error(['Bad magic (' hdr.magic ') for "' fname '.'] );
+    end
+else
+    if strcmp(ext,lower(ext)),
+        iname = fullfile(pth,[nam '.img']);
+    else
+        iname = fullfile(pth,[nam '.IMG']);
+    end;
+end
+if rem(double(hdr.vox_offset),dt.size)
+   error(['Bad alignment of voxels (' num2str(double(hdr.vox_offset)) '/' num2str(double(dt.size)) ') for "' fname '.'] );
+end;
+
+vol      = struct('hdr',hdr,'be',be,'hname',hname,'iname',iname);
+return
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/read_hdr_raw.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/read_hdr_raw.m
new file mode 100644
index 0000000000000000000000000000000000000000..ff0d501f5ea24855e2fb9fedec08b851c47764d9
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/read_hdr_raw.m
@@ -0,0 +1,98 @@
+function [hdr,be] = read_hdr_raw(fname)
+% Read a NIFTI-1 hdr file
+% FORMAT [hdr,be] = read_hdr_raw(fname)
+% fname - filename of image
+% hdr   - a structure containing hdr info
+% be    - whether big-endian or not
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: read_hdr_raw.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: read_hdr_raw.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+hdr = [];
+be  = [];
+ok  = true;
+
+% Name of header file
+[pth,nam,ext] = fileparts(fname);
+switch ext
+case {'.img','.hdr'}
+    hname = fullfile(pth,[nam '.hdr']);
+case {'.nii'}
+    hname = fullfile(pth,[nam '.nii']);
+otherwise
+    hname = fullfile(pth,[nam '.hdr']);
+end;
+
+% Open it if possible
+fp  = fopen(hname,'r','native');
+if fp==-1
+    hdr = [];
+    return;
+end;
+
+% Sort out endian issues of header
+[unused,unused,mach] = fopen(fp);
+if strcmp(mach,'ieee-be') || strcmp(mach,'ieee-be.l64')
+    be = true;
+else
+    be = false;
+end;
+fseek(fp,0,'bof');
+fseek(fp,40,'bof');
+nd = fread(fp,1,'int16')';
+if isempty(nd),
+    fclose(fp);
+    hdr = [];
+    return;
+elseif nd<1 || nd>7
+    be = ~be;
+    fclose(fp);
+    if be, mach = 'ieee-be';
+    else   mach = 'ieee-le';
+    end;
+    fp = fopen(hname,'r',mach);
+    if fp==-1
+        hdr = [];
+        return;
+    end;
+end;
+
+% Is it NIFTI or not
+fseek(fp,0,'bof');
+fseek(fp,344,'bof');
+mgc = deblank(char(fread(fp,4,'uint8')'));
+switch mgc
+case {'ni1','n+1'}
+    org = niftistruc;
+otherwise
+    org = mayostruc;
+end;
+fseek(fp,0,'bof');
+% Read the fields
+for i=1:length(org)
+    tmp = fread(fp,org(i).len,['*' org(i).dtype.prec])';
+    if length(tmp) ~= org(i).len
+disp([length(tmp) org(i).len]);
+        tmp = org(i).def;
+        ok  = false;
+    end;
+    tmp = feval(org(i).dtype.conv,tmp);
+    hdr.(org(i).label) = tmp;
+end;
+
+fclose(fp);
+if ~ok,
+     fprintf('There was a problem reading the header of\n');
+     fprintf('"%s".\n', fname);
+     fprintf('It may be corrupted in some way.');
+end;
+return;
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/spm_existfile.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/spm_existfile.m
new file mode 100644
index 0000000000000000000000000000000000000000..c3008e15fe1eddb264416fb241ae1f30ddc1260d
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/spm_existfile.m
@@ -0,0 +1,33 @@
+function s = spm_existfile(filename)
+% Check if a file exists on disk - a compiled routine
+% FORMAT S = SPM_EXISTFILE(FILENAME)
+% FILENAME - filename (can also be a relative or full pathname to a file)
+% S        - logical scalar, true if the file exists and false otherwise
+%_______________________________________________________________________
+%
+% This compiled routine is equivalent to:
+% >> s = exist(filename,'file') == 2;
+% and was written for speed purposes. The differences in behaviour are:
+%  * spm_existfile returns true for directory names
+%  * spm_existfile does not look in MATLAB's search path
+%  * spm_existfile returns false for an existing file that does not have
+%    read permission
+%_______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+% Guillaume Flandin
+% $Id: spm_existfile.m,v 1.1 2012/03/22 18:36:33 fissell Exp $
+
+
+%-This is merely the help file for the compiled routine
+%error('spm_existfile.c not compiled - see Makefile')
+%persistent runonce
+%if isempty(runonce)
+%    warning('spm_existfile is not compiled for your platform.');
+%    runonce = 1;
+%end
+
+%s = exist(filename,'file') > 0;
+
+% KF replace compiled version with almost equivalent matlab call
+s = exist(filename,'file') == 2;
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/spm_fileparts.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/spm_fileparts.m
new file mode 100644
index 0000000000000000000000000000000000000000..26029f1a4ac0bd455ba774c51abb3b9a61853e32
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/spm_fileparts.m
@@ -0,0 +1,26 @@
+function [pth,nam,ext,num] = spm_fileparts(fname)
+% Like fileparts, but separates off a comma separated list at the end
+% FORMAT [pth,nam,ext,num] = spm_fileparts(fname)
+% fname - original filename
+% pth   - path
+% nam   - filename
+% ext   - extension
+% num   - comma separated list of values
+%__________________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+% John Ashburner
+% Id: spm_fileparts.m 4205 2011-02-21 15:39:08Z guillaume 
+
+%
+% niftilib $Id: spm_fileparts.m,v 1.1 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+num = '';
+[pth,nam,ext] = fileparts(fname);
+ind = find(ext==',');
+if ~isempty(ind)
+    num = ext(ind(1):end);
+    ext = ext(1:(ind(1)-1));
+end
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/README b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/README
new file mode 100644
index 0000000000000000000000000000000000000000..155b63d60fb5f09f8647b07adaa861292989db5d
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/README
@@ -0,0 +1,17 @@
+/* 
+ * This is a Matlab mex interface for Bob Cox's extensive nifti_stats.c
+ * functionality.  See nifti_stats.m for documentation.
+ */
+
+
+To compile on a big-endian machine
+	mex -DBIGENDIAN nifti_stats.c nifti_stats_mex.c -O
+
+On a little-endian machine
+	mex nifti_stats.c nifti_stats_mex.c -O
+
+On a Windows machine
+	mex -O -DSPM_WIN32 nifti_stats.c nifti_stats_mex.c
+
+
+mv the .mex* file up one level to the private dir
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/nifti1.h b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/nifti1.h
new file mode 100644
index 0000000000000000000000000000000000000000..4e30c0ce6cb24f29b924f8f86950ad7ccf749eb5
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/nifti1.h
@@ -0,0 +1,1227 @@
+#ifndef _NIFTI_HEADER_
+#define _NIFTI_HEADER_
+
+/*****************************************************************************
+      ** This file defines the "NIFTI-1" header format.               **
+      ** It is derived from 2 meetings at the NIH (31 Mar 2003 and    **
+      ** 02 Sep 2003) of the Data Format Working Group (DFWG),        **
+      ** chartered by the NIfTI (Neuroimaging Informatics Technology  **
+      ** Initiative) at the National Institutes of Health (NIH).      **
+      **--------------------------------------------------------------**
+      ** Neither the National Institutes of Health (NIH), the DFWG,   **
+      ** nor any of the members or employees of these institutions    **
+      ** imply any warranty of usefulness of this material for any    **
+      ** purpose, and do not assume any liability for damages,        **
+      ** incidental or otherwise, caused by any use of this document. **
+      ** If these conditions are not acceptable, do not use this!     **
+      **--------------------------------------------------------------**
+      ** Author:   Robert W Cox (NIMH, Bethesda)                      **
+      ** Advisors: John Ashburner (FIL, London),                      **
+      **           Stephen Smith (FMRIB, Oxford),                     **
+      **           Mark Jenkinson (FMRIB, Oxford)                     **
+******************************************************************************/
+
+
+/*
+ * niftilib $Id: nifti1.h,v 1.1 2012/03/22 18:36:33 fissell Exp $
+ */
+
+/*---------------------------------------------------------------------------*/
+/* Note that the ANALYZE 7.5 file header (dbh.h) is
+         (c) Copyright 1986-1995
+         Biomedical Imaging Resource
+         Mayo Foundation
+   Incorporation of components of dbh.h are by permission of the
+   Mayo Foundation.
+
+   Changes from the ANALYZE 7.5 file header in this file are released to the
+   public domain, including the functional comments and any amusing asides.
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/*! INTRODUCTION TO NIFTI-1:
+   ------------------------
+   The twin (and somewhat conflicting) goals of this modified ANALYZE 7.5
+   format are:
+    (a) To add information to the header that will be useful for functional
+        neuroimaging data analysis and display.  These additions include:
+        - More basic data types.
+        - Two affine transformations to specify voxel coordinates.
+        - "Intent" codes and parameters to describe the meaning of the data.
+        - Affine scaling of the stored data values to their "true" values.
+        - Optional storage of the header and image data in one file (.nii).
+    (b) To maintain compatibility with non-NIFTI-aware ANALYZE 7.5 compatible
+        software (i.e., such a program should be able to do something useful
+        with a NIFTI-1 dataset -- at least, with one stored in a traditional
+        .img/.hdr file pair).
+
+   Most of the unused fields in the ANALYZE 7.5 header have been taken,
+   and some of the lesser-used fields have been co-opted for other purposes.
+   Notably, most of the data_history substructure has been co-opted for
+   other purposes, since the ANALYZE 7.5 format describes this substructure
+   as "not required".
+
+   NIFTI-1 FLAG (MAGIC STRINGS):
+   ----------------------------
+   To flag such a struct as being conformant to the NIFTI-1 spec, the last 4
+   bytes of the header must be either the C String "ni1" or "n+1";
+   in hexadecimal, the 4 bytes
+     6E 69 31 00   or   6E 2B 31 00
+   (in any future version of this format, the '1' will be upgraded to '2',
+   etc.).  Normally, such a "magic number" or flag goes at the start of the
+   file, but trying to avoid clobbering widely-used ANALYZE 7.5 fields led to
+   putting this marker last.  However, recall that "the last shall be first"
+   (Matthew 20:16).
+
+   If a NIFTI-aware program reads a header file that is NOT marked with a
+   NIFTI magic string, then it should treat the header as an ANALYZE 7.5
+   structure.
+
+   NIFTI-1 FILE STORAGE:
+   --------------------
+   "ni1" means that the image data is stored in the ".img" file corresponding
+   to the header file (starting at file offset 0).
+
+   "n+1" means that the image data is stored in the same file as the header
+   information.  We recommend that the combined header+data filename suffix
+   be ".nii".  When the dataset is stored in one file, the first byte of image
+   data is stored at byte location (int)vox_offset in this combined file.
+
+   GRACE UNDER FIRE:
+   ----------------
+   Most NIFTI-aware programs will only be able to handle a subset of the full
+   range of datasets possible with this format.  All NIFTI-aware programs
+   should take care to check if an input dataset conforms to the program's
+   needs and expectations (e.g., check datatype, intent_code, etc.).  If the
+   input dataset can't be handled by the program, the program should fail
+   gracefully (e.g., print a useful warning; not crash).
+
+   SAMPLE CODES:
+   ------------
+   The associated files nifti1_io.h and nifti1_io.c provide a sample
+   implementation in C of a set of functions to read, write, and manipulate
+   NIFTI-1 files.  The file nifti1_test.c is a sample program that uses
+   the nifti1_io.c functions.
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* HEADER STRUCT DECLARATION:
+   -------------------------
+   In the comments below for each field, only NIFTI-1 specific requirements
+   or changes from the ANALYZE 7.5 format are described.  For convenience,
+   the 348 byte header is described as a single struct, rather than as the
+   ANALYZE 7.5 group of 3 substructs.
+
+   Further comments about the interpretation of various elements of this
+   header are after the data type definition itself.  Fields that are
+   marked as ++UNUSED++ have no particular interpretation in this standard.
+   (Also see the UNUSED FIELDS comment section, far below.)
+
+   The presumption below is that the various C types have particular sizes:
+     sizeof(int) = sizeof(float) = 4 ;  sizeof(short) = 2
+-----------------------------------------------------------------------------*/
+
+/*=================*/
+#ifdef  __cplusplus
+extern "C" {
+#endif
+/*=================*/
+                        /*************************/  /************************/
+struct nifti_1_header { /* NIFTI-1 usage         */  /* ANALYZE 7.5 field(s) */
+                        /*************************/  /************************/
+
+                                           /*--- was header_key substruct ---*/
+ int   sizeof_hdr;    /*!< MUST be 348           */  /* int sizeof_hdr;      */
+ char  data_type[10]; /*!< ++UNUSED++            */  /* char data_type[10];  */
+ char  db_name[18];   /*!< ++UNUSED++            */  /* char db_name[18];    */
+ int   extents;       /*!< ++UNUSED++            */  /* int extents;         */
+ short session_error; /*!< ++UNUSED++            */  /* short session_error; */
+ char  regular;       /*!< ++UNUSED++            */  /* char regular;        */
+ char  dim_info;      /*!< MRI slice ordering.   */  /* char hkey_un0;       */
+
+                                      /*--- was image_dimension substruct ---*/
+ short dim[8];        /*!< Data array dimensions.*/  /* short dim[8];        */
+ float intent_p1 ;    /*!< 1st intent parameter. */  /* short unused8;       */
+                                                     /* short unused9;       */
+ float intent_p2 ;    /*!< 2nd intent parameter. */  /* short unused10;      */
+                                                     /* short unused11;      */
+ float intent_p3 ;    /*!< 3rd intent parameter. */  /* short unused12;      */
+                                                     /* short unused13;      */
+ short intent_code ;  /*!< NIFTI_INTENT_* code.  */  /* short unused14;      */
+ short datatype;      /*!< Defines data type!    */  /* short datatype;      */
+ short bitpix;        /*!< Number bits/voxel.    */  /* short bitpix;        */
+ short slice_start;   /*!< First slice index.    */  /* short dim_un0;       */
+ float pixdim[8];     /*!< Grid spacings.        */  /* float pixdim[8];     */
+ float vox_offset;    /*!< Offset into .nii file */  /* float vox_offset;    */
+ float scl_slope ;    /*!< Data scaling: slope.  */  /* float funused1;      */
+ float scl_inter ;    /*!< Data scaling: offset. */  /* float funused2;      */
+ short slice_end;     /*!< Last slice index.     */  /* float funused3;      */
+ char  slice_code ;   /*!< Slice timing order.   */
+ char  xyzt_units ;   /*!< Units of pixdim[1..4] */
+ float cal_max;       /*!< Max display intensity */  /* float cal_max;       */
+ float cal_min;       /*!< Min display intensity */  /* float cal_min;       */
+ float slice_duration;/*!< Time for 1 slice.     */  /* float compressed;    */
+ float toffset;       /*!< Time axis shift.      */  /* float verified;      */
+ int   glmax;         /*!< ++UNUSED++            */  /* int glmax;           */
+ int   glmin;         /*!< ++UNUSED++            */  /* int glmin;           */
+
+                                         /*--- was data_history substruct ---*/
+ char  descrip[80];   /*!< any text you like.    */  /* char descrip[80];    */
+ char  aux_file[24];  /*!< auxiliary filename.   */  /* char aux_file[24];   */
+
+ short qform_code ;   /*!< NIFTI_XFORM_* code.   */  /*-- all ANALYZE 7.5 ---*/
+ short sform_code ;   /*!< NIFTI_XFORM_* code.   */  /*   fields below here  */
+                                                     /*   are replaced       */
+ float quatern_b ;    /*!< Quaternion b param.   */
+ float quatern_c ;    /*!< Quaternion c param.   */
+ float quatern_d ;    /*!< Quaternion d param.   */
+ float qoffset_x ;    /*!< Quaternion x shift.   */
+ float qoffset_y ;    /*!< Quaternion y shift.   */
+ float qoffset_z ;    /*!< Quaternion z shift.   */
+
+ float srow_x[4] ;    /*!< 1st row affine transform.   */
+ float srow_y[4] ;    /*!< 2nd row affine transform.   */
+ float srow_z[4] ;    /*!< 3rd row affine transform.   */
+
+ char intent_name[16];/*!< 'name' or meaning of data.  */
+
+ char magic[4] ;      /*!< MUST be "ni1\0" or "n+1\0". */
+
+} ;                   /**** 348 bytes total ****/
+
+typedef struct nifti_1_header nifti_1_header ;
+
+/*---------------------------------------------------------------------------*/
+/* DATA DIMENSIONALITY (as in ANALYZE 7.5):
+   ---------------------------------------
+     dim[0] = number of dimensions;
+              - if dim[0] is outside range 1..7, then the header information
+                needs to be byte swapped appropriately
+              - ANALYZE supports dim[0] up to 7, but NIFTI-1 reserves
+                dimensions 1,2,3 for space (x,y,z), 4 for time (t), and
+                5,6,7 for anything else needed.
+
+     dim[i] = length of dimension #i, for i=1..dim[0]  (must be positive)
+              - also see the discussion of intent_code, far below
+
+     pixdim[i] = voxel width along dimension #i, i=1..dim[0] (positive)
+                 - cf. ORIENTATION section below for use of pixdim[0]
+                 - the units of pixdim can be specified with the xyzt_units
+                   field (also described far below).
+
+   Number of bits per voxel value is in bitpix, which MUST correspond with
+   the datatype field.  The total number of bytes in the image data is
+     dim[1] * ... * dim[dim[0]] * bitpix / 8
+
+   In NIFTI-1 files, dimensions 1,2,3 are for space, dimension 4 is for time,
+   and dimension 5 is for storing multiple values at each spatiotemporal
+   voxel.  Some examples:
+     - A typical whole-brain FMRI experiment's time series:
+        - dim[0] = 4
+        - dim[1] = 64   pixdim[1] = 3.75 xyzt_units =  NIFTI_UNITS_MM
+        - dim[2] = 64   pixdim[2] = 3.75             | NIFTI_UNITS_SEC
+        - dim[3] = 20   pixdim[3] = 5.0
+        - dim[4] = 120  pixdim[4] = 2.0
+     - A typical T1-weighted anatomical volume:
+        - dim[0] = 3
+        - dim[1] = 256  pixdim[1] = 1.0  xyzt_units = NIFTI_UNITS_MM
+        - dim[2] = 256  pixdim[2] = 1.0
+        - dim[3] = 128  pixdim[3] = 1.1
+     - A single slice EPI time series:
+        - dim[0] = 4
+        - dim[1] = 64   pixdim[1] = 3.75 xyzt_units =  NIFTI_UNITS_MM
+        - dim[2] = 64   pixdim[2] = 3.75             | NIFTI_UNITS_SEC
+        - dim[3] = 1    pixdim[3] = 5.0
+        - dim[4] = 1200 pixdim[4] = 0.2
+     - A 3-vector stored at each point in a 3D volume:
+        - dim[0] = 5
+        - dim[1] = 256  pixdim[1] = 1.0  xyzt_units = NIFTI_UNITS_MM
+        - dim[2] = 256  pixdim[2] = 1.0
+        - dim[3] = 128  pixdim[3] = 1.1
+        - dim[4] = 1    pixdim[4] = 0.0
+        - dim[5] = 3                     intent_code = NIFTI_INTENT_VECTOR
+     - A single time series with a 3x3 matrix at each point:
+        - dim[0] = 5
+        - dim[1] = 1                     xyzt_units = NIFTI_UNITS_SEC
+        - dim[2] = 1
+        - dim[3] = 1
+        - dim[4] = 1200 pixdim[4] = 0.2
+        - dim[5] = 9                     intent_code = NIFTI_INTENT_GENMATRIX
+        - intent_p1 = intent_p2 = 3.0    (indicates matrix dimensions)
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* DATA STORAGE:
+   ------------
+   If the magic field is "n+1", then the voxel data is stored in the
+   same file as the header.  In this case, the voxel data starts at offset
+   (int)vox_offset into the header file.  Thus, vox_offset=348.0 means that
+   the data starts immediately after the NIFTI-1 header.  If vox_offset is
+   greater than 348, the NIFTI-1 format does not say anything about the
+   contents of the dataset file between the end of the header and the
+   start of the data.
+
+   FILES:
+   -----
+   If the magic field is "ni1", then the voxel data is stored in the
+   associated ".img" file, starting at offset 0 (i.e., vox_offset is not
+   used in this case, and should be set to 0.0).
+
+   When storing NIFTI-1 datasets in pairs of files, it is customary to name
+   the files in the pattern "name.hdr" and "name.img", as in ANALYZE 7.5.
+   When storing in a single file ("n+1"), the file name should be in
+   the form "name.nii" (the ".nft" and ".nif" suffixes are already taken;
+   cf. http://www.icdatamaster.com/n.html ).
+
+   BYTE ORDERING:
+   -------------
+   The byte order of the data arrays is presumed to be the same as the byte
+   order of the header (which is determined by examining dim[0]).
+
+   Floating point types are presumed to be stored in IEEE-754 format.
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* DATA SCALING:
+   ------------
+   If the scl_slope field is nonzero, then each voxel value in the dataset
+   should be scaled as
+      y = scl_slope * x + scl_inter
+   where x = voxel value stored
+         y = "true" voxel value
+   Normally, we would expect this scaling to be used to store "true" floating
+   values in a smaller integer datatype, but that is not required.  That is,
+   it is legal to use scaling even if the datatype is a float type (crazy,
+   perhaps, but legal).
+    - However, the scaling is to be ignored if datatype is DT_RGB24.
+    - If datatype is a complex type, then the scaling is to be
+      applied to both the real and imaginary parts.
+
+   The cal_min and cal_max fields (if nonzero) are used for mapping (possibly
+   scaled) dataset values to display colors:
+    - Minimum display intensity (black) corresponds to dataset value cal_min.
+    - Maximum display intensity (white) corresponds to dataset value cal_max.
+    - Dataset values below cal_min should display as black also, and values
+      above cal_max as white.
+    - Colors "black" and "white", of course, may refer to any scalar display
+      scheme (e.g., a color lookup table specified via aux_file).
+    - cal_min and cal_max only make sense when applied to scalar-valued
+      datasets (i.e., dim[0] < 5 or dim[5] = 1).
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* TYPE OF DATA (acceptable values for datatype field):
+   ---------------------------------------------------
+   Values of datatype smaller than 256 are ANALYZE 7.5 compatible.
+   Larger values are NIFTI-1 additions.  These are all multiples of 256, so
+   that no bits below position 8 are set in datatype.  But there is no need
+   to use only powers-of-2, as the original ANALYZE 7.5 datatype codes do.
+
+   The additional codes are intended to include a complete list of basic
+   scalar types, including signed and unsigned integers from 8 to 64 bits,
+   floats from 32 to 128 bits, and complex (float pairs) from 64 to 256 bits.
+
+   Note that most programs will support only a few of these datatypes!
+   A NIFTI-1 program should fail gracefully (e.g., print a warning message)
+   when it encounters a dataset with a type it doesn't like.
+-----------------------------------------------------------------------------*/
+
+#undef DT_UNKNOWN  /* defined in dirent.h on some Unix systems */
+
+                            /*--- the original ANALYZE 7.5 type codes ---*/
+#define DT_NONE                    0
+#define DT_UNKNOWN                 0     /* what it says, dude           */
+#define DT_BINARY                  1     /* binary (1 bit/voxel)         */
+#define DT_UNSIGNED_CHAR           2     /* unsigned char (8 bits/voxel) */
+#define DT_SIGNED_SHORT            4     /* signed short (16 bits/voxel) */
+#define DT_SIGNED_INT              8     /* signed int (32 bits/voxel)   */
+#define DT_FLOAT                  16     /* float (32 bits/voxel)        */
+#define DT_COMPLEX                32     /* complex (64 bits/voxel)      */
+#define DT_DOUBLE                 64     /* double (64 bits/voxel)       */
+#define DT_RGB                   128     /* RGB triple (24 bits/voxel)   */
+#define DT_ALL                   255     /* not very useful (?)          */
+
+                            /*----- another set of names for the same ---*/
+#define DT_UINT8                   2
+#define DT_INT16                   4
+#define DT_INT32                   8
+#define DT_FLOAT32                16
+#define DT_COMPLEX64              32
+#define DT_FLOAT64                64
+#define DT_RGB24                 128
+
+                            /*------------------- new codes for NIFTI ---*/
+#define DT_INT8                  256     /* signed char (8 bits)         */
+#define DT_UINT16                512     /* unsigned short (16 bits)     */
+#define DT_UINT32                768     /* unsigned int (32 bits)       */
+#define DT_INT64                1024     /* long long (64 bits)          */
+#define DT_UINT64               1280     /* unsigned long long (64 bits) */
+#define DT_FLOAT128             1536     /* long double (128 bits)       */
+#define DT_COMPLEX128           1792     /* double pair (128 bits)       */
+#define DT_COMPLEX256           2048     /* long double pair (256 bits)  */
+
+                            /*------- aliases for all the above codes ---*/
+
+                                       /*! unsigned char. */
+#define NIFTI_TYPE_UINT8           2
+                                       /*! signed short. */
+#define NIFTI_TYPE_INT16           4
+                                       /*! signed int. */
+#define NIFTI_TYPE_INT32           8
+                                       /*! 32 bit float. */
+#define NIFTI_TYPE_FLOAT32        16
+                                       /*! 64 bit complex = 2 32 bit floats. */
+#define NIFTI_TYPE_COMPLEX64      32
+                                       /*! 64 bit float = double. */
+#define NIFTI_TYPE_FLOAT64        64
+                                       /*! 3 8 bit bytes. */
+#define NIFTI_TYPE_RGB24         128
+                                       /*! signed char. */
+#define NIFTI_TYPE_INT8          256
+                                       /*! unsigned short. */
+#define NIFTI_TYPE_UINT16        512
+                                       /*! unsigned int. */
+#define NIFTI_TYPE_UINT32        768
+                                       /*! signed long long. */
+#define NIFTI_TYPE_INT64        1024
+                                       /*! unsigned long long. */
+#define NIFTI_TYPE_UINT64       1280
+                                       /*! 128 bit float = long double. */
+#define NIFTI_TYPE_FLOAT128     1536
+                                       /*! 128 bit complex = 2 64 bit floats. */
+#define NIFTI_TYPE_COMPLEX128   1792
+                                       /*! 256 bit complex = 2 128 bit floats */
+#define NIFTI_TYPE_COMPLEX256   2048
+
+                     /*-------- sample typedefs for complicated types ---*/
+#if 0
+typedef struct { float       r,i;     } complex_float ;
+typedef struct { double      r,i;     } complex_double ;
+typedef struct { long double r,i;     } complex_longdouble ;
+typedef struct { unsigned char r,g,b; } rgb_byte ;
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* INTERPRETATION OF VOXEL DATA:
+   ----------------------------
+   The intent_code field can be used to indicate that the voxel data has
+   some particular meaning.  In particular, a large number of codes is
+   given to indicate that the the voxel data should be interpreted as
+   being drawn from a given probability distribution.
+
+   VECTOR-VALUED DATASETS:
+   ----------------------
+   The 5th dimension of the dataset, if present (i.e., dim[0]=5 and
+   dim[5] > 1), contains multiple values (e.g., a vector) to be stored
+   at each spatiotemporal location.  For example, the header values
+    - dim[0] = 5
+    - dim[1] = 64
+    - dim[2] = 64
+    - dim[3] = 20
+    - dim[4] = 1     (indicates no time axis)
+    - dim[5] = 3
+    - datatype = DT_FLOAT
+    - intent_code = NIFTI_INTENT_VECTOR
+   mean that this dataset should be interpreted as a 3D volume (64x64x20),
+   with a 3-vector of floats defined at each point in the 3D grid.
+
+   A program reading a dataset with a 5th dimension may want to reformat
+   the image data to store each voxels' set of values together in a struct
+   or array.  This programming detail, however, is beyond the scope of the
+   NIFTI-1 file specification!  Uses of dimensions 6 and 7 are also not
+   specified here.
+
+   STATISTICAL PARAMETRIC DATASETS (i.e., SPMs):
+   --------------------------------------------
+   Values of intent_code from NIFTI_FIRST_STATCODE to NIFTI_LAST_STATCODE
+   (inclusive) indicate that the numbers in the dataset should be interpreted
+   as being drawn from a given distribution.  Most such distributions have
+   auxiliary parameters (e.g., NIFTI_INTENT_TTEST has 1 DOF parameter).
+
+   If the dataset DOES NOT have a 5th dimension, then the auxiliary parameters
+   are the same for each voxel, and are given in header fields intent_p1,
+   intent_p2, and intent_p3.
+
+   If the dataset DOES have a 5th dimension, then the auxiliary parameters
+   are different for each voxel.  For example, the header values
+    - dim[0] = 5
+    - dim[1] = 128
+    - dim[2] = 128
+    - dim[3] = 1      (indicates a single slice)
+    - dim[4] = 1      (indicates no time axis)
+    - dim[5] = 2
+    - datatype = DT_FLOAT
+    - intent_code = NIFTI_INTENT_TTEST
+   mean that this is a 2D dataset (128x128) of t-statistics, with the
+   t-statistic being in the first "plane" of data and the degrees-of-freedom
+   parameter being in the second "plane" of data.
+
+   If the dataset 5th dimension is used to store the voxel-wise statistical
+   parameters, then dim[5] must be 1 plus the number of parameters required
+   by that distribution (e.g., intent_code=NIFTI_INTENT_TTEST implies dim[5]
+   must be 2, as in the example just above).
+
+   Note: intent_code values 2..10 are compatible with AFNI 1.5x (which is
+   why there is no code with value=1, which is obsolescent in AFNI).
+
+   OTHER INTENTIONS:
+   ----------------
+   The purpose of the intent_* fields is to help interpret the values
+   stored in the dataset.  Some non-statistical values for intent_code
+   and conventions are provided for storing other complex data types.
+
+   The intent_name field provides space for a 15 character (plus 0 byte)
+   'name' string for the type of data stored. Examples:
+    - intent_code = NIFTI_INTENT_ESTIMATE; intent_name = "T1";
+       could be used to signify that the voxel values are estimates of the
+       NMR parameter T1.
+    - intent_code = NIFTI_INTENT_TTEST; intent_name = "House";
+       could be used to signify that the voxel values are t-statistics
+       for the significance of 'activation' response to a House stimulus.
+    - intent_code = NIFTI_INTENT_DISPVECT; intent_name = "ToMNI152";
+       could be used to signify that the voxel values are a displacement
+       vector that transforms each voxel (x,y,z) location to the
+       corresponding location in the MNI152 standard brain.
+    - intent_code = NIFTI_INTENT_SYMMATRIX; intent_name = "DTI";
+       could be used to signify that the voxel values comprise a diffusion
+       tensor image.
+
+   If no data name is implied or needed, intent_name[0] should be set to 0.
+-----------------------------------------------------------------------------*/
+
+ /*! default: no intention is indicated in the header. */
+
+#define NIFTI_INTENT_NONE        0
+
+    /*-------- These codes are for probability distributions ---------------*/
+    /* Most distributions have a number of parameters,
+       below denoted by p1, p2, and p3, and stored in
+        - intent_p1, intent_p2, intent_p3 if dataset doesn't have 5th dimension
+        - image data array                if dataset does have 5th dimension
+
+       Functions to compute with many of the distributions below can be found
+       in the CDF library from U Texas.
+
+       Formulas for and discussions of these distributions can be found in the
+       following books:
+
+        [U] Univariate Discrete Distributions,
+            NL Johnson, S Kotz, AW Kemp.
+
+        [C1] Continuous Univariate Distributions, vol. 1,
+             NL Johnson, S Kotz, N Balakrishnan.
+
+        [C2] Continuous Univariate Distributions, vol. 2,
+             NL Johnson, S Kotz, N Balakrishnan.                            */
+    /*----------------------------------------------------------------------*/
+
+  /*! [C2, chap 32] Correlation coefficient R (1 param):
+       p1 = degrees of freedom
+       R/sqrt(1-R*R) is t-distributed with p1 DOF. */
+
+#define NIFTI_INTENT_CORREL      2
+
+  /*! [C2, chap 28] Student t statistic (1 param): p1 = DOF. */
+
+#define NIFTI_INTENT_TTEST       3
+
+  /*! [C2, chap 27] Fisher F statistic (2 params):
+       p1 = numerator DOF, p2 = denominator DOF. */
+
+#define NIFTI_INTENT_FTEST       4
+
+  /*! [C1, chap 13] Standard normal (0 params): Density = N(0,1). */
+
+#define NIFTI_INTENT_ZSCORE      5
+
+  /*! [C1, chap 18] Chi-squared (1 param): p1 = DOF.
+      Density(x) proportional to exp(-x/2) * x^(p1/2-1). */
+
+#define NIFTI_INTENT_CHISQ       6
+
+  /*! [C2, chap 25] Beta distribution (2 params): p1=a, p2=b.
+      Density(x) proportional to x^(a-1) * (1-x)^(b-1). */
+
+#define NIFTI_INTENT_BETA        7
+
+  /*! [U, chap 3] Binomial distribution (2 params):
+       p1 = number of trials, p2 = probability per trial.
+      Prob(x) = (p1 choose x) * p2^x * (1-p2)^(p1-x), for x=0,1,...,p1. */
+
+#define NIFTI_INTENT_BINOM       8
+
+  /*! [C1, chap 17] Gamma distribution (2 params):
+       p1 = shape, p2 = scale.
+      Density(x) proportional to x^(p1-1) * exp(-p2*x). */
+
+#define NIFTI_INTENT_GAMMA       9
+
+  /*! [U, chap 4] Poisson distribution (1 param): p1 = mean.
+      Prob(x) = exp(-p1) * p1^x / x! , for x=0,1,2,.... */
+
+#define NIFTI_INTENT_POISSON    10
+
+  /*! [C1, chap 13] Normal distribution (2 params):
+       p1 = mean, p2 = standard deviation. */
+
+#define NIFTI_INTENT_NORMAL     11
+
+  /*! [C2, chap 30] Noncentral F statistic (3 params):
+       p1 = numerator DOF, p2 = denominator DOF,
+       p3 = numerator noncentrality parameter.  */
+
+#define NIFTI_INTENT_FTEST_NONC 12
+
+  /*! [C2, chap 29] Noncentral chi-squared statistic (2 params):
+       p1 = DOF, p2 = noncentrality parameter.     */
+
+#define NIFTI_INTENT_CHISQ_NONC 13
+
+  /*! [C2, chap 23] Logistic distribution (2 params):
+       p1 = location, p2 = scale.
+      Density(x) proportional to sech^2((x-p1)/(2*p2)). */
+
+#define NIFTI_INTENT_LOGISTIC   14
+
+  /*! [C2, chap 24] Laplace distribution (2 params):
+       p1 = location, p2 = scale.
+      Density(x) proportional to exp(-abs(x-p1)/p2). */
+
+#define NIFTI_INTENT_LAPLACE    15
+
+  /*! [C2, chap 26] Uniform distribution: p1 = lower end, p2 = upper end. */
+
+#define NIFTI_INTENT_UNIFORM    16
+
+  /*! [C2, chap 31] Noncentral t statistic (2 params):
+       p1 = DOF, p2 = noncentrality parameter. */
+
+#define NIFTI_INTENT_TTEST_NONC 17
+
+  /*! [C1, chap 21] Weibull distribution (3 params):
+       p1 = location, p2 = scale, p3 = power.
+      Density(x) proportional to
+       ((x-p1)/p2)^(p3-1) * exp(-((x-p1)/p2)^p3) for x > p1. */
+
+#define NIFTI_INTENT_WEIBULL    18
+
+  /*! [C1, chap 18] Chi distribution (1 param): p1 = DOF.
+      Density(x) proportional to x^(p1-1) * exp(-x^2/2) for x > 0.
+       p1 = 1 = 'half normal' distribution
+       p1 = 2 = Rayleigh distribution
+       p1 = 3 = Maxwell-Boltzmann distribution.                  */
+
+#define NIFTI_INTENT_CHI        19
+
+  /*! [C1, chap 15] Inverse Gaussian (2 params):
+       p1 = mu, p2 = lambda
+      Density(x) proportional to
+       exp(-p2*(x-p1)^2/(2*p1^2*x)) / x^3  for x > 0. */
+
+#define NIFTI_INTENT_INVGAUSS   20
+
+  /*! [C2, chap 22] Extreme value type I (2 params):
+       p1 = location, p2 = scale
+      cdf(x) = exp(-exp(-(x-p1)/p2)). */
+
+#define NIFTI_INTENT_EXTVAL     21
+
+  /*! Data is a 'p-value' (no params). */
+
+#define NIFTI_INTENT_PVAL       22
+
+  /*! Smallest intent_code that indicates a statistic. */
+
+#define NIFTI_FIRST_STATCODE     2
+
+  /*! Largest intent_code that indicates a statistic. */
+
+#define NIFTI_LAST_STATCODE     22
+
+ /*---------- these values for intent_code aren't for statistics ----------*/
+
+ /*! To signify that the value at each voxel is an estimate
+     of some parameter, set intent_code = NIFTI_INTENT_ESTIMATE.
+     The name of the parameter may be stored in intent_name.     */
+
+#define NIFTI_INTENT_ESTIMATE  1001
+
+ /*! To signify that the value at each voxel is an index into
+     some set of labels, set intent_code = NIFTI_INTENT_LABEL.
+     The filename with the labels may stored in aux_file.        */
+
+#define NIFTI_INTENT_LABEL     1002
+
+ /*! To signify that the value at each voxel is an index into the
+     NeuroNames labels set, set intent_code = NIFTI_INTENT_NEURONAME. */
+
+#define NIFTI_INTENT_NEURONAME 1003
+
+ /*! To store an M x N matrix at each voxel:
+       - dataset must have a 5th dimension (dim[0]=5 and dim[5]>1)
+       - intent_code must be NIFTI_INTENT_GENMATRIX
+       - dim[5] must be M*N
+       - intent_p1 must be M (in float format)
+       - intent_p2 must be N (ditto)
+       - the matrix values A[i][[j] are stored in row-order:
+         - A[0][0] A[0][1] ... A[0][N-1]
+         - A[1][0] A[1][1] ... A[1][N-1]
+         - etc., until
+         - A[M-1][0] A[M-1][1] ... A[M-1][N-1]        */
+
+#define NIFTI_INTENT_GENMATRIX 1004
+
+ /*! To store an NxN symmetric matrix at each voxel:
+       - dataset must have a 5th dimension
+       - intent_code must be NIFTI_INTENT_SYMMATRIX
+       - dim[5] must be N*(N+1)/2
+       - intent_p1 must be N (in float format)
+       - the matrix values A[i][[j] are stored in row-order:
+         - A[0][0]
+         - A[1][0] A[1][1]
+         - A[2][0] A[2][1] A[2][2]
+         - etc.: row-by-row                           */
+
+#define NIFTI_INTENT_SYMMATRIX 1005
+
+ /*! To signify that the vector value at each voxel is to be taken
+     as a displacement field or vector:
+       - dataset must have a 5th dimension
+       - intent_code must be NIFTI_INTENT_DISPVECT
+       - dim[5] must be the dimensionality of the displacment
+         vector (e.g., 3 for spatial displacement, 2 for in-plane) */
+
+#define NIFTI_INTENT_DISPVECT  1006   /* specifically for displacements */
+#define NIFTI_INTENT_VECTOR    1007   /* for any other type of vector */
+
+ /*! To signify that the vector value at each voxel is really a
+     spatial coordinate (e.g., the vertices or nodes of a surface mesh):
+       - dataset must have a 5th dimension
+       - intent_code must be NIFTI_INTENT_POINTSET
+       - dim[0] = 5
+       - dim[1] = number of points
+       - dim[2] = dim[3] = dim[4] = 1
+       - dim[5] must be the dimensionality of space (e.g., 3 => 3D space).
+       - intent_name may describe the object these points come from
+         (e.g., "pial", "gray/white" , "EEG", "MEG").                   */
+
+#define NIFTI_INTENT_POINTSET  1008
+
+ /*! To signify that the vector value at each voxel is really a triple
+     of indexes (e.g., forming a triangle) from a pointset dataset:
+       - dataset must have a 5th dimension
+       - intent_code must be NIFTI_INTENT_TRIANGLE
+       - dim[0] = 5
+       - dim[1] = number of triangles
+       - dim[2] = dim[3] = dim[4] = 1
+       - dim[5] = 3
+       - datatype should be an integer type (preferably DT_INT32)
+       - the data values are indexes (0,1,...) into a pointset dataset. */
+
+#define NIFTI_INTENT_TRIANGLE  1009
+
+ /*! To signify that the vector value at each voxel is a quaternion:
+       - dataset must have a 5th dimension
+       - intent_code must be NIFTI_INTENT_QUATERNION
+       - dim[0] = 5
+       - dim[5] = 4
+       - datatype should be a floating point type     */
+
+#define NIFTI_INTENT_QUATERNION 1010
+
+/*---------------------------------------------------------------------------*/
+/* 3D IMAGE (VOLUME) ORIENTATION AND LOCATION IN SPACE:
+   ---------------------------------------------------
+   There are 3 different methods by which continuous coordinates can
+   attached to voxels.  The discussion below emphasizes 3D volumes, and
+   the continuous coordinates are referred to as (x,y,z).  The voxel
+   index coordinates (i.e., the array indexes) are referred to as (i,j,k),
+   with valid ranges:
+     i = 0 .. dim[1]-1
+     j = 0 .. dim[2]-1  (if dim[0] >= 2)
+     k = 0 .. dim[3]-1  (if dim[0] >= 3)
+   The (x,y,z) coordinates refer to the CENTER of a voxel.  In methods
+   2 and 3, the (x,y,z) axes refer to a subject-based coordinate system,
+   with
+     +x = Right  +y = Anterior  +z = Superior.
+   This is a right-handed coordinate system.  However, the exact direction
+   these axes point with respect to the subject depends on qform_code
+   (Method 2) and sform_code (Method 3).
+
+   N.B.: The i index varies most rapidly, j index next, k index slowest.
+    Thus, voxel (i,j,k) is stored starting at location
+      (i + j*dim[1] + k*dim[1]*dim[2]) * (bitpix/8)
+    into the dataset array.
+
+   N.B.: The ANALYZE 7.5 coordinate system is
+      +x = Left  +y = Anterior  +z = Superior
+    which is a left-handed coordinate system.  This backwardness is
+    too difficult to tolerate, so this NIFTI-1 standard specifies the
+    coordinate order which is most common in functional neuroimaging.
+
+   N.B.: The 3 methods below all give the locations of the voxel centers
+    in the (x,y,z) coordinate system.  In many cases, programs will wish
+    to display image data on some other grid.  In such a case, the program
+    will need to convert its desired (x,y,z) values into (i,j,k) values
+    in order to extract (or interpolate) the image data.  This operation
+    would be done with the inverse transformation to those described below.
+
+   N.B.: Method 2 uses a factor 'qfac' which is either -1 or 1; qfac is
+    stored in the otherwise unused pixdim[0].  If pixdim[0]=0.0 (which
+    should not occur), we take qfac=1.  Of course, pixdim[0] is only used
+    when reading a NIFTI-1 header, not when reading an ANALYZE 7.5 header.
+
+   N.B.: The units of (x,y,z) can be specified using the xyzt_units field.
+
+   METHOD 1 (the "old" way, used only when qform_code = 0):
+   -------------------------------------------------------
+   The coordinate mapping from (i,j,k) to (x,y,z) is the ANALYZE
+   7.5 way.  This is a simple scaling relationship:
+
+     x = pixdim[1] * i
+     y = pixdim[2] * j
+     z = pixdim[3] * k
+
+   No particular spatial orientation is attached to these (x,y,z)
+   coordinates.  (NIFTI-1 does not have the ANALYZE 7.5 orient field,
+   which is not general and is often not set properly.)  This method
+   is not recommended, and is present mainly for compatibility with
+   ANALYZE 7.5 files.
+
+   METHOD 2 (used when qform_code > 0, which should be the "normal case):
+   ---------------------------------------------------------------------
+   The (x,y,z) coordinates are given by the pixdim[] scales, a rotation
+   matrix, and a shift.  This method is intended to represent
+   "scanner-anatomical" coordinates, which are often embedded in the
+   image header (e.g., DICOM fields (0020,0032), (0020,0037), (0028,0030),
+   and (0018,0050)), and represent the nominal orientation and location of
+   the data.  This method can also be used to represent "aligned"
+   coordinates, which would typically result from some post-acquisition
+   alignment of the volume to a standard orientation (e.g., the same
+   subject on another day, or a rigid rotation to true anatomical
+   orientation from the tilted position of the subject in the scanner).
+   The formula for (x,y,z) in terms of header parameters and (i,j,k) is:
+
+     [ x ]   [ R11 R12 R13 ] [        pixdim[1] * i ]   [ qoffset_x ]
+     [ y ] = [ R21 R22 R23 ] [        pixdim[2] * j ] + [ qoffset_y ]
+     [ z ]   [ R31 R32 R33 ] [ qfac * pixdim[3] * k ]   [ qoffset_z ]
+
+   The qoffset_* shifts are in the NIFTI-1 header.  Note that the center
+   of the (i,j,k)=(0,0,0) voxel (first value in the dataset array) is
+   just (x,y,z)=(qoffset_x,qoffset_y,qoffset_z).
+
+   The rotation matrix R is calculated from the quatern_* parameters.
+   This calculation is described below.
+
+   The scaling factor qfac is either 1 or -1.  The rotation matrix R
+   defined by the quaternion parameters is "proper" (has determinant 1).
+   This may not fit the needs of the data; for example, if the image
+   grid is
+     i increases from Left-to-Right
+     j increases from Anterior-to-Posterior
+     k increases from Inferior-to-Superior
+   Then (i,j,k) is a left-handed triple.  In this example, if qfac=1,
+   the R matrix would have to be
+
+     [  1   0   0 ]
+     [  0  -1   0 ]  which is "improper" (determinant = -1).
+     [  0   0   1 ]
+
+   If we set qfac=-1, then the R matrix would be
+
+     [  1   0   0 ]
+     [  0  -1   0 ]  which is proper.
+     [  0   0  -1 ]
+
+   This R matrix is represented by quaternion [a,b,c,d] = [0,1,0,0]
+   (which encodes a 180 degree rotation about the x-axis).
+
+   METHOD 3 (used when sform_code > 0):
+   -----------------------------------
+   The (x,y,z) coordinates are given by a general affine transformation
+   of the (i,j,k) indexes:
+
+     x = srow_x[0] * i + srow_x[1] * j + srow_x[2] * k + srow_x[3]
+     y = srow_y[0] * i + srow_y[1] * j + srow_y[2] * k + srow_y[3]
+     z = srow_z[0] * i + srow_z[1] * j + srow_z[2] * k + srow_z[3]
+
+   The srow_* vectors are in the NIFTI_1 header.  Note that no use is
+   made of pixdim[] in this method.
+
+   WHY 3 METHODS?
+   --------------
+   Method 1 is provided only for backwards compatibility.  The intention
+   is that Method 2 (qform_code > 0) represents the nominal voxel locations
+   as reported by the scanner, or as rotated to some fiducial orientation and
+   location.  Method 3, if present (sform_code > 0), is to be used to give
+   the location of the voxels in some standard space.  The sform_code
+   indicates which standard space is present.  Both methods 2 and 3 can be
+   present, and be useful in different contexts (method 2 for displaying the
+   data on its original grid; method 3 for displaying it on a standard grid).
+
+   In this scheme, a dataset would originally be set up so that the
+   Method 2 coordinates represent what the scanner reported.  Later,
+   a registration to some standard space can be computed and inserted
+   in the header.  Image display software can use either transform,
+   depending on its purposes and needs.
+
+   In Method 2, the origin of coordinates would generally be whatever
+   the scanner origin is; for example, in MRI, (0,0,0) is the center
+   of the gradient coil.
+
+   In Method 3, the origin of coordinates would depend on the value
+   of sform_code; for example, for the Talairach coordinate system,
+   (0,0,0) corresponds to the Anterior Commissure.
+
+   QUATERNION REPRESENTATION OF ROTATION MATRIX (METHOD 2)
+   -------------------------------------------------------
+   The orientation of the (x,y,z) axes relative to the (i,j,k) axes
+   in 3D space is specified using a unit quaternion [a,b,c,d], where
+   a*a+b*b+c*c+d*d=1.  The (b,c,d) values are all that is needed, since
+   we require that a = sqrt(1.0-b*b+c*c+d*d) be nonnegative.  The (b,c,d)
+   values are stored in the (quatern_b,quatern_c,quatern_d) fields.
+
+   The quaternion representation is chosen for its compactness in
+   representing rotations. The (proper) 3x3 rotation matrix that
+   corresponds to [a,b,c,d] is
+
+         [ a*a+b*b-c*c-d*d   2*b*c-2*a*d       2*b*d+2*a*c     ]
+     R = [ 2*b*c+2*a*d       a*a+c*c-b*b-d*d   2*c*d-2*a*b     ]
+         [ 2*b*d-2*a*c       2*c*d+2*a*b       a*a+d*d-c*c-b*b ]
+
+         [ R11               R12               R13             ]
+       = [ R21               R22               R23             ]
+         [ R31               R32               R33             ]
+
+   If (p,q,r) is a unit 3-vector, then rotation of angle h about that
+   direction is represented by the quaternion
+
+     [a,b,c,d] = [cos(h/2), p*sin(h/2), q*sin(h/2), r*sin(h/2)].
+
+   Requiring a >= 0 is equivalent to requiring -Pi <= h <= Pi.  (Note that
+   [-a,-b,-c,-d] represents the same rotation as [a,b,c,d]; there are 2
+   quaternions that can be used to represent a given rotation matrix R.)
+   To rotate a 3-vector (x,y,z) using quaternions, we compute the
+   quaternion product
+
+     [0,x',y',z'] = [a,b,c,d] * [0,x,y,z] * [a,-b,-c,-d]
+
+   which is equivalent to the matrix-vector multiply
+
+     [ x' ]     [ x ]
+     [ y' ] = R [ y ]   (equivalence depends on a*a+b*b+c*c+d*d=1)
+     [ z' ]     [ z ]
+
+   Multiplication of 2 quaternions is defined by the following:
+
+     [a,b,c,d] = a*1 + b*I + c*J + d*K
+     where
+       I*I = J*J = K*K = -1 (I,J,K are square roots of -1)
+       I*J =  K  J*K =  I  K*I =  J
+       J*I = -K  K*J = -I  I*K = -J  (not commutative!)
+     For example
+       [a,b,0,0] * [0,0,0,1] = [0,-b,0,a]
+     since this expands to
+       (a+b*I)*(K) = (a*K+b*I*K) = (a*K-b*J).
+
+   The above formula shows how to go from quaternion (b,c,d) to
+   rotation matrix and direction cosines.  Conversely, given R,
+   we can compute the fields for the NIFTI-1 header by
+
+     a = 0.5  * sqrt(1+R11+R22+R33)    (not stored)
+     b = 0.25 * (R32-R23) / a       => quatern_b
+     c = 0.25 * (R13-R31) / a       => quatern_c
+     d = 0.25 * (R21-R12) / a       => quatern_d
+
+   If a=0 (a 180 degree rotation), alternative formulas are needed.
+   See the nifti1_io.c function mat44_to_quatern() for an implementation
+   of the various cases in converting R to [a,b,c,d].
+
+   Note that R-transpose (= R-inverse) would lead to the quaternion
+   [a,-b,-c,-d].
+
+   The choice to specify the qoffset_x (etc.) values in the final
+   coordinate system is partly to make it easy to convert DICOM images to
+   this format.  The DICOM attribute "Image Position (Patient)" (0020,0032)
+   stores the (Xd,Yd,Zd) coordinates of the center of the first voxel.
+   Here, (Xd,Yd,Zd) refer to DICOM coordinates, and Xd=-x, Yd=-y, Zd=z,
+   where (x,y,z) refers to the NIFTI coordinate system discussed above.
+   (i.e., DICOM +Xd is Left, +Yd is Posterior, +Zd is Superior,
+        whereas +x is Right, +y is Anterior  , +z is Superior. )
+   Thus, if the (0020,0032) DICOM attribute is extracted into (px,py,pz), then
+     qoffset_x = -px   qoffset_y = -py   qoffset_z = pz
+   is a reasonable setting when qform_code=NIFTI_XFORM_SCANNER_ANAT.
+
+   That is, DICOM's coordinate system is 180 degrees rotated about the z-axis
+   from the neuroscience/NIFTI coordinate system.  To transform between DICOM
+   and NIFTI, you just have to negate the x- and y-coordinates.
+
+   The DICOM attribute (0020,0037) "Image Orientation (Patient)" gives the
+   orientation of the x- and y-axes of the image data in terms of 2 3-vectors.
+   The first vector is a unit vector along the x-axis, and the second is
+   along the y-axis.  If the (0020,0037) attribute is extracted into the
+   value (xa,xb,xc,ya,yb,yc), then the first two columns of the R matrix
+   would be
+              [ -xa  -ya ]
+              [ -xb  -yb ]
+              [  xc   yc ]
+   The negations are because DICOM's x- and y-axes are reversed relative
+   to NIFTI's.  The third column of the R matrix gives the direction of
+   displacement (relative to the subject) along the slice-wise direction.
+   This orientation is not encoded in the DICOM standard in a simple way;
+   DICOM is mostly concerned with 2D images.  The third column of R will be
+   either the cross-product of the first 2 columns or its negative.  It is
+   possible to infer the sign of the 3rd column by examining the coordinates
+   in DICOM attribute (0020,0032) "Image Position (Patient)" for successive
+   slices.  However, this method occasionally fails for reasons that I
+   (RW Cox) do not understand.
+-----------------------------------------------------------------------------*/
+
+   /* [qs]form_code value:  */      /* x,y,z coordinate system refers to:    */
+   /*-----------------------*/      /*---------------------------------------*/
+
+                                    /*! Arbitrary coordinates (Method 1). */
+
+#define NIFTI_XFORM_UNKNOWN      0
+
+                                    /*! Scanner-based anatomical coordinates */
+
+#define NIFTI_XFORM_SCANNER_ANAT 1
+
+                                    /*! Coordinates aligned to another file's,
+                                        or to anatomical "truth".            */
+
+#define NIFTI_XFORM_ALIGNED_ANAT 2
+
+                                    /*! Coordinates aligned to Talairach-
+                                        Tournoux Atlas; (0,0,0)=AC, etc. */
+
+#define NIFTI_XFORM_TALAIRACH    3
+
+                                    /*! MNI 152 normalized coordinates. */
+
+#define NIFTI_XFORM_MNI_152      4
+
+/*---------------------------------------------------------------------------*/
+/* UNITS OF SPATIAL AND TEMPORAL DIMENSIONS:
+   ----------------------------------------
+   The codes below can be used in xyzt_units to indicate the units of pixdim.
+   As noted earlier, dimensions 1,2,3 are for x,y,z; dimension 4 is for
+   time (t).
+    - If dim[4]=1 or dim[0] < 4, there is no time axis.
+    - A single time series (no space) would be specified with
+      - dim[0] = 4 (for scalar data) or dim[0] = 5 (for vector data)
+      - dim[1] = dim[2] = dim[3] = 1
+      - dim[4] = number of time points
+      - pixdim[4] = time step
+      - xyzt_units indicates units of pixdim[4]
+      - dim[5] = number of values stored at each time point
+
+   Bits 0..2 of xyzt_units specify the units of pixdim[1..3]
+    (e.g., spatial units are values 1..7).
+   Bits 3..5 of xyzt_units specify the units of pixdim[4]
+    (e.g., temporal units are multiples of 8).
+
+   This compression of 2 distinct concepts into 1 byte is due to the
+   limited space available in the 348 byte ANALYZE 7.5 header.  The
+   macros XYZT_TO_SPACE and XYZT_TO_TIME can be used to mask off the
+   undesired bits from the xyzt_units fields, leaving "pure" space
+   and time codes.  Inversely, the macro SPACE_TIME_TO_XYZT can be
+   used to assemble a space code (0,1,2,...,7) with a time code
+   (0,8,16,32,...,56) into the combined value for xyzt_units.
+
+   Note that codes are provided to indicate the "time" axis units are
+   actually frequency in Hertz (_HZ) or in part-per-million (_PPM).
+
+   The toffset field can be used to indicate a nonzero start point for
+   the time axis.  That is, time point #m is at t=toffset+m*pixdim[4]
+   for m=0..dim[4]-1.
+-----------------------------------------------------------------------------*/
+
+                               /*! NIFTI code for unspecified units. */
+#define NIFTI_UNITS_UNKNOWN 0
+
+                               /** Space codes are multiples of 1. **/
+                               /*! NIFTI code for meters. */
+#define NIFTI_UNITS_METER   1
+                               /*! NIFTI code for millimeters. */
+#define NIFTI_UNITS_MM      2
+                               /*! NIFTI code for micrometers. */
+#define NIFTI_UNITS_MICRON  3
+
+                               /** Time codes are multiples of 8. **/
+                               /*! NIFTI code for seconds. */
+#define NIFTI_UNITS_SEC     8
+                               /*! NIFTI code for milliseconds. */
+#define NIFTI_UNITS_MSEC   16
+                               /*! NIFTI code for microseconds. */
+#define NIFTI_UNITS_USEC   24
+
+                               /*** These units are for spectral data: ***/
+                               /*! NIFTI code for Hertz. */
+#define NIFTI_UNITS_HZ     32
+                               /*! NIFTI code for ppm. */
+#define NIFTI_UNITS_PPM    40
+
+#undef  XYZT_TO_SPACE
+#undef  XYZT_TO_TIME
+#define XYZT_TO_SPACE(xyzt)       ( (xyzt) & 0x07 )
+#define XYZT_TO_TIME(xyzt)        ( (xyzt) & 0x38 )
+
+#undef  SPACE_TIME_TO_XYZT
+#define SPACE_TIME_TO_XYZT(ss,tt) (  (((char)(ss)) & 0x07)   \
+                                   | (((char)(tt)) & 0x38) )
+
+/*---------------------------------------------------------------------------*/
+/* MRI-SPECIFIC SPATIAL AND TEMPORAL INFORMATION:
+   ---------------------------------------------
+   A few fields are provided to store some extra information
+   that is sometimes important when storing the image data
+   from an FMRI time series experiment.  (After processing such
+   data into statistical images, these fields are not likely
+   to be useful.)
+
+  { freq_dim  } = These fields encode which spatial dimension (1,2, or 3)
+  { phase_dim } = corresponds to which acquisition dimension for MRI data.
+  { slice_dim } =
+    Examples:
+      Rectangular scan multi-slice EPI:
+        freq_dim = 1  phase_dim = 2  slice_dim = 3  (or some permutation)
+      Spiral scan multi-slice EPI:
+        freq_dim = phase_dim = 0  slice_dim = 3
+        since the concepts of frequency- and phase-encoding directions
+        don't apply to spiral scan
+
+    slice_duration = If this is positive, AND if slice_dim is nonzero,
+                     indicates the amount of time used to acquire 1 slice.
+                     slice_duration*dim[slice_dim] can be less than pixdim[4]
+                     with a clustered acquisition method, for example.
+
+    slice_code = If this is nonzero, AND if slice_dim is nonzero, AND
+                 if slice_duration is positive, indicates the timing
+                 pattern of the slice acquisition.  The following codes
+                 are defined:
+                   NIFTI_SLICE_SEQ_INC
+                   NIFTI_SLICE_SEQ_DEC
+                   NIFTI_SLICE_ALT_INC
+                   NIFTI_SLICE_ALT_DEC
+  { slice_start } = Indicates the start and end of the slice acquisition
+  { slice_end   } = pattern, when slice_code is nonzero.  These values
+                    are present to allow for the possible addition of
+                    "padded" slices at either end of the volume, which
+                    don't fit into the slice timing pattern.  If there
+                    are no padding slices, then slice_start=0 and
+                    slice_end=dim[slice_dim]-1 are the correct values.
+                    For these values to be meaningful, slice_start must
+                    be non-negative and slice_end must be greater than
+                    slice_start.
+
+  The following table indicates the slice timing pattern, relative to
+  time=0 for the first slice acquired, for some sample cases.  Here,
+  dim[slice_dim]=7 (there are 7 slices, labeled 0..6), slice_duration=0.1,
+  and slice_start=1, slice_end=5 (1 padded slice on each end).
+
+    slice
+    index   SEQ_INC SEQ_DEC ALT_INC ALT_DEC
+      6  --   n/a     n/a     n/a     n/a     n/a = not applicable
+      5  --   0.4     0.0     0.2     0.0           (slice time offset
+      4  --   0.3     0.1     0.4     0.3            doesn't apply to
+      3  --   0.2     0.2     0.1     0.1            slices outside range
+      2  --   0.1     0.3     0.3     0.4            slice_start..slice_end)
+      1  --   0.0     0.4     0.0     0.2
+      0  --   n/a     n/a     n/a     n/a
+
+  The fields freq_dim, phase_dim, slice_dim are all squished into the single
+  byte field dim_info (2 bits each, since the values for each field are
+  limited to the range 0..3).  This unpleasantness is due to lack of space
+  in the 348 byte allowance.
+
+  The macros DIM_INFO_TO_FREQ_DIM, DIM_INFO_TO_PHASE_DIM, and
+  DIM_INFO_TO_SLICE_DIM can be used to extract these values from the
+  dim_info byte.
+
+  The macro FPS_INTO_DIM_INFO can be used to put these 3 values
+  into the dim_info byte.
+-----------------------------------------------------------------------------*/
+
+#undef  DIM_INFO_TO_FREQ_DIM
+#undef  DIM_INFO_TO_PHASE_DIM
+#undef  DIM_INFO_TO_SLICE_DIM
+
+#define DIM_INFO_TO_FREQ_DIM(di)   ( ((di)     ) & 0x03 )
+#define DIM_INFO_TO_PHASE_DIM(di)  ( ((di) >> 2) & 0x03 )
+#define DIM_INFO_TO_SLICE_DIM(di)  ( ((di) >> 4) & 0x03 )
+
+#undef  FPS_INTO_DIM_INFO
+#define FPS_INTO_DIM_INFO(fd,pd,sd) ( ( ( ((char)(fd)) & 0x03)      ) |  \
+                                      ( ( ((char)(pd)) & 0x03) << 2 ) |  \
+                                      ( ( ((char)(sd)) & 0x03) << 4 )  )
+
+#define NIFTI_SLICE_SEQ_INC  1
+#define NIFTI_SLICE_SEQ_DEC  2
+#define NIFTI_SLICE_ALT_INC  3
+#define NIFTI_SLICE_ALT_DEC  4
+
+/*---------------------------------------------------------------------------*/
+/* UNUSED FIELDS:
+   -------------
+   Some of the ANALYZE 7.5 fields marked as ++UNUSED++ may need to be set
+   to particular values for compatibility with other programs.  The issue
+   of interoperability of ANALYZE 7.5 files is a murky one -- not all
+   programs require exactly the same set of fields.  (Unobscuring this
+   murkiness is a principal motivation behind NIFTI-1.)
+
+   Some of the fields that may need to be set for other (non-NIFTI aware)
+   software to be happy are:
+
+     extents    dbh.h says this should be 16384
+     regular    dbh.h says this should be the character 'r'
+     glmin,   } dbh.h says these values should be the min and max voxel
+      glmax   }  values for the entire dataset
+
+   It is best to initialize ALL fields in the NIFTI-1 header to 0
+   (e.g., with calloc()), then fill in what is needed.
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* MISCELLANEOUS C MACROS
+-----------------------------------------------------------------------------*/
+
+/*.................*/
+/*! Given a nifti_1_header struct, check if it has a good magic number.
+    Returns NIFTI version number (1..9) if magic is good, 0 if it is not. */
+
+#define NIFTI_VERSION(h)                               \
+ ( ( (h).magic[0]=='n' && (h).magic[3]=='\0'    &&     \
+     ( (h).magic[1]=='i' || (h).magic[1]=='+' ) &&     \
+     ( (h).magic[2]>='1' && (h).magic[2]<='9' )   )    \
+ ? (h).magic[2]-'0' : 0 )
+
+/*.................*/
+/*! Check if a nifti_1_header struct says if the data is stored in the
+    same file or in a separate file.  Returns 1 if the data is in the same
+    file as the header, 0 if it is not.                                   */
+
+#define NIFTI_ONEFILE(h) ( (h).magic[1] == '+' )
+
+/*.................*/
+/*! Check if a nifti_1_header struct needs to be byte swapped.
+    Returns 1 if it needs to be swapped, 0 if it does not.     */
+
+#define NIFTI_NEEDS_SWAP(h) ( (h).dim[0] < 0 || (h).dim[0] > 7 )
+
+/*.................*/
+/*! Check if a nifti_1_header struct contains a 5th (vector) dimension.
+    Returns size of 5th dimension if > 1, returns 0 otherwise.         */
+
+#define NIFTI_5TH_DIM(h) ( ((h).dim[0]>4 && (h).dim[5]>1) ? (h).dim[5] : 0 )
+
+/*****************************************************************************/
+
+/*=================*/
+#ifdef  __cplusplus
+}
+#endif
+/*=================*/
+
+#endif /* _NIFTI_HEADER_ */
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/nifti_stats.c b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/nifti_stats.c
new file mode 100644
index 0000000000000000000000000000000000000000..e1c276af529497d0ed1ed3baf5858c78ee6a1012
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/nifti_stats.c
@@ -0,0 +1,11282 @@
+#ifndef lint
+static char sccsid[] = "%W% R.W. Cox %E%";
+#endif
+ /************************************************************************/
+ /**  Functions to compute cumulative distributions and their inverses  **/
+ /**  for the NIfTI-1 statistical types.  Much of this code is taken    **/
+ /**  from other sources.  In particular, the cdflib functions by       **/
+ /**  Brown and Lovato make up the bulk of this file.  That code        **/
+ /**  was placed in the public domain.  The code by K. Krishnamoorthy   **/
+ /**  is also released for unrestricted use.  Finally, the other parts  **/
+ /**  of this file (by RW Cox) are released to the public domain.       **/
+ /**                                                                    **/
+ /**  Most of this file comprises a set of "static" functions, to be    **/
+ /**  called by the user-level functions at the very end of the file.   **/
+ /**  At the end of the file is a simple main program to drive these    **/
+ /**  functions.                                                        **/
+ /**                                                                    **/
+ /**  To find the user-level functions, search forward for the string   **/
+ /**  "nifti_", which will be at about line 11000.                      **/
+ /************************************************************************/
+ /*****==============================================================*****/
+ /***** Neither the National Institutes of Health (NIH), the DFWG,   *****/
+ /***** nor any of the members or employees of these institutions    *****/
+ /***** imply any warranty of usefulness of this material for any    *****/
+ /***** purpose, and do not assume any liability for damages,        *****/
+ /***** incidental or otherwise, caused by any use of this document. *****/
+ /***** If these conditions are not acceptable, do not use this!     *****/
+ /*****==============================================================*****/
+ /************************************************************************/
+
+ /*.......................................................................
+    To compile with gcc, for example:
+
+    gcc -O3 -ffast-math -o nifti_stats nifti_stats.c -lm
+ ........................................................................*/
+
+
+/*
+ * niftilib $Id: nifti_stats.c,v 1.1 2012/03/22 18:36:33 fissell Exp $
+ */
+
+#include "nifti1.h"   /* for the NIFTI_INTENT_* constants */
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+ /************************************************************************/
+ /************ Include all the cdflib functions here and now *************/
+ /************     [about 9900 lines of code below here]     *************/
+ /************************************************************************/
+
+/** Prototypes for cdflib functions **/
+
+static double algdiv(double*,double*);
+static double alngam(double*);
+static double alnrel(double*);
+static double apser(double*,double*,double*,double*);
+static double basym(double*,double*,double*,double*);
+static double bcorr(double*,double*);
+static double betaln(double*,double*);
+static double bfrac(double*,double*,double*,double*,double*,double*);
+static void bgrat(double*,double*,double*,double*,double*,double*,int*i);
+static double bpser(double*,double*,double*,double*);
+static void bratio(double*,double*,double*,double*,double*,double*,int*);
+static double brcmp1(int*,double*,double*,double*,double*);
+static double brcomp(double*,double*,double*,double*);
+static double bup(double*,double*,double*,double*,int*,double*);
+static void cdfbet(int*,double*,double*,double*,double*,double*,double*,
+                   int*,double*);
+static void cdfbin(int*,double*,double*,double*,double*,double*,double*,
+                   int*,double*);
+static void cdfchi(int*,double*,double*,double*,double*,int*,double*);
+static void cdfchn(int*,double*,double*,double*,double*,double*,int*,double*);
+static void cdff(int*,double*,double*,double*,double*,double*,int*,double*);
+static void cdffnc(int*,double*,double*,double*,double*,double*,double*,
+                   int*s,double*);
+static void cdfgam(int*,double*,double*,double*,double*,double*,int*,double*);
+static void cdfnbn(int*,double*,double*,double*,double*,double*,double*,
+                   int*,double*);
+static void cdfnor(int*,double*,double*,double*,double*,double*,int*,double*);
+static void cdfpoi(int*,double*,double*,double*,double*,int*,double*);
+static void cdft(int*,double*,double*,double*,double*,int*,double*);
+static void cumbet(double*,double*,double*,double*,double*,double*);
+static void cumbin(double*,double*,double*,double*,double*,double*);
+static void cumchi(double*,double*,double*,double*);
+static void cumchn(double*,double*,double*,double*,double*);
+static void cumf(double*,double*,double*,double*,double*);
+static void cumfnc(double*,double*,double*,double*,double*,double*);
+static void cumgam(double*,double*,double*,double*);
+static void cumnbn(double*,double*,double*,double*,double*,double*);
+static void cumnor(double*,double*,double*);
+static void cumpoi(double*,double*,double*,double*);
+static void cumt(double*,double*,double*,double*);
+static double dbetrm(double*,double*);
+static double devlpl(double [],int*,double*);
+static double dexpm1(double*);
+static double dinvnr(double *p,double *q);
+static void E0000(int,int*,double*,double*,unsigned long*,
+                  unsigned long*,double*,double*,double*,
+                  double*,double*,double*,double*);
+static void dinvr(int*,double*,double*,unsigned long*,unsigned long*);
+static void dstinv(double*,double*,double*,double*,double*,double*,
+                   double*);
+static double dlanor(double*);
+static double dln1mx(double*);
+static double dln1px(double*);
+static double dlnbet(double*,double*);
+static double dlngam(double*);
+static double dstrem(double*);
+static double dt1(double*,double*,double*);
+static void E0001(int,int*,double*,double*,double*,double*,
+                  unsigned long*,unsigned long*,double*,double*,
+                  double*,double*);
+static void dzror(int*,double*,double*,double*,double *,
+                  unsigned long*,unsigned long*);
+static void dstzr(double *zxlo,double *zxhi,double *zabstl,double *zreltl);
+static double erf1(double*);
+static double erfc1(int*,double*);
+static double esum(int*,double*);
+static double exparg(int*);
+static double fpser(double*,double*,double*,double*);
+static double gam1(double*);
+static void gaminv(double*,double*,double*,double*,double*,int*);
+static double gamln(double*);
+static double gamln1(double*);
+static double Xgamm(double*);
+static void grat1(double*,double*,double*,double*,double*,double*);
+static void gratio(double*,double*,double*,double*,int*);
+static double gsumln(double*,double*);
+static double psi(double*);
+static double rcomp(double*,double*);
+static double rexp(double*);
+static double rlog(double*);
+static double rlog1(double*);
+static double spmpar(int*);
+static double stvaln(double*);
+static double fifdint(double);
+static double fifdmax1(double,double);
+static double fifdmin1(double,double);
+static double fifdsign(double,double);
+static long fifidint(double);
+static long fifmod(long,long);
+static void ftnstop(char*);
+static int ipmpar(int*);
+
+/***=====================================================================***/
+static double algdiv(double *a,double *b)
+/*
+-----------------------------------------------------------------------
+
+     COMPUTATION OF LN(GAMMA(B)/GAMMA(A+B)) WHEN B .GE. 8
+
+                         --------
+
+     IN THIS ALGORITHM, DEL(X) IS THE FUNCTION DEFINED BY
+     LN(GAMMA(X)) = (X - 0.5)*LN(X) - X + 0.5*LN(2*PI) + DEL(X).
+
+-----------------------------------------------------------------------
+*/
+{
+static double c0 = .833333333333333e-01;
+static double c1 = -.277777777760991e-02;
+static double c2 = .793650666825390e-03;
+static double c3 = -.595202931351870e-03;
+static double c4 = .837308034031215e-03;
+static double c5 = -.165322962780713e-02;
+static double algdiv,c,d,h,s11,s3,s5,s7,s9,t,u,v,w,x,x2,T1;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    if(*a <= *b) goto S10;
+    h = *b/ *a;
+    c = 1.0e0/(1.0e0+h);
+    x = h/(1.0e0+h);
+    d = *a+(*b-0.5e0);
+    goto S20;
+S10:
+    h = *a/ *b;
+    c = h/(1.0e0+h);
+    x = 1.0e0/(1.0e0+h);
+    d = *b+(*a-0.5e0);
+S20:
+/*
+                SET SN = (1 - X**N)/(1 - X)
+*/
+    x2 = x*x;
+    s3 = 1.0e0+(x+x2);
+    s5 = 1.0e0+(x+x2*s3);
+    s7 = 1.0e0+(x+x2*s5);
+    s9 = 1.0e0+(x+x2*s7);
+    s11 = 1.0e0+(x+x2*s9);
+/*
+                SET W = DEL(B) - DEL(A + B)
+*/
+    t = pow(1.0e0/ *b,2.0);
+    w = ((((c5*s11*t+c4*s9)*t+c3*s7)*t+c2*s5)*t+c1*s3)*t+c0;
+    w *= (c/ *b);
+/*
+                    COMBINE THE RESULTS
+*/
+    T1 = *a/ *b;
+    u = d*alnrel(&T1);
+    v = *a*(log(*b)-1.0e0);
+    if(u <= v) goto S30;
+    algdiv = w-v-u;
+    return algdiv;
+S30:
+    algdiv = w-u-v;
+    return algdiv;
+} /* END */
+
+/***=====================================================================***/
+static double alngam(double *x)
+/*
+**********************************************************************
+
+     double alngam(double *x)
+                 double precision LN of the GAMma function
+
+
+                              Function
+
+
+     Returns the natural logarithm of GAMMA(X).
+
+
+                              Arguments
+
+
+     X --> value at which scaled log gamma is to be returned
+                    X is DOUBLE PRECISION
+
+
+                              Method
+
+
+     If X .le. 6.0, then use recursion to get X below 3
+     then apply rational approximation number 5236 of
+     Hart et al, Computer Approximations, John Wiley and
+     Sons, NY, 1968.
+
+     If X .gt. 6.0, then use recursion to get X to at least 12 and
+     then use formula 5423 of the same source.
+
+**********************************************************************
+*/
+{
+#define hln2pi 0.91893853320467274178e0
+static double coef[5] = {
+    0.83333333333333023564e-1,-0.27777777768818808e-2,0.79365006754279e-3,
+    -0.594997310889e-3,0.8065880899e-3
+};
+static double scoefd[4] = {
+    0.62003838007126989331e2,0.9822521104713994894e1,-0.8906016659497461257e1,
+    0.1000000000000000000e1
+};
+static double scoefn[9] = {
+    0.62003838007127258804e2,0.36036772530024836321e2,0.20782472531792126786e2,
+    0.6338067999387272343e1,0.215994312846059073e1,0.3980671310203570498e0,
+    0.1093115956710439502e0,0.92381945590275995e-2,0.29737866448101651e-2
+};
+static int K1 = 9;
+static int K3 = 4;
+static int K5 = 5;
+static double alngam,offset,prod,xx;
+static int i,n;
+static double T2,T4,T6;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    if(!(*x <= 6.0e0)) goto S70;
+    prod = 1.0e0;
+    xx = *x;
+    if(!(*x > 3.0e0)) goto S30;
+S10:
+    if(!(xx > 3.0e0)) goto S20;
+    xx -= 1.0e0;
+    prod *= xx;
+    goto S10;
+S30:
+S20:
+    if(!(*x < 2.0e0)) goto S60;
+S40:
+    if(!(xx < 2.0e0)) goto S50;
+    prod /= xx;
+    xx += 1.0e0;
+    goto S40;
+S60:
+S50:
+    T2 = xx-2.0e0;
+    T4 = xx-2.0e0;
+    alngam = devlpl(scoefn,&K1,&T2)/devlpl(scoefd,&K3,&T4);
+/*
+     COMPUTE RATIONAL APPROXIMATION TO GAMMA(X)
+*/
+    alngam *= prod;
+    alngam = log(alngam);
+    goto S110;
+S70:
+    offset = hln2pi;
+/*
+     IF NECESSARY MAKE X AT LEAST 12 AND CARRY CORRECTION IN OFFSET
+*/
+    n = fifidint(12.0e0-*x);
+    if(!(n > 0)) goto S90;
+    prod = 1.0e0;
+    for(i=1; i<=n; i++) prod *= (*x+(double)(i-1));
+    offset -= log(prod);
+    xx = *x+(double)n;
+    goto S100;
+S90:
+    xx = *x;
+S100:
+/*
+     COMPUTE POWER SERIES
+*/
+    T6 = 1.0e0/pow(xx,2.0);
+    alngam = devlpl(coef,&K5,&T6)/xx;
+    alngam += (offset+(xx-0.5e0)*log(xx)-xx);
+S110:
+    return alngam;
+#undef hln2pi
+} /* END */
+
+/***=====================================================================***/
+static double alnrel(double *a)
+/*
+-----------------------------------------------------------------------
+            EVALUATION OF THE FUNCTION LN(1 + A)
+-----------------------------------------------------------------------
+*/
+{
+static double p1 = -.129418923021993e+01;
+static double p2 = .405303492862024e+00;
+static double p3 = -.178874546012214e-01;
+static double q1 = -.162752256355323e+01;
+static double q2 = .747811014037616e+00;
+static double q3 = -.845104217945565e-01;
+static double alnrel,t,t2,w,x;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    if(fabs(*a) > 0.375e0) goto S10;
+    t = *a/(*a+2.0e0);
+    t2 = t*t;
+    w = (((p3*t2+p2)*t2+p1)*t2+1.0e0)/(((q3*t2+q2)*t2+q1)*t2+1.0e0);
+    alnrel = 2.0e0*t*w;
+    return alnrel;
+S10:
+    x = 1.e0+*a;
+    alnrel = log(x);
+    return alnrel;
+} /* END */
+
+/***=====================================================================***/
+static double apser(double *a,double *b,double *x,double *eps)
+/*
+-----------------------------------------------------------------------
+     APSER YIELDS THE INCOMPLETE BETA RATIO I(SUB(1-X))(B,A) FOR
+     A .LE. MIN(EPS,EPS*B), B*X .LE. 1, AND X .LE. 0.5. USED WHEN
+     A IS VERY SMALL. USE ONLY IF ABOVE INEQUALITIES ARE SATISFIED.
+-----------------------------------------------------------------------
+*/
+{
+static double g = .577215664901533e0;
+static double apser,aj,bx,c,j,s,t,tol;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    bx = *b**x;
+    t = *x-bx;
+    if(*b**eps > 2.e-2) goto S10;
+    c = log(*x)+psi(b)+g+t;
+    goto S20;
+S10:
+    c = log(bx)+g+t;
+S20:
+    tol = 5.0e0**eps*fabs(c);
+    j = 1.0e0;
+    s = 0.0e0;
+S30:
+    j += 1.0e0;
+    t *= (*x-bx/j);
+    aj = t/j;
+    s += aj;
+    if(fabs(aj) > tol) goto S30;
+    apser = -(*a*(c+s));
+    return apser;
+} /* END */
+
+/***=====================================================================***/
+static double basym(double *a,double *b,double *lambda,double *eps)
+/*
+-----------------------------------------------------------------------
+     ASYMPTOTIC EXPANSION FOR IX(A,B) FOR LARGE A AND B.
+     LAMBDA = (A + B)*Y - B  AND EPS IS THE TOLERANCE USED.
+     IT IS ASSUMED THAT LAMBDA IS NONNEGATIVE AND THAT
+     A AND B ARE GREATER THAN OR EQUAL TO 15.
+-----------------------------------------------------------------------
+*/
+{
+static double e0 = 1.12837916709551e0;
+static double e1 = .353553390593274e0;
+static int num = 20;
+/*
+------------------------
+     ****** NUM IS THE MAXIMUM VALUE THAT N CAN TAKE IN THE DO LOOP
+            ENDING AT STATEMENT 50. IT IS REQUIRED THAT NUM BE EVEN.
+            THE ARRAYS A0, B0, C, D HAVE DIMENSION NUM + 1.
+------------------------
+     E0 = 2/SQRT(PI)
+     E1 = 2**(-3/2)
+------------------------
+*/
+static int K3 = 1;
+static double basym,bsum,dsum,f,h,h2,hn,j0,j1,r,r0,r1,s,sum,t,t0,t1,u,w,w0,z,z0,
+    z2,zn,znm1;
+static int i,im1,imj,j,m,mm1,mmj,n,np1;
+static double a0[21],b0[21],c[21],d[21],T1,T2;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    basym = 0.0e0;
+    if(*a >= *b) goto S10;
+    h = *a/ *b;
+    r0 = 1.0e0/(1.0e0+h);
+    r1 = (*b-*a)/ *b;
+    w0 = 1.0e0/sqrt(*a*(1.0e0+h));
+    goto S20;
+S10:
+    h = *b/ *a;
+    r0 = 1.0e0/(1.0e0+h);
+    r1 = (*b-*a)/ *a;
+    w0 = 1.0e0/sqrt(*b*(1.0e0+h));
+S20:
+    T1 = -(*lambda/ *a);
+    T2 = *lambda/ *b;
+    f = *a*rlog1(&T1)+*b*rlog1(&T2);
+    t = exp(-f);
+    if(t == 0.0e0) return basym;
+    z0 = sqrt(f);
+    z = 0.5e0*(z0/e1);
+    z2 = f+f;
+    a0[0] = 2.0e0/3.0e0*r1;
+    c[0] = -(0.5e0*a0[0]);
+    d[0] = -c[0];
+    j0 = 0.5e0/e0*erfc1(&K3,&z0);
+    j1 = e1;
+    sum = j0+d[0]*w0*j1;
+    s = 1.0e0;
+    h2 = h*h;
+    hn = 1.0e0;
+    w = w0;
+    znm1 = z;
+    zn = z2;
+    for(n=2; n<=num; n+=2) {
+        hn = h2*hn;
+        a0[n-1] = 2.0e0*r0*(1.0e0+h*hn)/((double)n+2.0e0);
+        np1 = n+1;
+        s += hn;
+        a0[np1-1] = 2.0e0*r1*s/((double)n+3.0e0);
+        for(i=n; i<=np1; i++) {
+            r = -(0.5e0*((double)i+1.0e0));
+            b0[0] = r*a0[0];
+            for(m=2; m<=i; m++) {
+                bsum = 0.0e0;
+                mm1 = m-1;
+                for(j=1; j<=mm1; j++) {
+                    mmj = m-j;
+                    bsum += (((double)j*r-(double)mmj)*a0[j-1]*b0[mmj-1]);
+                }
+                b0[m-1] = r*a0[m-1]+bsum/(double)m;
+            }
+            c[i-1] = b0[i-1]/((double)i+1.0e0);
+            dsum = 0.0e0;
+            im1 = i-1;
+            for(j=1; j<=im1; j++) {
+                imj = i-j;
+                dsum += (d[imj-1]*c[j-1]);
+            }
+            d[i-1] = -(dsum+c[i-1]);
+        }
+        j0 = e1*znm1+((double)n-1.0e0)*j0;
+        j1 = e1*zn+(double)n*j1;
+        znm1 = z2*znm1;
+        zn = z2*zn;
+        w = w0*w;
+        t0 = d[n-1]*w*j0;
+        w = w0*w;
+        t1 = d[np1-1]*w*j1;
+        sum += (t0+t1);
+        if(fabs(t0)+fabs(t1) <= *eps*sum) goto S80;
+    }
+S80:
+    u = exp(-bcorr(a,b));
+    basym = e0*t*u*sum;
+    return basym;
+} /* END */
+
+/***=====================================================================***/
+static double bcorr(double *a0,double *b0)
+/*
+-----------------------------------------------------------------------
+
+     EVALUATION OF  DEL(A0) + DEL(B0) - DEL(A0 + B0)  WHERE
+     LN(GAMMA(A)) = (A - 0.5)*LN(A) - A + 0.5*LN(2*PI) + DEL(A).
+     IT IS ASSUMED THAT A0 .GE. 8 AND B0 .GE. 8.
+
+-----------------------------------------------------------------------
+*/
+{
+static double c0 = .833333333333333e-01;
+static double c1 = -.277777777760991e-02;
+static double c2 = .793650666825390e-03;
+static double c3 = -.595202931351870e-03;
+static double c4 = .837308034031215e-03;
+static double c5 = -.165322962780713e-02;
+static double bcorr,a,b,c,h,s11,s3,s5,s7,s9,t,w,x,x2;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    a = fifdmin1(*a0,*b0);
+    b = fifdmax1(*a0,*b0);
+    h = a/b;
+    c = h/(1.0e0+h);
+    x = 1.0e0/(1.0e0+h);
+    x2 = x*x;
+/*
+                SET SN = (1 - X**N)/(1 - X)
+*/
+    s3 = 1.0e0+(x+x2);
+    s5 = 1.0e0+(x+x2*s3);
+    s7 = 1.0e0+(x+x2*s5);
+    s9 = 1.0e0+(x+x2*s7);
+    s11 = 1.0e0+(x+x2*s9);
+/*
+                SET W = DEL(B) - DEL(A + B)
+*/
+    t = pow(1.0e0/b,2.0);
+    w = ((((c5*s11*t+c4*s9)*t+c3*s7)*t+c2*s5)*t+c1*s3)*t+c0;
+    w *= (c/b);
+/*
+                   COMPUTE  DEL(A) + W
+*/
+    t = pow(1.0e0/a,2.0);
+    bcorr = (((((c5*t+c4)*t+c3)*t+c2)*t+c1)*t+c0)/a+w;
+    return bcorr;
+} /* END */
+
+/***=====================================================================***/
+static double betaln(double *a0,double *b0)
+/*
+-----------------------------------------------------------------------
+     EVALUATION OF THE LOGARITHM OF THE BETA FUNCTION
+-----------------------------------------------------------------------
+     E = 0.5*LN(2*PI)
+--------------------------
+*/
+{
+static double e = .918938533204673e0;
+static double betaln,a,b,c,h,u,v,w,z;
+static int i,n;
+static double T1;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    a = fifdmin1(*a0,*b0);
+    b = fifdmax1(*a0,*b0);
+    if(a >= 8.0e0) goto S100;
+    if(a >= 1.0e0) goto S20;
+/*
+-----------------------------------------------------------------------
+                   PROCEDURE WHEN A .LT. 1
+-----------------------------------------------------------------------
+*/
+    if(b >= 8.0e0) goto S10;
+    T1 = a+b;
+    betaln = gamln(&a)+(gamln(&b)-gamln(&T1));
+    return betaln;
+S10:
+    betaln = gamln(&a)+algdiv(&a,&b);
+    return betaln;
+S20:
+/*
+-----------------------------------------------------------------------
+                PROCEDURE WHEN 1 .LE. A .LT. 8
+-----------------------------------------------------------------------
+*/
+    if(a > 2.0e0) goto S40;
+    if(b > 2.0e0) goto S30;
+    betaln = gamln(&a)+gamln(&b)-gsumln(&a,&b);
+    return betaln;
+S30:
+    w = 0.0e0;
+    if(b < 8.0e0) goto S60;
+    betaln = gamln(&a)+algdiv(&a,&b);
+    return betaln;
+S40:
+/*
+                REDUCTION OF A WHEN B .LE. 1000
+*/
+    if(b > 1000.0e0) goto S80;
+    n = a-1.0e0;
+    w = 1.0e0;
+    for(i=1; i<=n; i++) {
+        a -= 1.0e0;
+        h = a/b;
+        w *= (h/(1.0e0+h));
+    }
+    w = log(w);
+    if(b < 8.0e0) goto S60;
+    betaln = w+gamln(&a)+algdiv(&a,&b);
+    return betaln;
+S60:
+/*
+                 REDUCTION OF B WHEN B .LT. 8
+*/
+    n = b-1.0e0;
+    z = 1.0e0;
+    for(i=1; i<=n; i++) {
+        b -= 1.0e0;
+        z *= (b/(a+b));
+    }
+    betaln = w+log(z)+(gamln(&a)+(gamln(&b)-gsumln(&a,&b)));
+    return betaln;
+S80:
+/*
+                REDUCTION OF A WHEN B .GT. 1000
+*/
+    n = a-1.0e0;
+    w = 1.0e0;
+    for(i=1; i<=n; i++) {
+        a -= 1.0e0;
+        w *= (a/(1.0e0+a/b));
+    }
+    betaln = log(w)-(double)n*log(b)+(gamln(&a)+algdiv(&a,&b));
+    return betaln;
+S100:
+/*
+-----------------------------------------------------------------------
+                   PROCEDURE WHEN A .GE. 8
+-----------------------------------------------------------------------
+*/
+    w = bcorr(&a,&b);
+    h = a/b;
+    c = h/(1.0e0+h);
+    u = -((a-0.5e0)*log(c));
+    v = b*alnrel(&h);
+    if(u <= v) goto S110;
+    betaln = -(0.5e0*log(b))+e+w-v-u;
+    return betaln;
+S110:
+    betaln = -(0.5e0*log(b))+e+w-u-v;
+    return betaln;
+} /* END */
+
+/***=====================================================================***/
+static double bfrac(double *a,double *b,double *x,double *y,double *lambda,
+         double *eps)
+/*
+-----------------------------------------------------------------------
+     CONTINUED FRACTION EXPANSION FOR IX(A,B) WHEN A,B .GT. 1.
+     IT IS ASSUMED THAT  LAMBDA = (A + B)*Y - B.
+-----------------------------------------------------------------------
+*/
+{
+static double bfrac,alpha,an,anp1,beta,bn,bnp1,c,c0,c1,e,n,p,r,r0,s,t,w,yp1;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    bfrac = brcomp(a,b,x,y);
+    if(bfrac == 0.0e0) return bfrac;
+    c = 1.0e0+*lambda;
+    c0 = *b/ *a;
+    c1 = 1.0e0+1.0e0/ *a;
+    yp1 = *y+1.0e0;
+    n = 0.0e0;
+    p = 1.0e0;
+    s = *a+1.0e0;
+    an = 0.0e0;
+    bn = anp1 = 1.0e0;
+    bnp1 = c/c1;
+    r = c1/c;
+S10:
+/*
+        CONTINUED FRACTION CALCULATION
+*/
+    n += 1.0e0;
+    t = n/ *a;
+    w = n*(*b-n)**x;
+    e = *a/s;
+    alpha = p*(p+c0)*e*e*(w**x);
+    e = (1.0e0+t)/(c1+t+t);
+    beta = n+w/s+e*(c+n*yp1);
+    p = 1.0e0+t;
+    s += 2.0e0;
+/*
+        UPDATE AN, BN, ANP1, AND BNP1
+*/
+    t = alpha*an+beta*anp1;
+    an = anp1;
+    anp1 = t;
+    t = alpha*bn+beta*bnp1;
+    bn = bnp1;
+    bnp1 = t;
+    r0 = r;
+    r = anp1/bnp1;
+    if(fabs(r-r0) <= *eps*r) goto S20;
+/*
+        RESCALE AN, BN, ANP1, AND BNP1
+*/
+    an /= bnp1;
+    bn /= bnp1;
+    anp1 = r;
+    bnp1 = 1.0e0;
+    goto S10;
+S20:
+/*
+                 TERMINATION
+*/
+    bfrac *= r;
+    return bfrac;
+} /* END */
+
+/***=====================================================================***/
+static void bgrat(double *a,double *b,double *x,double *y,double *w,
+       double *eps,int *ierr)
+/*
+-----------------------------------------------------------------------
+     ASYMPTOTIC EXPANSION FOR IX(A,B) WHEN A IS LARGER THAN B.
+     THE RESULT OF THE EXPANSION IS ADDED TO W. IT IS ASSUMED
+     THAT A .GE. 15 AND B .LE. 1.  EPS IS THE TOLERANCE USED.
+     IERR IS A VARIABLE THAT REPORTS THE STATUS OF THE RESULTS.
+-----------------------------------------------------------------------
+*/
+{
+static double bm1,bp2n,cn,coef,dj,j,l,lnx,n2,nu,p,q,r,s,sum,t,t2,u,v,z;
+static int i,n,nm1;
+static double c[30],d[30],T1;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    bm1 = *b-0.5e0-0.5e0;
+    nu = *a+0.5e0*bm1;
+    if(*y > 0.375e0) goto S10;
+    T1 = -*y;
+    lnx = alnrel(&T1);
+    goto S20;
+S10:
+    lnx = log(*x);
+S20:
+    z = -(nu*lnx);
+    if(*b*z == 0.0e0) goto S70;
+/*
+                 COMPUTATION OF THE EXPANSION
+                 SET R = EXP(-Z)*Z**B/GAMMA(B)
+*/
+    r = *b*(1.0e0+gam1(b))*exp(*b*log(z));
+    r *= (exp(*a*lnx)*exp(0.5e0*bm1*lnx));
+    u = algdiv(b,a)+*b*log(nu);
+    u = r*exp(-u);
+    if(u == 0.0e0) goto S70;
+    grat1(b,&z,&r,&p,&q,eps);
+    v = 0.25e0*pow(1.0e0/nu,2.0);
+    t2 = 0.25e0*lnx*lnx;
+    l = *w/u;
+    j = q/r;
+    sum = j;
+    t = cn = 1.0e0;
+    n2 = 0.0e0;
+    for(n=1; n<=30; n++) {
+        bp2n = *b+n2;
+        j = (bp2n*(bp2n+1.0e0)*j+(z+bp2n+1.0e0)*t)*v;
+        n2 += 2.0e0;
+        t *= t2;
+        cn /= (n2*(n2+1.0e0));
+        c[n-1] = cn;
+        s = 0.0e0;
+        if(n == 1) goto S40;
+        nm1 = n-1;
+        coef = *b-(double)n;
+        for(i=1; i<=nm1; i++) {
+            s += (coef*c[i-1]*d[n-i-1]);
+            coef += *b;
+        }
+S40:
+        d[n-1] = bm1*cn+s/(double)n;
+        dj = d[n-1]*j;
+        sum += dj;
+        if(sum <= 0.0e0) goto S70;
+        if(fabs(dj) <= *eps*(sum+l)) goto S60;
+    }
+S60:
+/*
+                    ADD THE RESULTS TO W
+*/
+    *ierr = 0;
+    *w += (u*sum);
+    return;
+S70:
+/*
+               THE EXPANSION CANNOT BE COMPUTED
+*/
+    *ierr = 1;
+    return;
+} /* END */
+
+/***=====================================================================***/
+static double bpser(double *a,double *b,double *x,double *eps)
+/*
+-----------------------------------------------------------------------
+     POWER SERIES EXPANSION FOR EVALUATING IX(A,B) WHEN B .LE. 1
+     OR B*X .LE. 0.7.  EPS IS THE TOLERANCE USED.
+-----------------------------------------------------------------------
+*/
+{
+static double bpser,a0,apb,b0,c,n,sum,t,tol,u,w,z;
+static int i,m;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    bpser = 0.0e0;
+    if(*x == 0.0e0) return bpser;
+/*
+-----------------------------------------------------------------------
+            COMPUTE THE FACTOR X**A/(A*BETA(A,B))
+-----------------------------------------------------------------------
+*/
+    a0 = fifdmin1(*a,*b);
+    if(a0 < 1.0e0) goto S10;
+    z = *a*log(*x)-betaln(a,b);
+    bpser = exp(z)/ *a;
+    goto S100;
+S10:
+    b0 = fifdmax1(*a,*b);
+    if(b0 >= 8.0e0) goto S90;
+    if(b0 > 1.0e0) goto S40;
+/*
+            PROCEDURE FOR A0 .LT. 1 AND B0 .LE. 1
+*/
+    bpser = pow(*x,*a);
+    if(bpser == 0.0e0) return bpser;
+    apb = *a+*b;
+    if(apb > 1.0e0) goto S20;
+    z = 1.0e0+gam1(&apb);
+    goto S30;
+S20:
+    u = *a+*b-1.e0;
+    z = (1.0e0+gam1(&u))/apb;
+S30:
+    c = (1.0e0+gam1(a))*(1.0e0+gam1(b))/z;
+    bpser *= (c*(*b/apb));
+    goto S100;
+S40:
+/*
+         PROCEDURE FOR A0 .LT. 1 AND 1 .LT. B0 .LT. 8
+*/
+    u = gamln1(&a0);
+    m = b0-1.0e0;
+    if(m < 1) goto S60;
+    c = 1.0e0;
+    for(i=1; i<=m; i++) {
+        b0 -= 1.0e0;
+        c *= (b0/(a0+b0));
+    }
+    u = log(c)+u;
+S60:
+    z = *a*log(*x)-u;
+    b0 -= 1.0e0;
+    apb = a0+b0;
+    if(apb > 1.0e0) goto S70;
+    t = 1.0e0+gam1(&apb);
+    goto S80;
+S70:
+    u = a0+b0-1.e0;
+    t = (1.0e0+gam1(&u))/apb;
+S80:
+    bpser = exp(z)*(a0/ *a)*(1.0e0+gam1(&b0))/t;
+    goto S100;
+S90:
+/*
+            PROCEDURE FOR A0 .LT. 1 AND B0 .GE. 8
+*/
+    u = gamln1(&a0)+algdiv(&a0,&b0);
+    z = *a*log(*x)-u;
+    bpser = a0/ *a*exp(z);
+S100:
+    if(bpser == 0.0e0 || *a <= 0.1e0**eps) return bpser;
+/*
+-----------------------------------------------------------------------
+                     COMPUTE THE SERIES
+-----------------------------------------------------------------------
+*/
+    sum = n = 0.0e0;
+    c = 1.0e0;
+    tol = *eps/ *a;
+S110:
+    n += 1.0e0;
+    c *= ((0.5e0+(0.5e0-*b/n))**x);
+    w = c/(*a+n);
+    sum += w;
+    if(fabs(w) > tol) goto S110;
+    bpser *= (1.0e0+*a*sum);
+    return bpser;
+} /* END */
+
+/***=====================================================================***/
+static void bratio(double *a,double *b,double *x,double *y,double *w,
+        double *w1,int *ierr)
+/*
+-----------------------------------------------------------------------
+
+            EVALUATION OF THE INCOMPLETE BETA FUNCTION IX(A,B)
+
+                     --------------------
+
+     IT IS ASSUMED THAT A AND B ARE NONNEGATIVE, AND THAT X .LE. 1
+     AND Y = 1 - X.  BRATIO ASSIGNS W AND W1 THE VALUES
+
+                      W  = IX(A,B)
+                      W1 = 1 - IX(A,B)
+
+     IERR IS A VARIABLE THAT REPORTS THE STATUS OF THE RESULTS.
+     IF NO INPUT ERRORS ARE DETECTED THEN IERR IS SET TO 0 AND
+     W AND W1 ARE COMPUTED. OTHERWISE, IF AN ERROR IS DETECTED,
+     THEN W AND W1 ARE ASSIGNED THE VALUE 0 AND IERR IS SET TO
+     ONE OF THE FOLLOWING VALUES ...
+
+        IERR = 1  IF A OR B IS NEGATIVE
+        IERR = 2  IF A = B = 0
+        IERR = 3  IF X .LT. 0 OR X .GT. 1
+        IERR = 4  IF Y .LT. 0 OR Y .GT. 1
+        IERR = 5  IF X + Y .NE. 1
+        IERR = 6  IF X = A = 0
+        IERR = 7  IF Y = B = 0
+
+--------------------
+     WRITTEN BY ALFRED H. MORRIS, JR.
+        NAVAL SURFACE WARFARE CENTER
+        DAHLGREN, VIRGINIA
+     REVISED ... NOV 1991
+-----------------------------------------------------------------------
+*/
+{
+static int K1 = 1;
+static double a0,b0,eps,lambda,t,x0,y0,z;
+static int ierr1,ind,n;
+static double T2,T3,T4,T5;
+/*
+     ..
+     .. Executable Statements ..
+*/
+/*
+     ****** EPS IS A MACHINE DEPENDENT CONSTANT. EPS IS THE SMALLEST
+            FLOATING POINT NUMBER FOR WHICH 1.0 + EPS .GT. 1.0
+*/
+    eps = spmpar(&K1);
+    *w = *w1 = 0.0e0;
+    if(*a < 0.0e0 || *b < 0.0e0) goto S270;
+    if(*a == 0.0e0 && *b == 0.0e0) goto S280;
+    if(*x < 0.0e0 || *x > 1.0e0) goto S290;
+    if(*y < 0.0e0 || *y > 1.0e0) goto S300;
+    z = *x+*y-0.5e0-0.5e0;
+    if(fabs(z) > 3.0e0*eps) goto S310;
+    *ierr = 0;
+    if(*x == 0.0e0) goto S210;
+    if(*y == 0.0e0) goto S230;
+    if(*a == 0.0e0) goto S240;
+    if(*b == 0.0e0) goto S220;
+    eps = fifdmax1(eps,1.e-15);
+    if(fifdmax1(*a,*b) < 1.e-3*eps) goto S260;
+    ind = 0;
+    a0 = *a;
+    b0 = *b;
+    x0 = *x;
+    y0 = *y;
+    if(fifdmin1(a0,b0) > 1.0e0) goto S40;
+/*
+             PROCEDURE FOR A0 .LE. 1 OR B0 .LE. 1
+*/
+    if(*x <= 0.5e0) goto S10;
+    ind = 1;
+    a0 = *b;
+    b0 = *a;
+    x0 = *y;
+    y0 = *x;
+S10:
+    if(b0 < fifdmin1(eps,eps*a0)) goto S90;
+    if(a0 < fifdmin1(eps,eps*b0) && b0*x0 <= 1.0e0) goto S100;
+    if(fifdmax1(a0,b0) > 1.0e0) goto S20;
+    if(a0 >= fifdmin1(0.2e0,b0)) goto S110;
+    if(pow(x0,a0) <= 0.9e0) goto S110;
+    if(x0 >= 0.3e0) goto S120;
+    n = 20;
+    goto S140;
+S20:
+    if(b0 <= 1.0e0) goto S110;
+    if(x0 >= 0.3e0) goto S120;
+    if(x0 >= 0.1e0) goto S30;
+    if(pow(x0*b0,a0) <= 0.7e0) goto S110;
+S30:
+    if(b0 > 15.0e0) goto S150;
+    n = 20;
+    goto S140;
+S40:
+/*
+             PROCEDURE FOR A0 .GT. 1 AND B0 .GT. 1
+*/
+    if(*a > *b) goto S50;
+    lambda = *a-(*a+*b)**x;
+    goto S60;
+S50:
+    lambda = (*a+*b)**y-*b;
+S60:
+    if(lambda >= 0.0e0) goto S70;
+    ind = 1;
+    a0 = *b;
+    b0 = *a;
+    x0 = *y;
+    y0 = *x;
+    lambda = fabs(lambda);
+S70:
+    if(b0 < 40.0e0 && b0*x0 <= 0.7e0) goto S110;
+    if(b0 < 40.0e0) goto S160;
+    if(a0 > b0) goto S80;
+    if(a0 <= 100.0e0) goto S130;
+    if(lambda > 0.03e0*a0) goto S130;
+    goto S200;
+S80:
+    if(b0 <= 100.0e0) goto S130;
+    if(lambda > 0.03e0*b0) goto S130;
+    goto S200;
+S90:
+/*
+            EVALUATION OF THE APPROPRIATE ALGORITHM
+*/
+    *w = fpser(&a0,&b0,&x0,&eps);
+    *w1 = 0.5e0+(0.5e0-*w);
+    goto S250;
+S100:
+    *w1 = apser(&a0,&b0,&x0,&eps);
+    *w = 0.5e0+(0.5e0-*w1);
+    goto S250;
+S110:
+    *w = bpser(&a0,&b0,&x0,&eps);
+    *w1 = 0.5e0+(0.5e0-*w);
+    goto S250;
+S120:
+    *w1 = bpser(&b0,&a0,&y0,&eps);
+    *w = 0.5e0+(0.5e0-*w1);
+    goto S250;
+S130:
+    T2 = 15.0e0*eps;
+    *w = bfrac(&a0,&b0,&x0,&y0,&lambda,&T2);
+    *w1 = 0.5e0+(0.5e0-*w);
+    goto S250;
+S140:
+    *w1 = bup(&b0,&a0,&y0,&x0,&n,&eps);
+    b0 += (double)n;
+S150:
+    T3 = 15.0e0*eps;
+    bgrat(&b0,&a0,&y0,&x0,w1,&T3,&ierr1);
+    *w = 0.5e0+(0.5e0-*w1);
+    goto S250;
+S160:
+    n = b0;
+    b0 -= (double)n;
+    if(b0 != 0.0e0) goto S170;
+    n -= 1;
+    b0 = 1.0e0;
+S170:
+    *w = bup(&b0,&a0,&y0,&x0,&n,&eps);
+    if(x0 > 0.7e0) goto S180;
+    *w += bpser(&a0,&b0,&x0,&eps);
+    *w1 = 0.5e0+(0.5e0-*w);
+    goto S250;
+S180:
+    if(a0 > 15.0e0) goto S190;
+    n = 20;
+    *w += bup(&a0,&b0,&x0,&y0,&n,&eps);
+    a0 += (double)n;
+S190:
+    T4 = 15.0e0*eps;
+    bgrat(&a0,&b0,&x0,&y0,w,&T4,&ierr1);
+    *w1 = 0.5e0+(0.5e0-*w);
+    goto S250;
+S200:
+    T5 = 100.0e0*eps;
+    *w = basym(&a0,&b0,&lambda,&T5);
+    *w1 = 0.5e0+(0.5e0-*w);
+    goto S250;
+S210:
+/*
+               TERMINATION OF THE PROCEDURE
+*/
+    if(*a == 0.0e0) goto S320;
+S220:
+    *w = 0.0e0;
+    *w1 = 1.0e0;
+    return;
+S230:
+    if(*b == 0.0e0) goto S330;
+S240:
+    *w = 1.0e0;
+    *w1 = 0.0e0;
+    return;
+S250:
+    if(ind == 0) return;
+    t = *w;
+    *w = *w1;
+    *w1 = t;
+    return;
+S260:
+/*
+           PROCEDURE FOR A AND B .LT. 1.E-3*EPS
+*/
+    *w = *b/(*a+*b);
+    *w1 = *a/(*a+*b);
+    return;
+S270:
+/*
+                       ERROR RETURN
+*/
+    *ierr = 1;
+    return;
+S280:
+    *ierr = 2;
+    return;
+S290:
+    *ierr = 3;
+    return;
+S300:
+    *ierr = 4;
+    return;
+S310:
+    *ierr = 5;
+    return;
+S320:
+    *ierr = 6;
+    return;
+S330:
+    *ierr = 7;
+    return;
+} /* END */
+
+/***=====================================================================***/
+static double brcmp1(int *mu,double *a,double *b,double *x,double *y)
+/*
+-----------------------------------------------------------------------
+          EVALUATION OF  EXP(MU) * (X**A*Y**B/BETA(A,B))
+-----------------------------------------------------------------------
+*/
+{
+static double Const = .398942280401433e0;
+static double brcmp1,a0,apb,b0,c,e,h,lambda,lnx,lny,t,u,v,x0,y0,z;
+static int i,n;
+/*
+-----------------
+     CONST = 1/SQRT(2*PI)
+-----------------
+*/
+static double T1,T2,T3,T4;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    a0 = fifdmin1(*a,*b);
+    if(a0 >= 8.0e0) goto S130;
+    if(*x > 0.375e0) goto S10;
+    lnx = log(*x);
+    T1 = -*x;
+    lny = alnrel(&T1);
+    goto S30;
+S10:
+    if(*y > 0.375e0) goto S20;
+    T2 = -*y;
+    lnx = alnrel(&T2);
+    lny = log(*y);
+    goto S30;
+S20:
+    lnx = log(*x);
+    lny = log(*y);
+S30:
+    z = *a*lnx+*b*lny;
+    if(a0 < 1.0e0) goto S40;
+    z -= betaln(a,b);
+    brcmp1 = esum(mu,&z);
+    return brcmp1;
+S40:
+/*
+-----------------------------------------------------------------------
+              PROCEDURE FOR A .LT. 1 OR B .LT. 1
+-----------------------------------------------------------------------
+*/
+    b0 = fifdmax1(*a,*b);
+    if(b0 >= 8.0e0) goto S120;
+    if(b0 > 1.0e0) goto S70;
+/*
+                   ALGORITHM FOR B0 .LE. 1
+*/
+    brcmp1 = esum(mu,&z);
+    if(brcmp1 == 0.0e0) return brcmp1;
+    apb = *a+*b;
+    if(apb > 1.0e0) goto S50;
+    z = 1.0e0+gam1(&apb);
+    goto S60;
+S50:
+    u = *a+*b-1.e0;
+    z = (1.0e0+gam1(&u))/apb;
+S60:
+    c = (1.0e0+gam1(a))*(1.0e0+gam1(b))/z;
+    brcmp1 = brcmp1*(a0*c)/(1.0e0+a0/b0);
+    return brcmp1;
+S70:
+/*
+                ALGORITHM FOR 1 .LT. B0 .LT. 8
+*/
+    u = gamln1(&a0);
+    n = b0-1.0e0;
+    if(n < 1) goto S90;
+    c = 1.0e0;
+    for(i=1; i<=n; i++) {
+        b0 -= 1.0e0;
+        c *= (b0/(a0+b0));
+    }
+    u = log(c)+u;
+S90:
+    z -= u;
+    b0 -= 1.0e0;
+    apb = a0+b0;
+    if(apb > 1.0e0) goto S100;
+    t = 1.0e0+gam1(&apb);
+    goto S110;
+S100:
+    u = a0+b0-1.e0;
+    t = (1.0e0+gam1(&u))/apb;
+S110:
+    brcmp1 = a0*esum(mu,&z)*(1.0e0+gam1(&b0))/t;
+    return brcmp1;
+S120:
+/*
+                   ALGORITHM FOR B0 .GE. 8
+*/
+    u = gamln1(&a0)+algdiv(&a0,&b0);
+    T3 = z-u;
+    brcmp1 = a0*esum(mu,&T3);
+    return brcmp1;
+S130:
+/*
+-----------------------------------------------------------------------
+              PROCEDURE FOR A .GE. 8 AND B .GE. 8
+-----------------------------------------------------------------------
+*/
+    if(*a > *b) goto S140;
+    h = *a/ *b;
+    x0 = h/(1.0e0+h);
+    y0 = 1.0e0/(1.0e0+h);
+    lambda = *a-(*a+*b)**x;
+    goto S150;
+S140:
+    h = *b/ *a;
+    x0 = 1.0e0/(1.0e0+h);
+    y0 = h/(1.0e0+h);
+    lambda = (*a+*b)**y-*b;
+S150:
+    e = -(lambda/ *a);
+    if(fabs(e) > 0.6e0) goto S160;
+    u = rlog1(&e);
+    goto S170;
+S160:
+    u = e-log(*x/x0);
+S170:
+    e = lambda/ *b;
+    if(fabs(e) > 0.6e0) goto S180;
+    v = rlog1(&e);
+    goto S190;
+S180:
+    v = e-log(*y/y0);
+S190:
+    T4 = -(*a*u+*b*v);
+    z = esum(mu,&T4);
+    brcmp1 = Const*sqrt(*b*x0)*z*exp(-bcorr(a,b));
+    return brcmp1;
+} /* END */
+
+/***=====================================================================***/
+static double brcomp(double *a,double *b,double *x,double *y)
+/*
+-----------------------------------------------------------------------
+               EVALUATION OF X**A*Y**B/BETA(A,B)
+-----------------------------------------------------------------------
+*/
+{
+static double Const = .398942280401433e0;
+static double brcomp,a0,apb,b0,c,e,h,lambda,lnx,lny,t,u,v,x0,y0,z;
+static int i,n;
+/*
+-----------------
+     CONST = 1/SQRT(2*PI)
+-----------------
+*/
+static double T1,T2;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    brcomp = 0.0e0;
+    if(*x == 0.0e0 || *y == 0.0e0) return brcomp;
+    a0 = fifdmin1(*a,*b);
+    if(a0 >= 8.0e0) goto S130;
+    if(*x > 0.375e0) goto S10;
+    lnx = log(*x);
+    T1 = -*x;
+    lny = alnrel(&T1);
+    goto S30;
+S10:
+    if(*y > 0.375e0) goto S20;
+    T2 = -*y;
+    lnx = alnrel(&T2);
+    lny = log(*y);
+    goto S30;
+S20:
+    lnx = log(*x);
+    lny = log(*y);
+S30:
+    z = *a*lnx+*b*lny;
+    if(a0 < 1.0e0) goto S40;
+    z -= betaln(a,b);
+    brcomp = exp(z);
+    return brcomp;
+S40:
+/*
+-----------------------------------------------------------------------
+              PROCEDURE FOR A .LT. 1 OR B .LT. 1
+-----------------------------------------------------------------------
+*/
+    b0 = fifdmax1(*a,*b);
+    if(b0 >= 8.0e0) goto S120;
+    if(b0 > 1.0e0) goto S70;
+/*
+                   ALGORITHM FOR B0 .LE. 1
+*/
+    brcomp = exp(z);
+    if(brcomp == 0.0e0) return brcomp;
+    apb = *a+*b;
+    if(apb > 1.0e0) goto S50;
+    z = 1.0e0+gam1(&apb);
+    goto S60;
+S50:
+    u = *a+*b-1.e0;
+    z = (1.0e0+gam1(&u))/apb;
+S60:
+    c = (1.0e0+gam1(a))*(1.0e0+gam1(b))/z;
+    brcomp = brcomp*(a0*c)/(1.0e0+a0/b0);
+    return brcomp;
+S70:
+/*
+                ALGORITHM FOR 1 .LT. B0 .LT. 8
+*/
+    u = gamln1(&a0);
+    n = b0-1.0e0;
+    if(n < 1) goto S90;
+    c = 1.0e0;
+    for(i=1; i<=n; i++) {
+        b0 -= 1.0e0;
+        c *= (b0/(a0+b0));
+    }
+    u = log(c)+u;
+S90:
+    z -= u;
+    b0 -= 1.0e0;
+    apb = a0+b0;
+    if(apb > 1.0e0) goto S100;
+    t = 1.0e0+gam1(&apb);
+    goto S110;
+S100:
+    u = a0+b0-1.e0;
+    t = (1.0e0+gam1(&u))/apb;
+S110:
+    brcomp = a0*exp(z)*(1.0e0+gam1(&b0))/t;
+    return brcomp;
+S120:
+/*
+                   ALGORITHM FOR B0 .GE. 8
+*/
+    u = gamln1(&a0)+algdiv(&a0,&b0);
+    brcomp = a0*exp(z-u);
+    return brcomp;
+S130:
+/*
+-----------------------------------------------------------------------
+              PROCEDURE FOR A .GE. 8 AND B .GE. 8
+-----------------------------------------------------------------------
+*/
+    if(*a > *b) goto S140;
+    h = *a/ *b;
+    x0 = h/(1.0e0+h);
+    y0 = 1.0e0/(1.0e0+h);
+    lambda = *a-(*a+*b)**x;
+    goto S150;
+S140:
+    h = *b/ *a;
+    x0 = 1.0e0/(1.0e0+h);
+    y0 = h/(1.0e0+h);
+    lambda = (*a+*b)**y-*b;
+S150:
+    e = -(lambda/ *a);
+    if(fabs(e) > 0.6e0) goto S160;
+    u = rlog1(&e);
+    goto S170;
+S160:
+    u = e-log(*x/x0);
+S170:
+    e = lambda/ *b;
+    if(fabs(e) > 0.6e0) goto S180;
+    v = rlog1(&e);
+    goto S190;
+S180:
+    v = e-log(*y/y0);
+S190:
+    z = exp(-(*a*u+*b*v));
+    brcomp = Const*sqrt(*b*x0)*z*exp(-bcorr(a,b));
+    return brcomp;
+} /* END */
+
+/***=====================================================================***/
+static double bup(double *a,double *b,double *x,double *y,int *n,double *eps)
+/*
+-----------------------------------------------------------------------
+     EVALUATION OF IX(A,B) - IX(A+N,B) WHERE N IS A POSITIVE INTEGER.
+     EPS IS THE TOLERANCE USED.
+-----------------------------------------------------------------------
+*/
+{
+static int K1 = 1;
+static int K2 = 0;
+static double bup,ap1,apb,d,l,r,t,w;
+static int i,k,kp1,mu,nm1;
+/*
+     ..
+     .. Executable Statements ..
+*/
+/*
+          OBTAIN THE SCALING FACTOR EXP(-MU) AND
+             EXP(MU)*(X**A*Y**B/BETA(A,B))/A
+*/
+    apb = *a+*b;
+    ap1 = *a+1.0e0;
+    mu = 0;
+    d = 1.0e0;
+    if(*n == 1 || *a < 1.0e0) goto S10;
+    if(apb < 1.1e0*ap1) goto S10;
+    mu = fabs(exparg(&K1));
+    k = exparg(&K2);
+    if(k < mu) mu = k;
+    t = mu;
+    d = exp(-t);
+S10:
+    bup = brcmp1(&mu,a,b,x,y)/ *a;
+    if(*n == 1 || bup == 0.0e0) return bup;
+    nm1 = *n-1;
+    w = d;
+/*
+          LET K BE THE INDEX OF THE MAXIMUM TERM
+*/
+    k = 0;
+    if(*b <= 1.0e0) goto S50;
+    if(*y > 1.e-4) goto S20;
+    k = nm1;
+    goto S30;
+S20:
+    r = (*b-1.0e0)**x/ *y-*a;
+    if(r < 1.0e0) goto S50;
+    k = t = nm1;
+    if(r < t) k = r;
+S30:
+/*
+          ADD THE INCREASING TERMS OF THE SERIES
+*/
+    for(i=1; i<=k; i++) {
+        l = i-1;
+        d = (apb+l)/(ap1+l)**x*d;
+        w += d;
+    }
+    if(k == nm1) goto S70;
+S50:
+/*
+          ADD THE REMAINING TERMS OF THE SERIES
+*/
+    kp1 = k+1;
+    for(i=kp1; i<=nm1; i++) {
+        l = i-1;
+        d = (apb+l)/(ap1+l)**x*d;
+        w += d;
+        if(d <= *eps*w) goto S70;
+    }
+S70:
+/*
+               TERMINATE THE PROCEDURE
+*/
+    bup *= w;
+    return bup;
+} /* END */
+
+/***=====================================================================***/
+static void cdfbet(int *which,double *p,double *q,double *x,double *y,
+        double *a,double *b,int *status,double *bound)
+/**********************************************************************
+
+      void cdfbet(int *which,double *p,double *q,double *x,double *y,
+            double *a,double *b,int *status,double *bound)
+
+               Cumulative Distribution Function
+                         BETa Distribution
+
+
+                              Function
+
+
+     Calculates any one parameter of the beta distribution given
+     values for the others.
+
+
+                              Arguments
+
+
+     WHICH --> Integer indicating which of the next four argument
+               values is to be calculated from the others.
+               Legal range: 1..4
+               iwhich = 1 : Calculate P and Q from X,Y,A and B
+               iwhich = 2 : Calculate X and Y from P,Q,A and B
+               iwhich = 3 : Calculate A from P,Q,X,Y and B
+               iwhich = 4 : Calculate B from P,Q,X,Y and A
+
+     P <--> The integral from 0 to X of the chi-square
+            distribution.
+            Input range: [0, 1].
+
+     Q <--> 1-P.
+            Input range: [0, 1].
+            P + Q = 1.0.
+
+     X <--> Upper limit of integration of beta density.
+            Input range: [0,1].
+            Search range: [0,1]
+
+     Y <--> 1-X.
+            Input range: [0,1].
+            Search range: [0,1]
+            X + Y = 1.0.
+
+     A <--> The first parameter of the beta density.
+            Input range: (0, +infinity).
+            Search range: [1D-300,1D300]
+
+     B <--> The second parameter of the beta density.
+            Input range: (0, +infinity).
+            Search range: [1D-300,1D300]
+
+     STATUS <-- 0 if calculation completed correctly
+               -I if input parameter number I is out of range
+                1 if answer appears to be lower than lowest
+                  search bound
+                2 if answer appears to be higher than greatest
+                  search bound
+                3 if P + Q .ne. 1
+                4 if X + Y .ne. 1
+
+     BOUND <-- Undefined if STATUS is 0
+
+               Bound exceeded by parameter number I if STATUS
+               is negative.
+
+               Lower search bound if STATUS is 1.
+
+               Upper search bound if STATUS is 2.
+
+
+                              Method
+
+
+     Cumulative distribution function  (P)  is calculated directly by
+     code associated with the following reference.
+
+     DiDinato, A. R. and Morris,  A.   H.  Algorithm 708: Significant
+     Digit Computation of the Incomplete  Beta  Function Ratios.  ACM
+     Trans. Math.  Softw. 18 (1993), 360-373.
+
+     Computation of other parameters involve a seach for a value that
+     produces  the desired  value  of P.   The search relies  on  the
+     monotinicity of P with the other parameter.
+
+
+                              Note
+
+
+     The beta density is proportional to
+               t^(A-1) * (1-t)^(B-1)
+
+**********************************************************************/
+{
+#define tol (1.0e-8)
+#define atol (1.0e-50)
+#define zero (1.0e-300)
+#define inf 1.0e300
+#define one 1.0e0
+static int K1 = 1;
+static double K2 = 0.0e0;
+static double K3 = 1.0e0;
+static double K8 = 0.5e0;
+static double K9 = 5.0e0;
+static double fx,xhi,xlo,cum,ccum,xy,pq;
+static unsigned long qhi,qleft,qporq;
+static double T4,T5,T6,T7,T10,T11,T12,T13,T14,T15;
+/*
+     ..
+     .. Executable Statements ..
+*/
+/*
+     Check arguments
+*/
+    if(!(*which < 1 || *which > 4)) goto S30;
+    if(!(*which < 1)) goto S10;
+    *bound = 1.0e0;
+    goto S20;
+S10:
+    *bound = 4.0e0;
+S20:
+    *status = -1;
+    return;
+S30:
+    if(*which == 1) goto S70;
+/*
+     P
+*/
+    if(!(*p < 0.0e0 || *p > 1.0e0)) goto S60;
+    if(!(*p < 0.0e0)) goto S40;
+    *bound = 0.0e0;
+    goto S50;
+S40:
+    *bound = 1.0e0;
+S50:
+    *status = -2;
+    return;
+S70:
+S60:
+    if(*which == 1) goto S110;
+/*
+     Q
+*/
+    if(!(*q < 0.0e0 || *q > 1.0e0)) goto S100;
+    if(!(*q < 0.0e0)) goto S80;
+    *bound = 0.0e0;
+    goto S90;
+S80:
+    *bound = 1.0e0;
+S90:
+    *status = -3;
+    return;
+S110:
+S100:
+    if(*which == 2) goto S150;
+/*
+     X
+*/
+    if(!(*x < 0.0e0 || *x > 1.0e0)) goto S140;
+    if(!(*x < 0.0e0)) goto S120;
+    *bound = 0.0e0;
+    goto S130;
+S120:
+    *bound = 1.0e0;
+S130:
+    *status = -4;
+    return;
+S150:
+S140:
+    if(*which == 2) goto S190;
+/*
+     Y
+*/
+    if(!(*y < 0.0e0 || *y > 1.0e0)) goto S180;
+    if(!(*y < 0.0e0)) goto S160;
+    *bound = 0.0e0;
+    goto S170;
+S160:
+    *bound = 1.0e0;
+S170:
+    *status = -5;
+    return;
+S190:
+S180:
+    if(*which == 3) goto S210;
+/*
+     A
+*/
+    if(!(*a <= 0.0e0)) goto S200;
+    *bound = 0.0e0;
+    *status = -6;
+    return;
+S210:
+S200:
+    if(*which == 4) goto S230;
+/*
+     B
+*/
+    if(!(*b <= 0.0e0)) goto S220;
+    *bound = 0.0e0;
+    *status = -7;
+    return;
+S230:
+S220:
+    if(*which == 1) goto S270;
+/*
+     P + Q
+*/
+    pq = *p+*q;
+    if(!(fabs(pq-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S260;
+    if(!(pq < 0.0e0)) goto S240;
+    *bound = 0.0e0;
+    goto S250;
+S240:
+    *bound = 1.0e0;
+S250:
+    *status = 3;
+    return;
+S270:
+S260:
+    if(*which == 2) goto S310;
+/*
+     X + Y
+*/
+    xy = *x+*y;
+    if(!(fabs(xy-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S300;
+    if(!(xy < 0.0e0)) goto S280;
+    *bound = 0.0e0;
+    goto S290;
+S280:
+    *bound = 1.0e0;
+S290:
+    *status = 4;
+    return;
+S310:
+S300:
+    if(!(*which == 1)) qporq = *p <= *q;
+/*
+     Select the minimum of P or Q
+     Calculate ANSWERS
+*/
+    if(1 == *which) {
+/*
+     Calculating P and Q
+*/
+        cumbet(x,y,a,b,p,q);
+        *status = 0;
+    }
+    else if(2 == *which) {
+/*
+     Calculating X and Y
+*/
+        T4 = atol;
+        T5 = tol;
+        dstzr(&K2,&K3,&T4,&T5);
+        if(!qporq) goto S340;
+        *status = 0;
+        dzror(status,x,&fx,&xlo,&xhi,&qleft,&qhi);
+        *y = one-*x;
+S320:
+        if(!(*status == 1)) goto S330;
+        cumbet(x,y,a,b,&cum,&ccum);
+        fx = cum-*p;
+        dzror(status,x,&fx,&xlo,&xhi,&qleft,&qhi);
+        *y = one-*x;
+        goto S320;
+S330:
+        goto S370;
+S340:
+        *status = 0;
+        dzror(status,y,&fx,&xlo,&xhi,&qleft,&qhi);
+        *x = one-*y;
+S350:
+        if(!(*status == 1)) goto S360;
+        cumbet(x,y,a,b,&cum,&ccum);
+        fx = ccum-*q;
+        dzror(status,y,&fx,&xlo,&xhi,&qleft,&qhi);
+        *x = one-*y;
+        goto S350;
+S370:
+S360:
+        if(!(*status == -1)) goto S400;
+        if(!qleft) goto S380;
+        *status = 1;
+        *bound = 0.0e0;
+        goto S390;
+S380:
+        *status = 2;
+        *bound = 1.0e0;
+S400:
+S390:
+        ;
+    }
+    else if(3 == *which) {
+/*
+     Computing A
+*/
+        *a = 5.0e0;
+        T6 = zero;
+        T7 = inf;
+        T10 = atol;
+        T11 = tol;
+        dstinv(&T6,&T7,&K8,&K8,&K9,&T10,&T11);
+        *status = 0;
+        dinvr(status,a,&fx,&qleft,&qhi);
+S410:
+        if(!(*status == 1)) goto S440;
+        cumbet(x,y,a,b,&cum,&ccum);
+        if(!qporq) goto S420;
+        fx = cum-*p;
+        goto S430;
+S420:
+        fx = ccum-*q;
+S430:
+        dinvr(status,a,&fx,&qleft,&qhi);
+        goto S410;
+S440:
+        if(!(*status == -1)) goto S470;
+        if(!qleft) goto S450;
+        *status = 1;
+        *bound = zero;
+        goto S460;
+S450:
+        *status = 2;
+        *bound = inf;
+S470:
+S460:
+        ;
+    }
+    else if(4 == *which) {
+/*
+     Computing B
+*/
+        *b = 5.0e0;
+        T12 = zero;
+        T13 = inf;
+        T14 = atol;
+        T15 = tol;
+        dstinv(&T12,&T13,&K8,&K8,&K9,&T14,&T15);
+        *status = 0;
+        dinvr(status,b,&fx,&qleft,&qhi);
+S480:
+        if(!(*status == 1)) goto S510;
+        cumbet(x,y,a,b,&cum,&ccum);
+        if(!qporq) goto S490;
+        fx = cum-*p;
+        goto S500;
+S490:
+        fx = ccum-*q;
+S500:
+        dinvr(status,b,&fx,&qleft,&qhi);
+        goto S480;
+S510:
+        if(!(*status == -1)) goto S540;
+        if(!qleft) goto S520;
+        *status = 1;
+        *bound = zero;
+        goto S530;
+S520:
+        *status = 2;
+        *bound = inf;
+S530:
+        ;
+    }
+S540:
+    return;
+#undef tol
+#undef atol
+#undef zero
+#undef inf
+#undef one
+} /* END */
+
+/***=====================================================================***/
+static void cdfbin(int *which,double *p,double *q,double *s,double *xn,
+        double *pr,double *ompr,int *status,double *bound)
+/**********************************************************************
+
+      void cdfbin(int *which,double *p,double *q,double *s,double *xn,
+            double *pr,double *ompr,int *status,double *bound)
+
+               Cumulative Distribution Function
+                         BINomial distribution
+
+
+                              Function
+
+
+     Calculates any one parameter of the binomial
+     distribution given values for the others.
+
+
+                              Arguments
+
+
+     WHICH --> Integer indicating which of the next four argument
+               values is to be calculated from the others.
+               Legal range: 1..4
+               iwhich = 1 : Calculate P and Q from S,XN,PR and OMPR
+               iwhich = 2 : Calculate S from P,Q,XN,PR and OMPR
+               iwhich = 3 : Calculate XN from P,Q,S,PR and OMPR
+               iwhich = 4 : Calculate PR and OMPR from P,Q,S and XN
+
+     P <--> The cumulation from 0 to S of the binomial distribution.
+            (Probablility of S or fewer successes in XN trials each
+            with probability of success PR.)
+            Input range: [0,1].
+
+     Q <--> 1-P.
+            Input range: [0, 1].
+            P + Q = 1.0.
+
+     S <--> The number of successes observed.
+            Input range: [0, XN]
+            Search range: [0, XN]
+
+     XN  <--> The number of binomial trials.
+              Input range: (0, +infinity).
+              Search range: [1E-300, 1E300]
+
+     PR  <--> The probability of success in each binomial trial.
+              Input range: [0,1].
+              Search range: [0,1]
+
+     OMPR  <--> 1-PR
+              Input range: [0,1].
+              Search range: [0,1]
+              PR + OMPR = 1.0
+
+     STATUS <-- 0 if calculation completed correctly
+               -I if input parameter number I is out of range
+                1 if answer appears to be lower than lowest
+                  search bound
+                2 if answer appears to be higher than greatest
+                  search bound
+                3 if P + Q .ne. 1
+                4 if PR + OMPR .ne. 1
+
+     BOUND <-- Undefined if STATUS is 0
+
+               Bound exceeded by parameter number I if STATUS
+               is negative.
+
+               Lower search bound if STATUS is 1.
+
+               Upper search bound if STATUS is 2.
+
+
+                              Method
+
+
+     Formula  26.5.24    of   Abramowitz  and    Stegun,  Handbook   of
+     Mathematical   Functions (1966) is   used  to reduce the  binomial
+     distribution  to  the  cumulative incomplete    beta distribution.
+
+     Computation of other parameters involve a seach for a value that
+     produces  the desired  value  of P.   The search relies  on  the
+     monotinicity of P with the other parameter.
+
+
+**********************************************************************/
+{
+#define atol (1.0e-50)
+#define tol (1.0e-8)
+#define zero (1.0e-300)
+#define inf 1.0e300
+#define one 1.0e0
+static int K1 = 1;
+static double K2 = 0.0e0;
+static double K3 = 0.5e0;
+static double K4 = 5.0e0;
+static double K11 = 1.0e0;
+static double fx,xhi,xlo,cum,ccum,pq,prompr;
+static unsigned long qhi,qleft,qporq;
+static double T5,T6,T7,T8,T9,T10,T12,T13;
+/*
+     ..
+     .. Executable Statements ..
+*/
+/*
+     Check arguments
+*/
+    if(!(*which < 1 && *which > 4)) goto S30;
+    if(!(*which < 1)) goto S10;
+    *bound = 1.0e0;
+    goto S20;
+S10:
+    *bound = 4.0e0;
+S20:
+    *status = -1;
+    return;
+S30:
+    if(*which == 1) goto S70;
+/*
+     P
+*/
+    if(!(*p < 0.0e0 || *p > 1.0e0)) goto S60;
+    if(!(*p < 0.0e0)) goto S40;
+    *bound = 0.0e0;
+    goto S50;
+S40:
+    *bound = 1.0e0;
+S50:
+    *status = -2;
+    return;
+S70:
+S60:
+    if(*which == 1) goto S110;
+/*
+     Q
+*/
+    if(!(*q < 0.0e0 || *q > 1.0e0)) goto S100;
+    if(!(*q < 0.0e0)) goto S80;
+    *bound = 0.0e0;
+    goto S90;
+S80:
+    *bound = 1.0e0;
+S90:
+    *status = -3;
+    return;
+S110:
+S100:
+    if(*which == 3) goto S130;
+/*
+     XN
+*/
+    if(!(*xn <= 0.0e0)) goto S120;
+    *bound = 0.0e0;
+    *status = -5;
+    return;
+S130:
+S120:
+    if(*which == 2) goto S170;
+/*
+     S
+*/
+    if(!(*s < 0.0e0 || *which != 3 && *s > *xn)) goto S160;
+    if(!(*s < 0.0e0)) goto S140;
+    *bound = 0.0e0;
+    goto S150;
+S140:
+    *bound = *xn;
+S150:
+    *status = -4;
+    return;
+S170:
+S160:
+    if(*which == 4) goto S210;
+/*
+     PR
+*/
+    if(!(*pr < 0.0e0 || *pr > 1.0e0)) goto S200;
+    if(!(*pr < 0.0e0)) goto S180;
+    *bound = 0.0e0;
+    goto S190;
+S180:
+    *bound = 1.0e0;
+S190:
+    *status = -6;
+    return;
+S210:
+S200:
+    if(*which == 4) goto S250;
+/*
+     OMPR
+*/
+    if(!(*ompr < 0.0e0 || *ompr > 1.0e0)) goto S240;
+    if(!(*ompr < 0.0e0)) goto S220;
+    *bound = 0.0e0;
+    goto S230;
+S220:
+    *bound = 1.0e0;
+S230:
+    *status = -7;
+    return;
+S250:
+S240:
+    if(*which == 1) goto S290;
+/*
+     P + Q
+*/
+    pq = *p+*q;
+    if(!(fabs(pq-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S280;
+    if(!(pq < 0.0e0)) goto S260;
+    *bound = 0.0e0;
+    goto S270;
+S260:
+    *bound = 1.0e0;
+S270:
+    *status = 3;
+    return;
+S290:
+S280:
+    if(*which == 4) goto S330;
+/*
+     PR + OMPR
+*/
+    prompr = *pr+*ompr;
+    if(!(fabs(prompr-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S320;
+    if(!(prompr < 0.0e0)) goto S300;
+    *bound = 0.0e0;
+    goto S310;
+S300:
+    *bound = 1.0e0;
+S310:
+    *status = 4;
+    return;
+S330:
+S320:
+    if(!(*which == 1)) qporq = *p <= *q;
+/*
+     Select the minimum of P or Q
+     Calculate ANSWERS
+*/
+    if(1 == *which) {
+/*
+     Calculating P
+*/
+        cumbin(s,xn,pr,ompr,p,q);
+        *status = 0;
+    }
+    else if(2 == *which) {
+/*
+     Calculating S
+*/
+        *s = 5.0e0;
+        T5 = atol;
+        T6 = tol;
+        dstinv(&K2,xn,&K3,&K3,&K4,&T5,&T6);
+        *status = 0;
+        dinvr(status,s,&fx,&qleft,&qhi);
+S340:
+        if(!(*status == 1)) goto S370;
+        cumbin(s,xn,pr,ompr,&cum,&ccum);
+        if(!qporq) goto S350;
+        fx = cum-*p;
+        goto S360;
+S350:
+        fx = ccum-*q;
+S360:
+        dinvr(status,s,&fx,&qleft,&qhi);
+        goto S340;
+S370:
+        if(!(*status == -1)) goto S400;
+        if(!qleft) goto S380;
+        *status = 1;
+        *bound = 0.0e0;
+        goto S390;
+S380:
+        *status = 2;
+        *bound = *xn;
+S400:
+S390:
+        ;
+    }
+    else if(3 == *which) {
+/*
+     Calculating XN
+*/
+        *xn = 5.0e0;
+        T7 = zero;
+        T8 = inf;
+        T9 = atol;
+        T10 = tol;
+        dstinv(&T7,&T8,&K3,&K3,&K4,&T9,&T10);
+        *status = 0;
+        dinvr(status,xn,&fx,&qleft,&qhi);
+S410:
+        if(!(*status == 1)) goto S440;
+        cumbin(s,xn,pr,ompr,&cum,&ccum);
+        if(!qporq) goto S420;
+        fx = cum-*p;
+        goto S430;
+S420:
+        fx = ccum-*q;
+S430:
+        dinvr(status,xn,&fx,&qleft,&qhi);
+        goto S410;
+S440:
+        if(!(*status == -1)) goto S470;
+        if(!qleft) goto S450;
+        *status = 1;
+        *bound = zero;
+        goto S460;
+S450:
+        *status = 2;
+        *bound = inf;
+S470:
+S460:
+        ;
+    }
+    else if(4 == *which) {
+/*
+     Calculating PR and OMPR
+*/
+        T12 = atol;
+        T13 = tol;
+        dstzr(&K2,&K11,&T12,&T13);
+        if(!qporq) goto S500;
+        *status = 0;
+        dzror(status,pr,&fx,&xlo,&xhi,&qleft,&qhi);
+        *ompr = one-*pr;
+S480:
+        if(!(*status == 1)) goto S490;
+        cumbin(s,xn,pr,ompr,&cum,&ccum);
+        fx = cum-*p;
+        dzror(status,pr,&fx,&xlo,&xhi,&qleft,&qhi);
+        *ompr = one-*pr;
+        goto S480;
+S490:
+        goto S530;
+S500:
+        *status = 0;
+        dzror(status,ompr,&fx,&xlo,&xhi,&qleft,&qhi);
+        *pr = one-*ompr;
+S510:
+        if(!(*status == 1)) goto S520;
+        cumbin(s,xn,pr,ompr,&cum,&ccum);
+        fx = ccum-*q;
+        dzror(status,ompr,&fx,&xlo,&xhi,&qleft,&qhi);
+        *pr = one-*ompr;
+        goto S510;
+S530:
+S520:
+        if(!(*status == -1)) goto S560;
+        if(!qleft) goto S540;
+        *status = 1;
+        *bound = 0.0e0;
+        goto S550;
+S540:
+        *status = 2;
+        *bound = 1.0e0;
+S550:
+        ;
+    }
+S560:
+    return;
+#undef atol
+#undef tol
+#undef zero
+#undef inf
+#undef one
+} /* END */
+
+/***=====================================================================***/
+static void cdfchi(int *which,double *p,double *q,double *x,double *df,
+        int *status,double *bound)
+/**********************************************************************
+
+      void cdfchi(int *which,double *p,double *q,double *x,double *df,
+            int *status,double *bound)
+
+               Cumulative Distribution Function
+               CHI-Square distribution
+
+
+                              Function
+
+
+     Calculates any one parameter of the chi-square
+     distribution given values for the others.
+
+
+                              Arguments
+
+
+     WHICH --> Integer indicating which of the next three argument
+               values is to be calculated from the others.
+               Legal range: 1..3
+               iwhich = 1 : Calculate P and Q from X and DF
+               iwhich = 2 : Calculate X from P,Q and DF
+               iwhich = 3 : Calculate DF from P,Q and X
+
+     P <--> The integral from 0 to X of the chi-square
+            distribution.
+            Input range: [0, 1].
+
+     Q <--> 1-P.
+            Input range: (0, 1].
+            P + Q = 1.0.
+
+     X <--> Upper limit of integration of the non-central
+            chi-square distribution.
+            Input range: [0, +infinity).
+            Search range: [0,1E300]
+
+     DF <--> Degrees of freedom of the
+             chi-square distribution.
+             Input range: (0, +infinity).
+             Search range: [ 1E-300, 1E300]
+
+     STATUS <-- 0 if calculation completed correctly
+               -I if input parameter number I is out of range
+                1 if answer appears to be lower than lowest
+                  search bound
+                2 if answer appears to be higher than greatest
+                  search bound
+                3 if P + Q .ne. 1
+               10 indicates error returned from cumgam.  See
+                  references in cdfgam
+
+     BOUND <-- Undefined if STATUS is 0
+
+               Bound exceeded by parameter number I if STATUS
+               is negative.
+
+               Lower search bound if STATUS is 1.
+
+               Upper search bound if STATUS is 2.
+
+
+                              Method
+
+
+     Formula    26.4.19   of Abramowitz  and     Stegun, Handbook  of
+     Mathematical Functions   (1966) is used   to reduce the chisqure
+     distribution to the incomplete distribution.
+
+     Computation of other parameters involve a seach for a value that
+     produces  the desired  value  of P.   The search relies  on  the
+     monotinicity of P with the other parameter.
+
+**********************************************************************/
+{
+#define tol (1.0e-8)
+#define atol (1.0e-50)
+#define zero (1.0e-300)
+#define inf 1.0e300
+static int K1 = 1;
+static double K2 = 0.0e0;
+static double K4 = 0.5e0;
+static double K5 = 5.0e0;
+static double fx,cum,ccum,pq,porq;
+static unsigned long qhi,qleft,qporq;
+static double T3,T6,T7,T8,T9,T10,T11;
+/*
+     ..
+     .. Executable Statements ..
+*/
+/*
+     Check arguments
+*/
+    if(!(*which < 1 || *which > 3)) goto S30;
+    if(!(*which < 1)) goto S10;
+    *bound = 1.0e0;
+    goto S20;
+S10:
+    *bound = 3.0e0;
+S20:
+    *status = -1;
+    return;
+S30:
+    if(*which == 1) goto S70;
+/*
+     P
+*/
+    if(!(*p < 0.0e0 || *p > 1.0e0)) goto S60;
+    if(!(*p < 0.0e0)) goto S40;
+    *bound = 0.0e0;
+    goto S50;
+S40:
+    *bound = 1.0e0;
+S50:
+    *status = -2;
+    return;
+S70:
+S60:
+    if(*which == 1) goto S110;
+/*
+     Q
+*/
+    if(!(*q <= 0.0e0 || *q > 1.0e0)) goto S100;
+    if(!(*q <= 0.0e0)) goto S80;
+    *bound = 0.0e0;
+    goto S90;
+S80:
+    *bound = 1.0e0;
+S90:
+    *status = -3;
+    return;
+S110:
+S100:
+    if(*which == 2) goto S130;
+/*
+     X
+*/
+    if(!(*x < 0.0e0)) goto S120;
+    *bound = 0.0e0;
+    *status = -4;
+    return;
+S130:
+S120:
+    if(*which == 3) goto S150;
+/*
+     DF
+*/
+    if(!(*df <= 0.0e0)) goto S140;
+    *bound = 0.0e0;
+    *status = -5;
+    return;
+S150:
+S140:
+    if(*which == 1) goto S190;
+/*
+     P + Q
+*/
+    pq = *p+*q;
+    if(!(fabs(pq-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S180;
+    if(!(pq < 0.0e0)) goto S160;
+    *bound = 0.0e0;
+    goto S170;
+S160:
+    *bound = 1.0e0;
+S170:
+    *status = 3;
+    return;
+S190:
+S180:
+    if(*which == 1) goto S220;
+/*
+     Select the minimum of P or Q
+*/
+    qporq = *p <= *q;
+    if(!qporq) goto S200;
+    porq = *p;
+    goto S210;
+S200:
+    porq = *q;
+S220:
+S210:
+/*
+     Calculate ANSWERS
+*/
+    if(1 == *which) {
+/*
+     Calculating P and Q
+*/
+        *status = 0;
+        cumchi(x,df,p,q);
+        if(porq > 1.5e0) {
+            *status = 10;
+            return;
+        }
+    }
+    else if(2 == *which) {
+/*
+     Calculating X
+*/
+        *x = 5.0e0;
+        T3 = inf;
+        T6 = atol;
+        T7 = tol;
+        dstinv(&K2,&T3,&K4,&K4,&K5,&T6,&T7);
+        *status = 0;
+        dinvr(status,x,&fx,&qleft,&qhi);
+S230:
+        if(!(*status == 1)) goto S270;
+        cumchi(x,df,&cum,&ccum);
+        if(!qporq) goto S240;
+        fx = cum-*p;
+        goto S250;
+S240:
+        fx = ccum-*q;
+S250:
+        if(!(fx+porq > 1.5e0)) goto S260;
+        *status = 10;
+        return;
+S260:
+        dinvr(status,x,&fx,&qleft,&qhi);
+        goto S230;
+S270:
+        if(!(*status == -1)) goto S300;
+        if(!qleft) goto S280;
+        *status = 1;
+        *bound = 0.0e0;
+        goto S290;
+S280:
+        *status = 2;
+        *bound = inf;
+S300:
+S290:
+        ;
+    }
+    else if(3 == *which) {
+/*
+     Calculating DF
+*/
+        *df = 5.0e0;
+        T8 = zero;
+        T9 = inf;
+        T10 = atol;
+        T11 = tol;
+        dstinv(&T8,&T9,&K4,&K4,&K5,&T10,&T11);
+        *status = 0;
+        dinvr(status,df,&fx,&qleft,&qhi);
+S310:
+        if(!(*status == 1)) goto S350;
+        cumchi(x,df,&cum,&ccum);
+        if(!qporq) goto S320;
+        fx = cum-*p;
+        goto S330;
+S320:
+        fx = ccum-*q;
+S330:
+        if(!(fx+porq > 1.5e0)) goto S340;
+        *status = 10;
+        return;
+S340:
+        dinvr(status,df,&fx,&qleft,&qhi);
+        goto S310;
+S350:
+        if(!(*status == -1)) goto S380;
+        if(!qleft) goto S360;
+        *status = 1;
+        *bound = zero;
+        goto S370;
+S360:
+        *status = 2;
+        *bound = inf;
+S370:
+        ;
+    }
+S380:
+    return;
+#undef tol
+#undef atol
+#undef zero
+#undef inf
+} /* END */
+
+/***=====================================================================***/
+static void cdfchn(int *which,double *p,double *q,double *x,double *df,
+        double *pnonc,int *status,double *bound)
+/**********************************************************************
+
+      void cdfchn(int *which,double *p,double *q,double *x,double *df,
+            double *pnonc,int *status,double *bound)
+
+               Cumulative Distribution Function
+               Non-central Chi-Square
+
+
+                              Function
+
+
+     Calculates any one parameter of the non-central chi-square
+     distribution given values for the others.
+
+
+                              Arguments
+
+
+     WHICH --> Integer indicating which of the next three argument
+               values is to be calculated from the others.
+               Input range: 1..4
+               iwhich = 1 : Calculate P and Q from X and DF
+               iwhich = 2 : Calculate X from P,DF and PNONC
+               iwhich = 3 : Calculate DF from P,X and PNONC
+               iwhich = 3 : Calculate PNONC from P,X and DF
+
+     P <--> The integral from 0 to X of the non-central chi-square
+            distribution.
+            Input range: [0, 1-1E-16).
+
+     Q <--> 1-P.
+            Q is not used by this subroutine and is only included
+            for similarity with other cdf* routines.
+
+     X <--> Upper limit of integration of the non-central
+            chi-square distribution.
+            Input range: [0, +infinity).
+            Search range: [0,1E300]
+
+     DF <--> Degrees of freedom of the non-central
+             chi-square distribution.
+             Input range: (0, +infinity).
+             Search range: [ 1E-300, 1E300]
+
+     PNONC <--> Non-centrality parameter of the non-central
+                chi-square distribution.
+                Input range: [0, +infinity).
+                Search range: [0,1E4]
+
+     STATUS <-- 0 if calculation completed correctly
+               -I if input parameter number I is out of range
+                1 if answer appears to be lower than lowest
+                  search bound
+                2 if answer appears to be higher than greatest
+                  search bound
+
+     BOUND <-- Undefined if STATUS is 0
+
+               Bound exceeded by parameter number I if STATUS
+               is negative.
+
+               Lower search bound if STATUS is 1.
+
+               Upper search bound if STATUS is 2.
+
+
+                              Method
+
+
+     Formula  26.4.25   of   Abramowitz   and   Stegun,  Handbook  of
+     Mathematical  Functions (1966) is used to compute the cumulative
+     distribution function.
+
+     Computation of other parameters involve a seach for a value that
+     produces  the desired  value  of P.   The search relies  on  the
+     monotinicity of P with the other parameter.
+
+
+                            WARNING
+
+     The computation time  required for this  routine is proportional
+     to the noncentrality  parameter  (PNONC).  Very large  values of
+     this parameter can consume immense  computer resources.  This is
+     why the search range is bounded by 10,000.
+
+**********************************************************************/
+{
+#define tent4 1.0e4
+#define tol (1.0e-8)
+#define atol (1.0e-50)
+#define zero (1.0e-300)
+#define one (1.0e0-1.0e-16)
+#define inf 1.0e300
+static double K1 = 0.0e0;
+static double K3 = 0.5e0;
+static double K4 = 5.0e0;
+static double fx,cum,ccum;
+static unsigned long qhi,qleft;
+static double T2,T5,T6,T7,T8,T9,T10,T11,T12,T13;
+/*
+     ..
+     .. Executable Statements ..
+*/
+/*
+     Check arguments
+*/
+    if(!(*which < 1 || *which > 4)) goto S30;
+    if(!(*which < 1)) goto S10;
+    *bound = 1.0e0;
+    goto S20;
+S10:
+    *bound = 4.0e0;
+S20:
+    *status = -1;
+    return;
+S30:
+    if(*which == 1) goto S70;
+/*
+     P
+*/
+    if(!(*p < 0.0e0 || *p > one)) goto S60;
+    if(!(*p < 0.0e0)) goto S40;
+    *bound = 0.0e0;
+    goto S50;
+S40:
+    *bound = one;
+S50:
+    *status = -2;
+    return;
+S70:
+S60:
+    if(*which == 2) goto S90;
+/*
+     X
+*/
+    if(!(*x < 0.0e0)) goto S80;
+    *bound = 0.0e0;
+    *status = -4;
+    return;
+S90:
+S80:
+    if(*which == 3) goto S110;
+/*
+     DF
+*/
+    if(!(*df <= 0.0e0)) goto S100;
+    *bound = 0.0e0;
+    *status = -5;
+    return;
+S110:
+S100:
+    if(*which == 4) goto S130;
+/*
+     PNONC
+*/
+    if(!(*pnonc < 0.0e0)) goto S120;
+    *bound = 0.0e0;
+    *status = -6;
+    return;
+S130:
+S120:
+/*
+     Calculate ANSWERS
+*/
+    if(1 == *which) {
+/*
+     Calculating P and Q
+*/
+        cumchn(x,df,pnonc,p,q);
+        *status = 0;
+    }
+    else if(2 == *which) {
+/*
+     Calculating X
+*/
+        *x = 5.0e0;
+        T2 = inf;
+        T5 = atol;
+        T6 = tol;
+        dstinv(&K1,&T2,&K3,&K3,&K4,&T5,&T6);
+        *status = 0;
+        dinvr(status,x,&fx,&qleft,&qhi);
+S140:
+        if(!(*status == 1)) goto S150;
+        cumchn(x,df,pnonc,&cum,&ccum);
+        fx = cum-*p;
+        dinvr(status,x,&fx,&qleft,&qhi);
+        goto S140;
+S150:
+        if(!(*status == -1)) goto S180;
+        if(!qleft) goto S160;
+        *status = 1;
+        *bound = 0.0e0;
+        goto S170;
+S160:
+        *status = 2;
+        *bound = inf;
+S180:
+S170:
+        ;
+    }
+    else if(3 == *which) {
+/*
+     Calculating DF
+*/
+        *df = 5.0e0;
+        T7 = zero;
+        T8 = inf;
+        T9 = atol;
+        T10 = tol;
+        dstinv(&T7,&T8,&K3,&K3,&K4,&T9,&T10);
+        *status = 0;
+        dinvr(status,df,&fx,&qleft,&qhi);
+S190:
+        if(!(*status == 1)) goto S200;
+        cumchn(x,df,pnonc,&cum,&ccum);
+        fx = cum-*p;
+        dinvr(status,df,&fx,&qleft,&qhi);
+        goto S190;
+S200:
+        if(!(*status == -1)) goto S230;
+        if(!qleft) goto S210;
+        *status = 1;
+        *bound = zero;
+        goto S220;
+S210:
+        *status = 2;
+        *bound = inf;
+S230:
+S220:
+        ;
+    }
+    else if(4 == *which) {
+/*
+     Calculating PNONC
+*/
+        *pnonc = 5.0e0;
+        T11 = tent4;
+        T12 = atol;
+        T13 = tol;
+        dstinv(&K1,&T11,&K3,&K3,&K4,&T12,&T13);
+        *status = 0;
+        dinvr(status,pnonc,&fx,&qleft,&qhi);
+S240:
+        if(!(*status == 1)) goto S250;
+        cumchn(x,df,pnonc,&cum,&ccum);
+        fx = cum-*p;
+        dinvr(status,pnonc,&fx,&qleft,&qhi);
+        goto S240;
+S250:
+        if(!(*status == -1)) goto S280;
+        if(!qleft) goto S260;
+        *status = 1;
+        *bound = zero;
+        goto S270;
+S260:
+        *status = 2;
+        *bound = tent4;
+S270:
+        ;
+    }
+S280:
+    return;
+#undef tent4
+#undef tol
+#undef atol
+#undef zero
+#undef one
+#undef inf
+} /* END */
+
+/***=====================================================================***/
+static void cdff(int *which,double *p,double *q,double *f,double *dfn,
+      double *dfd,int *status,double *bound)
+/**********************************************************************
+
+      void cdff(int *which,double *p,double *q,double *f,double *dfn,
+          double *dfd,int *status,double *bound)
+
+               Cumulative Distribution Function
+               F distribution
+
+
+                              Function
+
+
+     Calculates any one parameter of the F distribution
+     given values for the others.
+
+
+                              Arguments
+
+
+     WHICH --> Integer indicating which of the next four argument
+               values is to be calculated from the others.
+               Legal range: 1..4
+               iwhich = 1 : Calculate P and Q from F,DFN and DFD
+               iwhich = 2 : Calculate F from P,Q,DFN and DFD
+               iwhich = 3 : Calculate DFN from P,Q,F and DFD
+               iwhich = 4 : Calculate DFD from P,Q,F and DFN
+
+       P <--> The integral from 0 to F of the f-density.
+              Input range: [0,1].
+
+       Q <--> 1-P.
+              Input range: (0, 1].
+              P + Q = 1.0.
+
+       F <--> Upper limit of integration of the f-density.
+              Input range: [0, +infinity).
+              Search range: [0,1E300]
+
+     DFN < --> Degrees of freedom of the numerator sum of squares.
+               Input range: (0, +infinity).
+               Search range: [ 1E-300, 1E300]
+
+     DFD < --> Degrees of freedom of the denominator sum of squares.
+               Input range: (0, +infinity).
+               Search range: [ 1E-300, 1E300]
+
+     STATUS <-- 0 if calculation completed correctly
+               -I if input parameter number I is out of range
+                1 if answer appears to be lower than lowest
+                  search bound
+                2 if answer appears to be higher than greatest
+                  search bound
+                3 if P + Q .ne. 1
+
+     BOUND <-- Undefined if STATUS is 0
+
+               Bound exceeded by parameter number I if STATUS
+               is negative.
+
+               Lower search bound if STATUS is 1.
+
+               Upper search bound if STATUS is 2.
+
+
+                              Method
+
+
+     Formula   26.6.2   of   Abramowitz   and   Stegun,  Handbook  of
+     Mathematical  Functions (1966) is used to reduce the computation
+     of the  cumulative  distribution function for the  F  variate to
+     that of an incomplete beta.
+
+     Computation of other parameters involve a seach for a value that
+     produces  the desired  value  of P.   The search relies  on  the
+     monotinicity of P with the other parameter.
+
+                              WARNING
+
+     The value of the  cumulative  F distribution is  not necessarily
+     monotone in  either degrees of freedom.  There  thus may  be two
+     values  that  provide a given CDF  value.   This routine assumes
+     monotonicity and will find an arbitrary one of the two values.
+
+**********************************************************************/
+{
+#define tol (1.0e-8)
+#define atol (1.0e-50)
+#define zero (1.0e-300)
+#define inf 1.0e300
+static int K1 = 1;
+static double K2 = 0.0e0;
+static double K4 = 0.5e0;
+static double K5 = 5.0e0;
+static double pq,fx,cum,ccum;
+static unsigned long qhi,qleft,qporq;
+static double T3,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15;
+/*
+     ..
+     .. Executable Statements ..
+*/
+/*
+     Check arguments
+*/
+    if(!(*which < 1 || *which > 4)) goto S30;
+    if(!(*which < 1)) goto S10;
+    *bound = 1.0e0;
+    goto S20;
+S10:
+    *bound = 4.0e0;
+S20:
+    *status = -1;
+    return;
+S30:
+    if(*which == 1) goto S70;
+/*
+     P
+*/
+    if(!(*p < 0.0e0 || *p > 1.0e0)) goto S60;
+    if(!(*p < 0.0e0)) goto S40;
+    *bound = 0.0e0;
+    goto S50;
+S40:
+    *bound = 1.0e0;
+S50:
+    *status = -2;
+    return;
+S70:
+S60:
+    if(*which == 1) goto S110;
+/*
+     Q
+*/
+    if(!(*q <= 0.0e0 || *q > 1.0e0)) goto S100;
+    if(!(*q <= 0.0e0)) goto S80;
+    *bound = 0.0e0;
+    goto S90;
+S80:
+    *bound = 1.0e0;
+S90:
+    *status = -3;
+    return;
+S110:
+S100:
+    if(*which == 2) goto S130;
+/*
+     F
+*/
+    if(!(*f < 0.0e0)) goto S120;
+    *bound = 0.0e0;
+    *status = -4;
+    return;
+S130:
+S120:
+    if(*which == 3) goto S150;
+/*
+     DFN
+*/
+    if(!(*dfn <= 0.0e0)) goto S140;
+    *bound = 0.0e0;
+    *status = -5;
+    return;
+S150:
+S140:
+    if(*which == 4) goto S170;
+/*
+     DFD
+*/
+    if(!(*dfd <= 0.0e0)) goto S160;
+    *bound = 0.0e0;
+    *status = -6;
+    return;
+S170:
+S160:
+    if(*which == 1) goto S210;
+/*
+     P + Q
+*/
+    pq = *p+*q;
+    if(!(fabs(pq-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S200;
+    if(!(pq < 0.0e0)) goto S180;
+    *bound = 0.0e0;
+    goto S190;
+S180:
+    *bound = 1.0e0;
+S190:
+    *status = 3;
+    return;
+S210:
+S200:
+    if(!(*which == 1)) qporq = *p <= *q;
+/*
+     Select the minimum of P or Q
+     Calculate ANSWERS
+*/
+    if(1 == *which) {
+/*
+     Calculating P
+*/
+        cumf(f,dfn,dfd,p,q);
+        *status = 0;
+    }
+    else if(2 == *which) {
+/*
+     Calculating F
+*/
+        *f = 5.0e0;
+        T3 = inf;
+        T6 = atol;
+        T7 = tol;
+        dstinv(&K2,&T3,&K4,&K4,&K5,&T6,&T7);
+        *status = 0;
+        dinvr(status,f,&fx,&qleft,&qhi);
+S220:
+        if(!(*status == 1)) goto S250;
+        cumf(f,dfn,dfd,&cum,&ccum);
+        if(!qporq) goto S230;
+        fx = cum-*p;
+        goto S240;
+S230:
+        fx = ccum-*q;
+S240:
+        dinvr(status,f,&fx,&qleft,&qhi);
+        goto S220;
+S250:
+        if(!(*status == -1)) goto S280;
+        if(!qleft) goto S260;
+        *status = 1;
+        *bound = 0.0e0;
+        goto S270;
+S260:
+        *status = 2;
+        *bound = inf;
+S280:
+S270:
+        ;
+    }
+    else if(3 == *which) {
+/*
+     Calculating DFN
+*/
+        *dfn = 5.0e0;
+        T8 = zero;
+        T9 = inf;
+        T10 = atol;
+        T11 = tol;
+        dstinv(&T8,&T9,&K4,&K4,&K5,&T10,&T11);
+        *status = 0;
+        dinvr(status,dfn,&fx,&qleft,&qhi);
+S290:
+        if(!(*status == 1)) goto S320;
+        cumf(f,dfn,dfd,&cum,&ccum);
+        if(!qporq) goto S300;
+        fx = cum-*p;
+        goto S310;
+S300:
+        fx = ccum-*q;
+S310:
+        dinvr(status,dfn,&fx,&qleft,&qhi);
+        goto S290;
+S320:
+        if(!(*status == -1)) goto S350;
+        if(!qleft) goto S330;
+        *status = 1;
+        *bound = zero;
+        goto S340;
+S330:
+        *status = 2;
+        *bound = inf;
+S350:
+S340:
+        ;
+    }
+    else if(4 == *which) {
+/*
+     Calculating DFD
+*/
+        *dfd = 5.0e0;
+        T12 = zero;
+        T13 = inf;
+        T14 = atol;
+        T15 = tol;
+        dstinv(&T12,&T13,&K4,&K4,&K5,&T14,&T15);
+        *status = 0;
+        dinvr(status,dfd,&fx,&qleft,&qhi);
+S360:
+        if(!(*status == 1)) goto S390;
+        cumf(f,dfn,dfd,&cum,&ccum);
+        if(!qporq) goto S370;
+        fx = cum-*p;
+        goto S380;
+S370:
+        fx = ccum-*q;
+S380:
+        dinvr(status,dfd,&fx,&qleft,&qhi);
+        goto S360;
+S390:
+        if(!(*status == -1)) goto S420;
+        if(!qleft) goto S400;
+        *status = 1;
+        *bound = zero;
+        goto S410;
+S400:
+        *status = 2;
+        *bound = inf;
+S410:
+        ;
+    }
+S420:
+    return;
+#undef tol
+#undef atol
+#undef zero
+#undef inf
+} /* END */
+
+/***=====================================================================***/
+static void cdffnc(int *which,double *p,double *q,double *f,double *dfn,
+        double *dfd,double *phonc,int *status,double *bound)
+/**********************************************************************
+
+      void cdffnc(int *which,double *p,double *q,double *f,double *dfn,
+            double *dfd,double *phonc,int *status,double *bound)
+
+               Cumulative Distribution Function
+               Non-central F distribution
+
+
+                              Function
+
+
+     Calculates any one parameter of the Non-central F
+     distribution given values for the others.
+
+
+                              Arguments
+
+
+     WHICH --> Integer indicating which of the next five argument
+               values is to be calculated from the others.
+               Legal range: 1..5
+               iwhich = 1 : Calculate P and Q from F,DFN,DFD and PNONC
+               iwhich = 2 : Calculate F from P,Q,DFN,DFD and PNONC
+               iwhich = 3 : Calculate DFN from P,Q,F,DFD and PNONC
+               iwhich = 4 : Calculate DFD from P,Q,F,DFN and PNONC
+               iwhich = 5 : Calculate PNONC from P,Q,F,DFN and DFD
+
+       P <--> The integral from 0 to F of the non-central f-density.
+              Input range: [0,1-1E-16).
+
+       Q <--> 1-P.
+              Q is not used by this subroutine and is only included
+              for similarity with other cdf* routines.
+
+       F <--> Upper limit of integration of the non-central f-density.
+              Input range: [0, +infinity).
+              Search range: [0,1E300]
+
+     DFN < --> Degrees of freedom of the numerator sum of squares.
+               Input range: (0, +infinity).
+               Search range: [ 1E-300, 1E300]
+
+     DFD < --> Degrees of freedom of the denominator sum of squares.
+               Must be in range: (0, +infinity).
+               Input range: (0, +infinity).
+               Search range: [ 1E-300, 1E300]
+
+     PNONC <-> The non-centrality parameter
+               Input range: [0,infinity)
+               Search range: [0,1E4]
+
+     STATUS <-- 0 if calculation completed correctly
+               -I if input parameter number I is out of range
+                1 if answer appears to be lower than lowest
+                  search bound
+                2 if answer appears to be higher than greatest
+                  search bound
+                3 if P + Q .ne. 1
+
+     BOUND <-- Undefined if STATUS is 0
+
+               Bound exceeded by parameter number I if STATUS
+               is negative.
+
+               Lower search bound if STATUS is 1.
+
+               Upper search bound if STATUS is 2.
+
+
+                              Method
+
+
+     Formula  26.6.20   of   Abramowitz   and   Stegun,  Handbook  of
+     Mathematical  Functions (1966) is used to compute the cumulative
+     distribution function.
+
+     Computation of other parameters involve a seach for a value that
+     produces  the desired  value  of P.   The search relies  on  the
+     monotinicity of P with the other parameter.
+
+                            WARNING
+
+     The computation time  required for this  routine is proportional
+     to the noncentrality  parameter  (PNONC).  Very large  values of
+     this parameter can consume immense  computer resources.  This is
+     why the search range is bounded by 10,000.
+
+                              WARNING
+
+     The  value  of the  cumulative  noncentral F distribution is not
+     necessarily monotone in either degrees  of freedom.  There  thus
+     may be two values that provide a given  CDF value.  This routine
+     assumes monotonicity  and will find  an arbitrary one of the two
+     values.
+
+**********************************************************************/
+{
+#define tent4 1.0e4
+#define tol (1.0e-8)
+#define atol (1.0e-50)
+#define zero (1.0e-300)
+#define one (1.0e0-1.0e-16)
+#define inf 1.0e300
+static double K1 = 0.0e0;
+static double K3 = 0.5e0;
+static double K4 = 5.0e0;
+static double fx,cum,ccum;
+static unsigned long qhi,qleft;
+static double T2,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17;
+/*
+     ..
+     .. Executable Statements ..
+*/
+/*
+     Check arguments
+*/
+    if(!(*which < 1 || *which > 5)) goto S30;
+    if(!(*which < 1)) goto S10;
+    *bound = 1.0e0;
+    goto S20;
+S10:
+    *bound = 5.0e0;
+S20:
+    *status = -1;
+    return;
+S30:
+    if(*which == 1) goto S70;
+/*
+     P
+*/
+    if(!(*p < 0.0e0 || *p > one)) goto S60;
+    if(!(*p < 0.0e0)) goto S40;
+    *bound = 0.0e0;
+    goto S50;
+S40:
+    *bound = one;
+S50:
+    *status = -2;
+    return;
+S70:
+S60:
+    if(*which == 2) goto S90;
+/*
+     F
+*/
+    if(!(*f < 0.0e0)) goto S80;
+    *bound = 0.0e0;
+    *status = -4;
+    return;
+S90:
+S80:
+    if(*which == 3) goto S110;
+/*
+     DFN
+*/
+    if(!(*dfn <= 0.0e0)) goto S100;
+    *bound = 0.0e0;
+    *status = -5;
+    return;
+S110:
+S100:
+    if(*which == 4) goto S130;
+/*
+     DFD
+*/
+    if(!(*dfd <= 0.0e0)) goto S120;
+    *bound = 0.0e0;
+    *status = -6;
+    return;
+S130:
+S120:
+    if(*which == 5) goto S150;
+/*
+     PHONC
+*/
+    if(!(*phonc < 0.0e0)) goto S140;
+    *bound = 0.0e0;
+    *status = -7;
+    return;
+S150:
+S140:
+/*
+     Calculate ANSWERS
+*/
+    if(1 == *which) {
+/*
+     Calculating P
+*/
+        cumfnc(f,dfn,dfd,phonc,p,q);
+        *status = 0;
+    }
+    else if(2 == *which) {
+/*
+     Calculating F
+*/
+        *f = 5.0e0;
+        T2 = inf;
+        T5 = atol;
+        T6 = tol;
+        dstinv(&K1,&T2,&K3,&K3,&K4,&T5,&T6);
+        *status = 0;
+        dinvr(status,f,&fx,&qleft,&qhi);
+S160:
+        if(!(*status == 1)) goto S170;
+        cumfnc(f,dfn,dfd,phonc,&cum,&ccum);
+        fx = cum-*p;
+        dinvr(status,f,&fx,&qleft,&qhi);
+        goto S160;
+S170:
+        if(!(*status == -1)) goto S200;
+        if(!qleft) goto S180;
+        *status = 1;
+        *bound = 0.0e0;
+        goto S190;
+S180:
+        *status = 2;
+        *bound = inf;
+S200:
+S190:
+        ;
+    }
+    else if(3 == *which) {
+/*
+     Calculating DFN
+*/
+        *dfn = 5.0e0;
+        T7 = zero;
+        T8 = inf;
+        T9 = atol;
+        T10 = tol;
+        dstinv(&T7,&T8,&K3,&K3,&K4,&T9,&T10);
+        *status = 0;
+        dinvr(status,dfn,&fx,&qleft,&qhi);
+S210:
+        if(!(*status == 1)) goto S220;
+        cumfnc(f,dfn,dfd,phonc,&cum,&ccum);
+        fx = cum-*p;
+        dinvr(status,dfn,&fx,&qleft,&qhi);
+        goto S210;
+S220:
+        if(!(*status == -1)) goto S250;
+        if(!qleft) goto S230;
+        *status = 1;
+        *bound = zero;
+        goto S240;
+S230:
+        *status = 2;
+        *bound = inf;
+S250:
+S240:
+        ;
+    }
+    else if(4 == *which) {
+/*
+     Calculating DFD
+*/
+        *dfd = 5.0e0;
+        T11 = zero;
+        T12 = inf;
+        T13 = atol;
+        T14 = tol;
+        dstinv(&T11,&T12,&K3,&K3,&K4,&T13,&T14);
+        *status = 0;
+        dinvr(status,dfd,&fx,&qleft,&qhi);
+S260:
+        if(!(*status == 1)) goto S270;
+        cumfnc(f,dfn,dfd,phonc,&cum,&ccum);
+        fx = cum-*p;
+        dinvr(status,dfd,&fx,&qleft,&qhi);
+        goto S260;
+S270:
+        if(!(*status == -1)) goto S300;
+        if(!qleft) goto S280;
+        *status = 1;
+        *bound = zero;
+        goto S290;
+S280:
+        *status = 2;
+        *bound = inf;
+S300:
+S290:
+        ;
+    }
+    else if(5 == *which) {
+/*
+     Calculating PHONC
+*/
+        *phonc = 5.0e0;
+        T15 = tent4;
+        T16 = atol;
+        T17 = tol;
+        dstinv(&K1,&T15,&K3,&K3,&K4,&T16,&T17);
+        *status = 0;
+        dinvr(status,phonc,&fx,&qleft,&qhi);
+S310:
+        if(!(*status == 1)) goto S320;
+        cumfnc(f,dfn,dfd,phonc,&cum,&ccum);
+        fx = cum-*p;
+        dinvr(status,phonc,&fx,&qleft,&qhi);
+        goto S310;
+S320:
+        if(!(*status == -1)) goto S350;
+        if(!qleft) goto S330;
+        *status = 1;
+        *bound = 0.0e0;
+        goto S340;
+S330:
+        *status = 2;
+        *bound = tent4;
+S340:
+        ;
+    }
+S350:
+    return;
+#undef tent4
+#undef tol
+#undef atol
+#undef zero
+#undef one
+#undef inf
+} /* END */
+
+/***=====================================================================***/
+static void cdfgam(int *which,double *p,double *q,double *x,double *shape,
+        double *scale,int *status,double *bound)
+/**********************************************************************
+
+      void cdfgam(int *which,double *p,double *q,double *x,double *shape,
+            double *scale,int *status,double *bound)
+
+               Cumulative Distribution Function
+                         GAMma Distribution
+
+
+                              Function
+
+
+     Calculates any one parameter of the gamma
+     distribution given values for the others.
+
+
+                              Arguments
+
+
+     WHICH --> Integer indicating which of the next four argument
+               values is to be calculated from the others.
+               Legal range: 1..4
+               iwhich = 1 : Calculate P and Q from X,SHAPE and SCALE
+               iwhich = 2 : Calculate X from P,Q,SHAPE and SCALE
+               iwhich = 3 : Calculate SHAPE from P,Q,X and SCALE
+               iwhich = 4 : Calculate SCALE from P,Q,X and SHAPE
+
+     P <--> The integral from 0 to X of the gamma density.
+            Input range: [0,1].
+
+     Q <--> 1-P.
+            Input range: (0, 1].
+            P + Q = 1.0.
+
+     X <--> The upper limit of integration of the gamma density.
+            Input range: [0, +infinity).
+            Search range: [0,1E300]
+
+     SHAPE <--> The shape parameter of the gamma density.
+                Input range: (0, +infinity).
+                Search range: [1E-300,1E300]
+
+     SCALE <--> The scale parameter of the gamma density.
+                Input range: (0, +infinity).
+                Search range: (1E-300,1E300]
+
+     STATUS <-- 0 if calculation completed correctly
+               -I if input parameter number I is out of range
+                1 if answer appears to be lower than lowest
+                  search bound
+                2 if answer appears to be higher than greatest
+                  search bound
+                3 if P + Q .ne. 1
+                10 if the gamma or inverse gamma routine cannot
+                   compute the answer.  Usually happens only for
+                   X and SHAPE very large (gt 1E10 or more)
+
+     BOUND <-- Undefined if STATUS is 0
+
+               Bound exceeded by parameter number I if STATUS
+               is negative.
+
+               Lower search bound if STATUS is 1.
+
+               Upper search bound if STATUS is 2.
+
+
+                              Method
+
+
+     Cumulative distribution function (P) is calculated directly by
+     the code associated with:
+
+     DiDinato, A. R. and Morris, A. H. Computation of the  incomplete
+     gamma function  ratios  and their  inverse.   ACM  Trans.  Math.
+     Softw. 12 (1986), 377-393.
+
+     Computation of other parameters involve a seach for a value that
+     produces  the desired  value  of P.   The search relies  on  the
+     monotinicity of P with the other parameter.
+
+
+                              Note
+
+
+
+     The gamma density is proportional to
+       T**(SHAPE - 1) * EXP(- SCALE * T)
+
+**********************************************************************/
+{
+#define tol (1.0e-8)
+#define atol (1.0e-50)
+#define zero (1.0e-300)
+#define inf 1.0e300
+static int K1 = 1;
+static double K5 = 0.5e0;
+static double K6 = 5.0e0;
+static double xx,fx,xscale,cum,ccum,pq,porq;
+static int ierr;
+static unsigned long qhi,qleft,qporq;
+static double T2,T3,T4,T7,T8,T9;
+/*
+     ..
+     .. Executable Statements ..
+*/
+/*
+     Check arguments
+*/
+    if(!(*which < 1 || *which > 4)) goto S30;
+    if(!(*which < 1)) goto S10;
+    *bound = 1.0e0;
+    goto S20;
+S10:
+    *bound = 4.0e0;
+S20:
+    *status = -1;
+    return;
+S30:
+    if(*which == 1) goto S70;
+/*
+     P
+*/
+    if(!(*p < 0.0e0 || *p > 1.0e0)) goto S60;
+    if(!(*p < 0.0e0)) goto S40;
+    *bound = 0.0e0;
+    goto S50;
+S40:
+    *bound = 1.0e0;
+S50:
+    *status = -2;
+    return;
+S70:
+S60:
+    if(*which == 1) goto S110;
+/*
+     Q
+*/
+    if(!(*q <= 0.0e0 || *q > 1.0e0)) goto S100;
+    if(!(*q <= 0.0e0)) goto S80;
+    *bound = 0.0e0;
+    goto S90;
+S80:
+    *bound = 1.0e0;
+S90:
+    *status = -3;
+    return;
+S110:
+S100:
+    if(*which == 2) goto S130;
+/*
+     X
+*/
+    if(!(*x < 0.0e0)) goto S120;
+    *bound = 0.0e0;
+    *status = -4;
+    return;
+S130:
+S120:
+    if(*which == 3) goto S150;
+/*
+     SHAPE
+*/
+    if(!(*shape <= 0.0e0)) goto S140;
+    *bound = 0.0e0;
+    *status = -5;
+    return;
+S150:
+S140:
+    if(*which == 4) goto S170;
+/*
+     SCALE
+*/
+    if(!(*scale <= 0.0e0)) goto S160;
+    *bound = 0.0e0;
+    *status = -6;
+    return;
+S170:
+S160:
+    if(*which == 1) goto S210;
+/*
+     P + Q
+*/
+    pq = *p+*q;
+    if(!(fabs(pq-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S200;
+    if(!(pq < 0.0e0)) goto S180;
+    *bound = 0.0e0;
+    goto S190;
+S180:
+    *bound = 1.0e0;
+S190:
+    *status = 3;
+    return;
+S210:
+S200:
+    if(*which == 1) goto S240;
+/*
+     Select the minimum of P or Q
+*/
+    qporq = *p <= *q;
+    if(!qporq) goto S220;
+    porq = *p;
+    goto S230;
+S220:
+    porq = *q;
+S240:
+S230:
+/*
+     Calculate ANSWERS
+*/
+    if(1 == *which) {
+/*
+     Calculating P
+*/
+        *status = 0;
+        xscale = *x**scale;
+        cumgam(&xscale,shape,p,q);
+        if(porq > 1.5e0) *status = 10;
+    }
+    else if(2 == *which) {
+/*
+     Computing X
+*/
+        T2 = -1.0e0;
+        gaminv(shape,&xx,&T2,p,q,&ierr);
+        if(ierr < 0.0e0) {
+            *status = 10;
+            return;
+        }
+        else  {
+            *x = xx/ *scale;
+            *status = 0;
+        }
+    }
+    else if(3 == *which) {
+/*
+     Computing SHAPE
+*/
+        *shape = 5.0e0;
+        xscale = *x**scale;
+        T3 = zero;
+        T4 = inf;
+        T7 = atol;
+        T8 = tol;
+        dstinv(&T3,&T4,&K5,&K5,&K6,&T7,&T8);
+        *status = 0;
+        dinvr(status,shape,&fx,&qleft,&qhi);
+S250:
+        if(!(*status == 1)) goto S290;
+        cumgam(&xscale,shape,&cum,&ccum);
+        if(!qporq) goto S260;
+        fx = cum-*p;
+        goto S270;
+S260:
+        fx = ccum-*q;
+S270:
+        if(!(qporq && cum > 1.5e0 || !qporq && ccum > 1.5e0)) goto S280;
+        *status = 10;
+        return;
+S280:
+        dinvr(status,shape,&fx,&qleft,&qhi);
+        goto S250;
+S290:
+        if(!(*status == -1)) goto S320;
+        if(!qleft) goto S300;
+        *status = 1;
+        *bound = zero;
+        goto S310;
+S300:
+        *status = 2;
+        *bound = inf;
+S320:
+S310:
+        ;
+    }
+    else if(4 == *which) {
+/*
+     Computing SCALE
+*/
+        T9 = -1.0e0;
+        gaminv(shape,&xx,&T9,p,q,&ierr);
+        if(ierr < 0.0e0) {
+            *status = 10;
+            return;
+        }
+        else  {
+            *scale = xx/ *x;
+            *status = 0;
+        }
+    }
+    return;
+#undef tol
+#undef atol
+#undef zero
+#undef inf
+} /* END */
+
+/***=====================================================================***/
+static void cdfnbn(int *which,double *p,double *q,double *s,double *xn,
+        double *pr,double *ompr,int *status,double *bound)
+/**********************************************************************
+
+      void cdfnbn(int *which,double *p,double *q,double *s,double *xn,
+            double *pr,double *ompr,int *status,double *bound)
+
+               Cumulative Distribution Function
+               Negative BiNomial distribution
+
+
+                              Function
+
+
+     Calculates any one parameter of the negative binomial
+     distribution given values for the others.
+
+     The  cumulative  negative   binomial  distribution  returns  the
+     probability that there  will be  F or fewer failures before  the
+     XNth success in binomial trials each of which has probability of
+     success PR.
+
+     The individual term of the negative binomial is the probability of
+     S failures before XN successes and is
+          Choose( S, XN+S-1 ) * PR^(XN) * (1-PR)^S
+
+
+                              Arguments
+
+
+     WHICH --> Integer indicating which of the next four argument
+               values is to be calculated from the others.
+               Legal range: 1..4
+               iwhich = 1 : Calculate P and Q from S,XN,PR and OMPR
+               iwhich = 2 : Calculate S from P,Q,XN,PR and OMPR
+               iwhich = 3 : Calculate XN from P,Q,S,PR and OMPR
+               iwhich = 4 : Calculate PR and OMPR from P,Q,S and XN
+
+     P <--> The cumulation from 0 to S of the  negative
+            binomial distribution.
+            Input range: [0,1].
+
+     Q <--> 1-P.
+            Input range: (0, 1].
+            P + Q = 1.0.
+
+     S <--> The upper limit of cumulation of the binomial distribution.
+            There are F or fewer failures before the XNth success.
+            Input range: [0, +infinity).
+            Search range: [0, 1E300]
+
+     XN  <--> The number of successes.
+              Input range: [0, +infinity).
+              Search range: [0, 1E300]
+
+     PR  <--> The probability of success in each binomial trial.
+              Input range: [0,1].
+              Search range: [0,1].
+
+     OMPR  <--> 1-PR
+              Input range: [0,1].
+              Search range: [0,1]
+              PR + OMPR = 1.0
+
+     STATUS <-- 0 if calculation completed correctly
+               -I if input parameter number I is out of range
+                1 if answer appears to be lower than lowest
+                  search bound
+                2 if answer appears to be higher than greatest
+                  search bound
+                3 if P + Q .ne. 1
+                4 if PR + OMPR .ne. 1
+
+     BOUND <-- Undefined if STATUS is 0
+
+               Bound exceeded by parameter number I if STATUS
+               is negative.
+
+               Lower search bound if STATUS is 1.
+
+               Upper search bound if STATUS is 2.
+
+
+                              Method
+
+
+     Formula   26.5.26   of   Abramowitz  and  Stegun,  Handbook   of
+     Mathematical Functions (1966) is used  to  reduce calculation of
+     the cumulative distribution  function to that of  an  incomplete
+     beta.
+
+     Computation of other parameters involve a seach for a value that
+     produces  the desired  value  of P.   The search relies  on  the
+     monotinicity of P with the other parameter.
+
+**********************************************************************/
+{
+#define tol (1.0e-8)
+#define atol (1.0e-50)
+#define inf 1.0e300
+#define one 1.0e0
+static int K1 = 1;
+static double K2 = 0.0e0;
+static double K4 = 0.5e0;
+static double K5 = 5.0e0;
+static double K11 = 1.0e0;
+static double fx,xhi,xlo,pq,prompr,cum,ccum;
+static unsigned long qhi,qleft,qporq;
+static double T3,T6,T7,T8,T9,T10,T12,T13;
+/*
+     ..
+     .. Executable Statements ..
+*/
+/*
+     Check arguments
+*/
+    if(!(*which < 1 || *which > 4)) goto S30;
+    if(!(*which < 1)) goto S10;
+    *bound = 1.0e0;
+    goto S20;
+S10:
+    *bound = 4.0e0;
+S20:
+    *status = -1;
+    return;
+S30:
+    if(*which == 1) goto S70;
+/*
+     P
+*/
+    if(!(*p < 0.0e0 || *p > 1.0e0)) goto S60;
+    if(!(*p < 0.0e0)) goto S40;
+    *bound = 0.0e0;
+    goto S50;
+S40:
+    *bound = 1.0e0;
+S50:
+    *status = -2;
+    return;
+S70:
+S60:
+    if(*which == 1) goto S110;
+/*
+     Q
+*/
+    if(!(*q <= 0.0e0 || *q > 1.0e0)) goto S100;
+    if(!(*q <= 0.0e0)) goto S80;
+    *bound = 0.0e0;
+    goto S90;
+S80:
+    *bound = 1.0e0;
+S90:
+    *status = -3;
+    return;
+S110:
+S100:
+    if(*which == 2) goto S130;
+/*
+     S
+*/
+    if(!(*s < 0.0e0)) goto S120;
+    *bound = 0.0e0;
+    *status = -4;
+    return;
+S130:
+S120:
+    if(*which == 3) goto S150;
+/*
+     XN
+*/
+    if(!(*xn < 0.0e0)) goto S140;
+    *bound = 0.0e0;
+    *status = -5;
+    return;
+S150:
+S140:
+    if(*which == 4) goto S190;
+/*
+     PR
+*/
+    if(!(*pr < 0.0e0 || *pr > 1.0e0)) goto S180;
+    if(!(*pr < 0.0e0)) goto S160;
+    *bound = 0.0e0;
+    goto S170;
+S160:
+    *bound = 1.0e0;
+S170:
+    *status = -6;
+    return;
+S190:
+S180:
+    if(*which == 4) goto S230;
+/*
+     OMPR
+*/
+    if(!(*ompr < 0.0e0 || *ompr > 1.0e0)) goto S220;
+    if(!(*ompr < 0.0e0)) goto S200;
+    *bound = 0.0e0;
+    goto S210;
+S200:
+    *bound = 1.0e0;
+S210:
+    *status = -7;
+    return;
+S230:
+S220:
+    if(*which == 1) goto S270;
+/*
+     P + Q
+*/
+    pq = *p+*q;
+    if(!(fabs(pq-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S260;
+    if(!(pq < 0.0e0)) goto S240;
+    *bound = 0.0e0;
+    goto S250;
+S240:
+    *bound = 1.0e0;
+S250:
+    *status = 3;
+    return;
+S270:
+S260:
+    if(*which == 4) goto S310;
+/*
+     PR + OMPR
+*/
+    prompr = *pr+*ompr;
+    if(!(fabs(prompr-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S300;
+    if(!(prompr < 0.0e0)) goto S280;
+    *bound = 0.0e0;
+    goto S290;
+S280:
+    *bound = 1.0e0;
+S290:
+    *status = 4;
+    return;
+S310:
+S300:
+    if(!(*which == 1)) qporq = *p <= *q;
+/*
+     Select the minimum of P or Q
+     Calculate ANSWERS
+*/
+    if(1 == *which) {
+/*
+     Calculating P
+*/
+        cumnbn(s,xn,pr,ompr,p,q);
+        *status = 0;
+    }
+    else if(2 == *which) {
+/*
+     Calculating S
+*/
+        *s = 5.0e0;
+        T3 = inf;
+        T6 = atol;
+        T7 = tol;
+        dstinv(&K2,&T3,&K4,&K4,&K5,&T6,&T7);
+        *status = 0;
+        dinvr(status,s,&fx,&qleft,&qhi);
+S320:
+        if(!(*status == 1)) goto S350;
+        cumnbn(s,xn,pr,ompr,&cum,&ccum);
+        if(!qporq) goto S330;
+        fx = cum-*p;
+        goto S340;
+S330:
+        fx = ccum-*q;
+S340:
+        dinvr(status,s,&fx,&qleft,&qhi);
+        goto S320;
+S350:
+        if(!(*status == -1)) goto S380;
+        if(!qleft) goto S360;
+        *status = 1;
+        *bound = 0.0e0;
+        goto S370;
+S360:
+        *status = 2;
+        *bound = inf;
+S380:
+S370:
+        ;
+    }
+    else if(3 == *which) {
+/*
+     Calculating XN
+*/
+        *xn = 5.0e0;
+        T8 = inf;
+        T9 = atol;
+        T10 = tol;
+        dstinv(&K2,&T8,&K4,&K4,&K5,&T9,&T10);
+        *status = 0;
+        dinvr(status,xn,&fx,&qleft,&qhi);
+S390:
+        if(!(*status == 1)) goto S420;
+        cumnbn(s,xn,pr,ompr,&cum,&ccum);
+        if(!qporq) goto S400;
+        fx = cum-*p;
+        goto S410;
+S400:
+        fx = ccum-*q;
+S410:
+        dinvr(status,xn,&fx,&qleft,&qhi);
+        goto S390;
+S420:
+        if(!(*status == -1)) goto S450;
+        if(!qleft) goto S430;
+        *status = 1;
+        *bound = 0.0e0;
+        goto S440;
+S430:
+        *status = 2;
+        *bound = inf;
+S450:
+S440:
+        ;
+    }
+    else if(4 == *which) {
+/*
+     Calculating PR and OMPR
+*/
+        T12 = atol;
+        T13 = tol;
+        dstzr(&K2,&K11,&T12,&T13);
+        if(!qporq) goto S480;
+        *status = 0;
+        dzror(status,pr,&fx,&xlo,&xhi,&qleft,&qhi);
+        *ompr = one-*pr;
+S460:
+        if(!(*status == 1)) goto S470;
+        cumnbn(s,xn,pr,ompr,&cum,&ccum);
+        fx = cum-*p;
+        dzror(status,pr,&fx,&xlo,&xhi,&qleft,&qhi);
+        *ompr = one-*pr;
+        goto S460;
+S470:
+        goto S510;
+S480:
+        *status = 0;
+        dzror(status,ompr,&fx,&xlo,&xhi,&qleft,&qhi);
+        *pr = one-*ompr;
+S490:
+        if(!(*status == 1)) goto S500;
+        cumnbn(s,xn,pr,ompr,&cum,&ccum);
+        fx = ccum-*q;
+        dzror(status,ompr,&fx,&xlo,&xhi,&qleft,&qhi);
+        *pr = one-*ompr;
+        goto S490;
+S510:
+S500:
+        if(!(*status == -1)) goto S540;
+        if(!qleft) goto S520;
+        *status = 1;
+        *bound = 0.0e0;
+        goto S530;
+S520:
+        *status = 2;
+        *bound = 1.0e0;
+S530:
+        ;
+    }
+S540:
+    return;
+#undef tol
+#undef atol
+#undef inf
+#undef one
+} /* END */
+
+/***=====================================================================***/
+static void cdfnor(int *which,double *p,double *q,double *x,double *mean,
+        double *sd,int *status,double *bound)
+/**********************************************************************
+
+      void cdfnor(int *which,double *p,double *q,double *x,double *mean,
+            double *sd,int *status,double *bound)
+
+               Cumulative Distribution Function
+               NORmal distribution
+
+
+                              Function
+
+
+     Calculates any one parameter of the normal
+     distribution given values for the others.
+
+
+                              Arguments
+
+
+     WHICH  --> Integer indicating  which of the  next  parameter
+     values is to be calculated using values  of the others.
+     Legal range: 1..4
+               iwhich = 1 : Calculate P and Q from X,MEAN and SD
+               iwhich = 2 : Calculate X from P,Q,MEAN and SD
+               iwhich = 3 : Calculate MEAN from P,Q,X and SD
+               iwhich = 4 : Calculate SD from P,Q,X and MEAN
+
+     P <--> The integral from -infinity to X of the normal density.
+            Input range: (0,1].
+
+     Q <--> 1-P.
+            Input range: (0, 1].
+            P + Q = 1.0.
+
+     X < --> Upper limit of integration of the normal-density.
+             Input range: ( -infinity, +infinity)
+
+     MEAN <--> The mean of the normal density.
+               Input range: (-infinity, +infinity)
+
+     SD <--> Standard Deviation of the normal density.
+             Input range: (0, +infinity).
+
+     STATUS <-- 0 if calculation completed correctly
+               -I if input parameter number I is out of range
+                1 if answer appears to be lower than lowest
+                  search bound
+                2 if answer appears to be higher than greatest
+                  search bound
+                3 if P + Q .ne. 1
+
+     BOUND <-- Undefined if STATUS is 0
+
+               Bound exceeded by parameter number I if STATUS
+               is negative.
+
+               Lower search bound if STATUS is 1.
+
+               Upper search bound if STATUS is 2.
+
+
+                              Method
+
+
+
+
+     A slightly modified version of ANORM from
+
+     Cody, W.D. (1993). "ALGORITHM 715: SPECFUN - A Portabel FORTRAN
+     Package of Special Function Routines and Test Drivers"
+     acm Transactions on Mathematical Software. 19, 22-32.
+
+     is used to calulate the  cumulative standard normal distribution.
+
+     The rational functions from pages  90-95  of Kennedy and Gentle,
+     Statistical  Computing,  Marcel  Dekker, NY,  1980 are  used  as
+     starting values to Newton's Iterations which compute the inverse
+     standard normal.  Therefore no  searches  are necessary for  any
+     parameter.
+
+     For X < -15, the asymptotic expansion for the normal is used  as
+     the starting value in finding the inverse standard normal.
+     This is formula 26.2.12 of Abramowitz and Stegun.
+
+
+                              Note
+
+
+      The normal density is proportional to
+      exp( - 0.5 * (( X - MEAN)/SD)**2)
+
+**********************************************************************/
+{
+static int K1 = 1;
+static double z,pq;
+/*
+     ..
+     .. Executable Statements ..
+*/
+/*
+     Check arguments
+*/
+    *status = 0;
+    if(!(*which < 1 || *which > 4)) goto S30;
+    if(!(*which < 1)) goto S10;
+    *bound = 1.0e0;
+    goto S20;
+S10:
+    *bound = 4.0e0;
+S20:
+    *status = -1;
+    return;
+S30:
+    if(*which == 1) goto S70;
+/*
+     P
+*/
+    if(!(*p <= 0.0e0 || *p > 1.0e0)) goto S60;
+    if(!(*p <= 0.0e0)) goto S40;
+    *bound = 0.0e0;
+    goto S50;
+S40:
+    *bound = 1.0e0;
+S50:
+    *status = -2;
+    return;
+S70:
+S60:
+    if(*which == 1) goto S110;
+/*
+     Q
+*/
+    if(!(*q <= 0.0e0 || *q > 1.0e0)) goto S100;
+    if(!(*q <= 0.0e0)) goto S80;
+    *bound = 0.0e0;
+    goto S90;
+S80:
+    *bound = 1.0e0;
+S90:
+    *status = -3;
+    return;
+S110:
+S100:
+    if(*which == 1) goto S150;
+/*
+     P + Q
+*/
+    pq = *p+*q;
+    if(!(fabs(pq-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S140;
+    if(!(pq < 0.0e0)) goto S120;
+    *bound = 0.0e0;
+    goto S130;
+S120:
+    *bound = 1.0e0;
+S130:
+    *status = 3;
+    return;
+S150:
+S140:
+    if(*which == 4) goto S170;
+/*
+     SD
+*/
+    if(!(*sd <= 0.0e0)) goto S160;
+    *bound = 0.0e0;
+    *status = -6;
+    return;
+S170:
+S160:
+/*
+     Calculate ANSWERS
+*/
+    if(1 == *which) {
+/*
+     Computing P
+*/
+        z = (*x-*mean)/ *sd;
+        cumnor(&z,p,q);
+    }
+    else if(2 == *which) {
+/*
+     Computing X
+*/
+        z = dinvnr(p,q);
+        *x = *sd*z+*mean;
+    }
+    else if(3 == *which) {
+/*
+     Computing the MEAN
+*/
+        z = dinvnr(p,q);
+        *mean = *x-*sd*z;
+    }
+    else if(4 == *which) {
+/*
+     Computing SD
+*/
+        z = dinvnr(p,q);
+        *sd = (*x-*mean)/z;
+    }
+    return;
+} /* END */
+
+/***=====================================================================***/
+static void cdfpoi(int *which,double *p,double *q,double *s,double *xlam,
+        int *status,double *bound)
+/**********************************************************************
+
+      void cdfpoi(int *which,double *p,double *q,double *s,double *xlam,
+            int *status,double *bound)
+
+               Cumulative Distribution Function
+               POIsson distribution
+
+
+                              Function
+
+
+     Calculates any one parameter of the Poisson
+     distribution given values for the others.
+
+
+                              Arguments
+
+
+     WHICH --> Integer indicating which  argument
+               value is to be calculated from the others.
+               Legal range: 1..3
+               iwhich = 1 : Calculate P and Q from S and XLAM
+               iwhich = 2 : Calculate A from P,Q and XLAM
+               iwhich = 3 : Calculate XLAM from P,Q and S
+
+        P <--> The cumulation from 0 to S of the poisson density.
+               Input range: [0,1].
+
+        Q <--> 1-P.
+               Input range: (0, 1].
+               P + Q = 1.0.
+
+        S <--> Upper limit of cumulation of the Poisson.
+               Input range: [0, +infinity).
+               Search range: [0,1E300]
+
+     XLAM <--> Mean of the Poisson distribution.
+               Input range: [0, +infinity).
+               Search range: [0,1E300]
+
+     STATUS <-- 0 if calculation completed correctly
+               -I if input parameter number I is out of range
+                1 if answer appears to be lower than lowest
+                  search bound
+                2 if answer appears to be higher than greatest
+                  search bound
+                3 if P + Q .ne. 1
+
+     BOUND <-- Undefined if STATUS is 0
+
+               Bound exceeded by parameter number I if STATUS
+               is negative.
+
+               Lower search bound if STATUS is 1.
+
+               Upper search bound if STATUS is 2.
+
+
+                              Method
+
+
+     Formula   26.4.21  of   Abramowitz  and   Stegun,   Handbook  of
+     Mathematical Functions (1966) is used  to reduce the computation
+     of  the cumulative distribution function to that  of computing a
+     chi-square, hence an incomplete gamma function.
+
+     Cumulative  distribution function  (P) is  calculated  directly.
+     Computation of other parameters involve a seach for a value that
+     produces  the desired value of  P.   The  search relies  on  the
+     monotinicity of P with the other parameter.
+
+**********************************************************************/
+{
+#define tol (1.0e-8)
+#define atol (1.0e-50)
+#define inf 1.0e300
+static int K1 = 1;
+static double K2 = 0.0e0;
+static double K4 = 0.5e0;
+static double K5 = 5.0e0;
+static double fx,cum,ccum,pq;
+static unsigned long qhi,qleft,qporq;
+static double T3,T6,T7,T8,T9,T10;
+/*
+     ..
+     .. Executable Statements ..
+*/
+/*
+     Check arguments
+*/
+    if(!(*which < 1 || *which > 3)) goto S30;
+    if(!(*which < 1)) goto S10;
+    *bound = 1.0e0;
+    goto S20;
+S10:
+    *bound = 3.0e0;
+S20:
+    *status = -1;
+    return;
+S30:
+    if(*which == 1) goto S70;
+/*
+     P
+*/
+    if(!(*p < 0.0e0 || *p > 1.0e0)) goto S60;
+    if(!(*p < 0.0e0)) goto S40;
+    *bound = 0.0e0;
+    goto S50;
+S40:
+    *bound = 1.0e0;
+S50:
+    *status = -2;
+    return;
+S70:
+S60:
+    if(*which == 1) goto S110;
+/*
+     Q
+*/
+    if(!(*q <= 0.0e0 || *q > 1.0e0)) goto S100;
+    if(!(*q <= 0.0e0)) goto S80;
+    *bound = 0.0e0;
+    goto S90;
+S80:
+    *bound = 1.0e0;
+S90:
+    *status = -3;
+    return;
+S110:
+S100:
+    if(*which == 2) goto S130;
+/*
+     S
+*/
+    if(!(*s < 0.0e0)) goto S120;
+    *bound = 0.0e0;
+    *status = -4;
+    return;
+S130:
+S120:
+    if(*which == 3) goto S150;
+/*
+     XLAM
+*/
+    if(!(*xlam < 0.0e0)) goto S140;
+    *bound = 0.0e0;
+    *status = -5;
+    return;
+S150:
+S140:
+    if(*which == 1) goto S190;
+/*
+     P + Q
+*/
+    pq = *p+*q;
+    if(!(fabs(pq-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S180;
+    if(!(pq < 0.0e0)) goto S160;
+    *bound = 0.0e0;
+    goto S170;
+S160:
+    *bound = 1.0e0;
+S170:
+    *status = 3;
+    return;
+S190:
+S180:
+    if(!(*which == 1)) qporq = *p <= *q;
+/*
+     Select the minimum of P or Q
+     Calculate ANSWERS
+*/
+    if(1 == *which) {
+/*
+     Calculating P
+*/
+        cumpoi(s,xlam,p,q);
+        *status = 0;
+    }
+    else if(2 == *which) {
+/*
+     Calculating S
+*/
+        *s = 5.0e0;
+        T3 = inf;
+        T6 = atol;
+        T7 = tol;
+        dstinv(&K2,&T3,&K4,&K4,&K5,&T6,&T7);
+        *status = 0;
+        dinvr(status,s,&fx,&qleft,&qhi);
+S200:
+        if(!(*status == 1)) goto S230;
+        cumpoi(s,xlam,&cum,&ccum);
+        if(!qporq) goto S210;
+        fx = cum-*p;
+        goto S220;
+S210:
+        fx = ccum-*q;
+S220:
+        dinvr(status,s,&fx,&qleft,&qhi);
+        goto S200;
+S230:
+        if(!(*status == -1)) goto S260;
+        if(!qleft) goto S240;
+        *status = 1;
+        *bound = 0.0e0;
+        goto S250;
+S240:
+        *status = 2;
+        *bound = inf;
+S260:
+S250:
+        ;
+    }
+    else if(3 == *which) {
+/*
+     Calculating XLAM
+*/
+        *xlam = 5.0e0;
+        T8 = inf;
+        T9 = atol;
+        T10 = tol;
+        dstinv(&K2,&T8,&K4,&K4,&K5,&T9,&T10);
+        *status = 0;
+        dinvr(status,xlam,&fx,&qleft,&qhi);
+S270:
+        if(!(*status == 1)) goto S300;
+        cumpoi(s,xlam,&cum,&ccum);
+        if(!qporq) goto S280;
+        fx = cum-*p;
+        goto S290;
+S280:
+        fx = ccum-*q;
+S290:
+        dinvr(status,xlam,&fx,&qleft,&qhi);
+        goto S270;
+S300:
+        if(!(*status == -1)) goto S330;
+        if(!qleft) goto S310;
+        *status = 1;
+        *bound = 0.0e0;
+        goto S320;
+S310:
+        *status = 2;
+        *bound = inf;
+S320:
+        ;
+    }
+S330:
+    return;
+#undef tol
+#undef atol
+#undef inf
+} /* END */
+
+/***=====================================================================***/
+static void cdft(int *which,double *p,double *q,double *t,double *df,
+      int *status,double *bound)
+/**********************************************************************
+
+      void cdft(int *which,double *p,double *q,double *t,double *df,
+          int *status,double *bound)
+
+               Cumulative Distribution Function
+                         T distribution
+
+
+                              Function
+
+
+     Calculates any one parameter of the t distribution given
+     values for the others.
+
+
+                              Arguments
+
+
+     WHICH --> Integer indicating which  argument
+               values is to be calculated from the others.
+               Legal range: 1..3
+               iwhich = 1 : Calculate P and Q from T and DF
+               iwhich = 2 : Calculate T from P,Q and DF
+               iwhich = 3 : Calculate DF from P,Q and T
+
+        P <--> The integral from -infinity to t of the t-density.
+               Input range: (0,1].
+
+        Q <--> 1-P.
+               Input range: (0, 1].
+               P + Q = 1.0.
+
+        T <--> Upper limit of integration of the t-density.
+               Input range: ( -infinity, +infinity).
+               Search range: [ -1E300, 1E300 ]
+
+        DF <--> Degrees of freedom of the t-distribution.
+                Input range: (0 , +infinity).
+                Search range: [1e-300, 1E10]
+
+     STATUS <-- 0 if calculation completed correctly
+               -I if input parameter number I is out of range
+                1 if answer appears to be lower than lowest
+                  search bound
+                2 if answer appears to be higher than greatest
+                  search bound
+                3 if P + Q .ne. 1
+
+     BOUND <-- Undefined if STATUS is 0
+
+               Bound exceeded by parameter number I if STATUS
+               is negative.
+
+               Lower search bound if STATUS is 1.
+
+               Upper search bound if STATUS is 2.
+
+
+                              Method
+
+
+     Formula  26.5.27  of   Abramowitz   and  Stegun,   Handbook   of
+     Mathematical Functions  (1966) is used to reduce the computation
+     of the cumulative distribution function to that of an incomplete
+     beta.
+
+     Computation of other parameters involve a seach for a value that
+     produces  the desired  value  of P.   The search relies  on  the
+     monotinicity of P with the other parameter.
+
+**********************************************************************/
+{
+#define tol (1.0e-8)
+#define atol (1.0e-50)
+#define zero (1.0e-300)
+#define inf 1.0e300
+#define maxdf 1.0e10
+static int K1 = 1;
+static double K4 = 0.5e0;
+static double K5 = 5.0e0;
+static double fx,cum,ccum,pq;
+static unsigned long qhi,qleft,qporq;
+static double T2,T3,T6,T7,T8,T9,T10,T11;
+/*
+     ..
+     .. Executable Statements ..
+*/
+/*
+     Check arguments
+*/
+    if(!(*which < 1 || *which > 3)) goto S30;
+    if(!(*which < 1)) goto S10;
+    *bound = 1.0e0;
+    goto S20;
+S10:
+    *bound = 3.0e0;
+S20:
+    *status = -1;
+    return;
+S30:
+    if(*which == 1) goto S70;
+/*
+     P
+*/
+    if(!(*p <= 0.0e0 || *p > 1.0e0)) goto S60;
+    if(!(*p <= 0.0e0)) goto S40;
+    *bound = 0.0e0;
+    goto S50;
+S40:
+    *bound = 1.0e0;
+S50:
+    *status = -2;
+    return;
+S70:
+S60:
+    if(*which == 1) goto S110;
+/*
+     Q
+*/
+    if(!(*q <= 0.0e0 || *q > 1.0e0)) goto S100;
+    if(!(*q <= 0.0e0)) goto S80;
+    *bound = 0.0e0;
+    goto S90;
+S80:
+    *bound = 1.0e0;
+S90:
+    *status = -3;
+    return;
+S110:
+S100:
+    if(*which == 3) goto S130;
+/*
+     DF
+*/
+    if(!(*df <= 0.0e0)) goto S120;
+    *bound = 0.0e0;
+    *status = -5;
+    return;
+S130:
+S120:
+    if(*which == 1) goto S170;
+/*
+     P + Q
+*/
+    pq = *p+*q;
+    if(!(fabs(pq-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S160;
+    if(!(pq < 0.0e0)) goto S140;
+    *bound = 0.0e0;
+    goto S150;
+S140:
+    *bound = 1.0e0;
+S150:
+    *status = 3;
+    return;
+S170:
+S160:
+    if(!(*which == 1)) qporq = *p <= *q;
+/*
+     Select the minimum of P or Q
+     Calculate ANSWERS
+*/
+    if(1 == *which) {
+/*
+     Computing P and Q
+*/
+        cumt(t,df,p,q);
+        *status = 0;
+    }
+    else if(2 == *which) {
+/*
+     Computing T
+     .. Get initial approximation for T
+*/
+        *t = dt1(p,q,df);
+        T2 = -inf;
+        T3 = inf;
+        T6 = atol;
+        T7 = tol;
+        dstinv(&T2,&T3,&K4,&K4,&K5,&T6,&T7);
+        *status = 0;
+        dinvr(status,t,&fx,&qleft,&qhi);
+S180:
+        if(!(*status == 1)) goto S210;
+        cumt(t,df,&cum,&ccum);
+        if(!qporq) goto S190;
+        fx = cum-*p;
+        goto S200;
+S190:
+        fx = ccum-*q;
+S200:
+        dinvr(status,t,&fx,&qleft,&qhi);
+        goto S180;
+S210:
+        if(!(*status == -1)) goto S240;
+        if(!qleft) goto S220;
+        *status = 1;
+        *bound = -inf;
+        goto S230;
+S220:
+        *status = 2;
+        *bound = inf;
+S240:
+S230:
+        ;
+    }
+    else if(3 == *which) {
+/*
+     Computing DF
+*/
+        *df = 5.0e0;
+        T8 = zero;
+        T9 = maxdf;
+        T10 = atol;
+        T11 = tol;
+        dstinv(&T8,&T9,&K4,&K4,&K5,&T10,&T11);
+        *status = 0;
+        dinvr(status,df,&fx,&qleft,&qhi);
+S250:
+        if(!(*status == 1)) goto S280;
+        cumt(t,df,&cum,&ccum);
+        if(!qporq) goto S260;
+        fx = cum-*p;
+        goto S270;
+S260:
+        fx = ccum-*q;
+S270:
+        dinvr(status,df,&fx,&qleft,&qhi);
+        goto S250;
+S280:
+        if(!(*status == -1)) goto S310;
+        if(!qleft) goto S290;
+        *status = 1;
+        *bound = zero;
+        goto S300;
+S290:
+        *status = 2;
+        *bound = maxdf;
+S300:
+        ;
+    }
+S310:
+    return;
+#undef tol
+#undef atol
+#undef zero
+#undef inf
+#undef maxdf
+} /* END */
+
+/***=====================================================================***/
+static void cumbet(double *x,double *y,double *a,double *b,double *cum,
+        double *ccum)
+/*
+**********************************************************************
+
+     void cumbet(double *x,double *y,double *a,double *b,double *cum,
+            double *ccum)
+
+          Double precision cUMulative incomplete BETa distribution
+
+
+                              Function
+
+
+     Calculates the cdf to X of the incomplete beta distribution
+     with parameters a and b.  This is the integral from 0 to x
+     of (1/B(a,b))*f(t)) where f(t) = t**(a-1) * (1-t)**(b-1)
+
+
+                              Arguments
+
+
+     X --> Upper limit of integration.
+                                        X is DOUBLE PRECISION
+
+     Y --> 1 - X.
+                                        Y is DOUBLE PRECISION
+
+     A --> First parameter of the beta distribution.
+                                        A is DOUBLE PRECISION
+
+     B --> Second parameter of the beta distribution.
+                                        B is DOUBLE PRECISION
+
+     CUM <-- Cumulative incomplete beta distribution.
+                                        CUM is DOUBLE PRECISION
+
+     CCUM <-- Compliment of Cumulative incomplete beta distribution.
+                                        CCUM is DOUBLE PRECISION
+
+
+                              Method
+
+
+     Calls the routine BRATIO.
+
+                                   References
+
+     Didonato, Armido R. and Morris, Alfred H. Jr. (1992) Algorithim
+     708 Significant Digit Computation of the Incomplete Beta Function
+     Ratios. ACM ToMS, Vol.18, No. 3, Sept. 1992, 360-373.
+
+**********************************************************************
+*/
+{
+static int ierr;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    if(!(*x <= 0.0e0)) goto S10;
+    *cum = 0.0e0;
+    *ccum = 1.0e0;
+    return;
+S10:
+    if(!(*y <= 0.0e0)) goto S20;
+    *cum = 1.0e0;
+    *ccum = 0.0e0;
+    return;
+S20:
+    bratio(a,b,x,y,cum,ccum,&ierr);
+/*
+     Call bratio routine
+*/
+    return;
+} /* END */
+
+/***=====================================================================***/
+static void cumbin(double *s,double *xn,double *pr,double *ompr,
+        double *cum,double *ccum)
+/*
+**********************************************************************
+
+     void cumbin(double *s,double *xn,double *pr,double *ompr,
+            double *cum,double *ccum)
+
+                    CUmulative BINomial distribution
+
+
+                              Function
+
+
+     Returns the probability   of 0  to  S  successes in  XN   binomial
+     trials, each of which has a probability of success, PBIN.
+
+
+                              Arguments
+
+
+     S --> The upper limit of cumulation of the binomial distribution.
+                                                  S is DOUBLE PRECISION
+
+     XN --> The number of binomial trials.
+                                                  XN is DOUBLE PRECISIO
+
+     PBIN --> The probability of success in each binomial trial.
+                                                  PBIN is DOUBLE PRECIS
+
+     OMPR --> 1 - PBIN
+                                                  OMPR is DOUBLE PRECIS
+
+     CUM <-- Cumulative binomial distribution.
+                                                  CUM is DOUBLE PRECISI
+
+     CCUM <-- Compliment of Cumulative binomial distribution.
+                                                  CCUM is DOUBLE PRECIS
+
+
+                              Method
+
+
+     Formula  26.5.24    of   Abramowitz  and    Stegun,  Handbook   of
+     Mathematical   Functions (1966) is   used  to reduce the  binomial
+     distribution  to  the  cumulative    beta distribution.
+
+**********************************************************************
+*/
+{
+static double T1,T2;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    if(!(*s < *xn)) goto S10;
+    T1 = *s+1.0e0;
+    T2 = *xn-*s;
+    cumbet(pr,ompr,&T1,&T2,ccum,cum);
+    goto S20;
+S10:
+    *cum = 1.0e0;
+    *ccum = 0.0e0;
+S20:
+    return;
+} /* END */
+
+/***=====================================================================***/
+static void cumchi(double *x,double *df,double *cum,double *ccum)
+/*
+**********************************************************************
+
+     void cumchi(double *x,double *df,double *cum,double *ccum)
+             CUMulative of the CHi-square distribution
+
+
+                              Function
+
+
+     Calculates the cumulative chi-square distribution.
+
+
+                              Arguments
+
+
+     X       --> Upper limit of integration of the
+                 chi-square distribution.
+                                                 X is DOUBLE PRECISION
+
+     DF      --> Degrees of freedom of the
+                 chi-square distribution.
+                                                 DF is DOUBLE PRECISION
+
+     CUM <-- Cumulative chi-square distribution.
+                                                 CUM is DOUBLE PRECISIO
+
+     CCUM <-- Compliment of Cumulative chi-square distribution.
+                                                 CCUM is DOUBLE PRECISI
+
+
+                              Method
+
+
+     Calls incomplete gamma function (CUMGAM)
+
+**********************************************************************
+*/
+{
+static double a,xx;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    a = *df*0.5e0;
+    xx = *x*0.5e0;
+    cumgam(&xx,&a,cum,ccum);
+    return;
+} /* END */
+
+/***=====================================================================***/
+static void cumchn(double *x,double *df,double *pnonc,double *cum,
+        double *ccum)
+/*
+**********************************************************************
+
+     void cumchn(double *x,double *df,double *pnonc,double *cum,
+            double *ccum)
+
+             CUMulative of the Non-central CHi-square distribution
+
+
+                              Function
+
+
+     Calculates     the       cumulative      non-central    chi-square
+     distribution, i.e.,  the probability   that  a   random   variable
+     which    follows  the  non-central chi-square  distribution,  with
+     non-centrality  parameter    PNONC  and   continuous  degrees   of
+     freedom DF, is less than or equal to X.
+
+
+                              Arguments
+
+
+     X       --> Upper limit of integration of the non-central
+                 chi-square distribution.
+                                                 X is DOUBLE PRECISION
+
+     DF      --> Degrees of freedom of the non-central
+                 chi-square distribution.
+                                                 DF is DOUBLE PRECISION
+
+     PNONC   --> Non-centrality parameter of the non-central
+                 chi-square distribution.
+                                                 PNONC is DOUBLE PRECIS
+
+     CUM <-- Cumulative non-central chi-square distribution.
+                                                 CUM is DOUBLE PRECISIO
+
+     CCUM <-- Compliment of Cumulative non-central chi-square distribut
+                                                 CCUM is DOUBLE PRECISI
+
+
+                              Method
+
+
+     Uses  formula  26.4.25   of  Abramowitz  and  Stegun, Handbook  of
+     Mathematical    Functions,  US   NBS   (1966)    to calculate  the
+     non-central chi-square.
+
+
+                              Variables
+
+
+     EPS     --- Convergence criterion.  The sum stops when a
+                 term is less than EPS*SUM.
+                                                 EPS is DOUBLE PRECISIO
+
+     NTIRED  --- Maximum number of terms to be evaluated
+                 in each sum.
+                                                 NTIRED is INTEGER
+
+     QCONV   --- .TRUE. if convergence achieved -
+                 i.e., program did not stop on NTIRED criterion.
+                                                 QCONV is LOGICAL
+
+     CCUM <-- Compliment of Cumulative non-central
+              chi-square distribution.
+                                                 CCUM is DOUBLE PRECISI
+
+**********************************************************************
+*/
+{
+#define dg(i) (*df+2.0e0*(double)(i))
+#define qsmall(xx) (int)(sum < 1.0e-20 || (xx) < eps*sum)
+#define qtired(i) (int)((i) > ntired)
+static double eps = 1.0e-5;
+static int ntired = 1000;
+static double adj,centaj,centwt,chid2,dfd2,lcntaj,lcntwt,lfact,pcent,pterm,sum,
+    sumadj,term,wt,xnonc;
+static int i,icent,iterb,iterf;
+static double T1,T2,T3;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    if(!(*x <= 0.0e0)) goto S10;
+    *cum = 0.0e0;
+    *ccum = 1.0e0;
+    return;
+S10:
+    if(!(*pnonc <= 1.0e-10)) goto S20;
+/*
+     When non-centrality parameter is (essentially) zero,
+     use cumulative chi-square distribution
+*/
+    cumchi(x,df,cum,ccum);
+    return;
+S20:
+    xnonc = *pnonc/2.0e0;
+/*
+**********************************************************************
+     The following code calcualtes the weight, chi-square, and
+     adjustment term for the central term in the infinite series.
+     The central term is the one in which the poisson weight is
+     greatest.  The adjustment term is the amount that must
+     be subtracted from the chi-square to move up two degrees
+     of freedom.
+**********************************************************************
+*/
+    icent = fifidint(xnonc);
+    if(icent == 0) icent = 1;
+    chid2 = *x/2.0e0;
+/*
+     Calculate central weight term
+*/
+    T1 = (double)(icent+1);
+    lfact = alngam(&T1);
+    lcntwt = -xnonc+(double)icent*log(xnonc)-lfact;
+    centwt = exp(lcntwt);
+/*
+     Calculate central chi-square
+*/
+    T2 = dg(icent);
+    cumchi(x,&T2,&pcent,ccum);
+/*
+     Calculate central adjustment term
+*/
+    dfd2 = dg(icent)/2.0e0;
+    T3 = 1.0e0+dfd2;
+    lfact = alngam(&T3);
+    lcntaj = dfd2*log(chid2)-chid2-lfact;
+    centaj = exp(lcntaj);
+    sum = centwt*pcent;
+/*
+**********************************************************************
+     Sum backwards from the central term towards zero.
+     Quit whenever either
+     (1) the zero term is reached, or
+     (2) the term gets small relative to the sum, or
+     (3) More than NTIRED terms are totaled.
+**********************************************************************
+*/
+    iterb = 0;
+    sumadj = 0.0e0;
+    adj = centaj;
+    wt = centwt;
+    i = icent;
+    goto S40;
+S30:
+    if(qtired(iterb) || qsmall(term) || i == 0) goto S50;
+S40:
+    dfd2 = dg(i)/2.0e0;
+/*
+     Adjust chi-square for two fewer degrees of freedom.
+     The adjusted value ends up in PTERM.
+*/
+    adj = adj*dfd2/chid2;
+    sumadj += adj;
+    pterm = pcent+sumadj;
+/*
+     Adjust poisson weight for J decreased by one
+*/
+    wt *= ((double)i/xnonc);
+    term = wt*pterm;
+    sum += term;
+    i -= 1;
+    iterb += 1;
+    goto S30;
+S50:
+    iterf = 0;
+/*
+**********************************************************************
+     Now sum forward from the central term towards infinity.
+     Quit when either
+     (1) the term gets small relative to the sum, or
+     (2) More than NTIRED terms are totaled.
+**********************************************************************
+*/
+    sumadj = adj = centaj;
+    wt = centwt;
+    i = icent;
+    goto S70;
+S60:
+    if(qtired(iterf) || qsmall(term)) goto S80;
+S70:
+/*
+     Update weights for next higher J
+*/
+    wt *= (xnonc/(double)(i+1));
+/*
+     Calculate PTERM and add term to sum
+*/
+    pterm = pcent-sumadj;
+    term = wt*pterm;
+    sum += term;
+/*
+     Update adjustment term for DF for next iteration
+*/
+    i += 1;
+    dfd2 = dg(i)/2.0e0;
+    adj = adj*chid2/dfd2;
+    sumadj += adj;
+    iterf += 1;
+    goto S60;
+S80:
+    *cum = sum;
+    *ccum = 0.5e0+(0.5e0-*cum);
+    return;
+#undef dg
+#undef qsmall
+#undef qtired
+} /* END */
+
+/***=====================================================================***/
+static void cumf(double *f,double *dfn,double *dfd,double *cum,double *ccum)
+/*
+**********************************************************************
+
+     void cumf(double *f,double *dfn,double *dfd,double *cum,double *ccum)
+                    CUMulative F distribution
+
+
+                              Function
+
+
+     Computes  the  integral from  0  to  F of  the f-density  with DFN
+     and DFD degrees of freedom.
+
+
+                              Arguments
+
+
+     F --> Upper limit of integration of the f-density.
+                                                  F is DOUBLE PRECISION
+
+     DFN --> Degrees of freedom of the numerator sum of squares.
+                                                  DFN is DOUBLE PRECISI
+
+     DFD --> Degrees of freedom of the denominator sum of squares.
+                                                  DFD is DOUBLE PRECISI
+
+     CUM <-- Cumulative f distribution.
+                                                  CUM is DOUBLE PRECISI
+
+     CCUM <-- Compliment of Cumulative f distribution.
+                                                  CCUM is DOUBLE PRECIS
+
+
+                              Method
+
+
+     Formula  26.5.28 of  Abramowitz and   Stegun   is  used to  reduce
+     the cumulative F to a cumulative beta distribution.
+
+
+                              Note
+
+
+     If F is less than or equal to 0, 0 is returned.
+
+**********************************************************************
+*/
+{
+#define half 0.5e0
+#define done 1.0e0
+static double dsum,prod,xx,yy;
+static int ierr;
+static double T1,T2;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    if(!(*f <= 0.0e0)) goto S10;
+    *cum = 0.0e0;
+    *ccum = 1.0e0;
+    return;
+S10:
+    prod = *dfn**f;
+/*
+     XX is such that the incomplete beta with parameters
+     DFD/2 and DFN/2 evaluated at XX is 1 - CUM or CCUM
+     YY is 1 - XX
+     Calculate the smaller of XX and YY accurately
+*/
+    dsum = *dfd+prod;
+    xx = *dfd/dsum;
+    if(xx > half) {
+        yy = prod/dsum;
+        xx = done-yy;
+    }
+    else  yy = done-xx;
+    T1 = *dfd*half;
+    T2 = *dfn*half;
+    bratio(&T1,&T2,&xx,&yy,ccum,cum,&ierr);
+    return;
+#undef half
+#undef done
+} /* END */
+
+/***=====================================================================***/
+static void cumfnc(double *f,double *dfn,double *dfd,double *pnonc,
+        double *cum,double *ccum)
+/*
+**********************************************************************
+
+               F -NON- -C-ENTRAL F DISTRIBUTION
+
+
+
+                              Function
+
+
+     COMPUTES NONCENTRAL F DISTRIBUTION WITH DFN AND DFD
+     DEGREES OF FREEDOM AND NONCENTRALITY PARAMETER PNONC
+
+
+                              Arguments
+
+
+     X --> UPPER LIMIT OF INTEGRATION OF NONCENTRAL F IN EQUATION
+
+     DFN --> DEGREES OF FREEDOM OF NUMERATOR
+
+     DFD -->  DEGREES OF FREEDOM OF DENOMINATOR
+
+     PNONC --> NONCENTRALITY PARAMETER.
+
+     CUM <-- CUMULATIVE NONCENTRAL F DISTRIBUTION
+
+     CCUM <-- COMPLIMENT OF CUMMULATIVE
+
+
+                              Method
+
+
+     USES FORMULA 26.6.20 OF REFERENCE FOR INFINITE SERIES.
+     SERIES IS CALCULATED BACKWARD AND FORWARD FROM J = LAMBDA/2
+     (THIS IS THE TERM WITH THE LARGEST POISSON WEIGHT) UNTIL
+     THE CONVERGENCE CRITERION IS MET.
+
+     FOR SPEED, THE INCOMPLETE BETA FUNCTIONS ARE EVALUATED
+     BY FORMULA 26.5.16.
+
+
+               REFERENCE
+
+
+     HANDBOOD OF MATHEMATICAL FUNCTIONS
+     EDITED BY MILTON ABRAMOWITZ AND IRENE A. STEGUN
+     NATIONAL BUREAU OF STANDARDS APPLIED MATEMATICS SERIES - 55
+     MARCH 1965
+     P 947, EQUATIONS 26.6.17, 26.6.18
+
+
+                              Note
+
+
+     THE SUM CONTINUES UNTIL A SUCCEEDING TERM IS LESS THAN EPS
+     TIMES THE SUM (OR THE SUM IS LESS THAN 1.0E-20).  EPS IS
+     SET TO 1.0E-4 IN A DATA STATEMENT WHICH CAN BE CHANGED.
+
+**********************************************************************
+*/
+{
+#define qsmall(x) (int)(sum < 1.0e-20 || (x) < eps*sum)
+#define half 0.5e0
+#define done 1.0e0
+static double eps = 1.0e-4;
+static double dsum,dummy,prod,xx,yy,adn,aup,b,betdn,betup,centwt,dnterm,sum,
+    upterm,xmult,xnonc;
+static int i,icent,ierr;
+static double T1,T2,T3,T4,T5,T6;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    if(!(*f <= 0.0e0)) goto S10;
+    *cum = 0.0e0;
+    *ccum = 1.0e0;
+    return;
+S10:
+    if(!(*pnonc < 1.0e-10)) goto S20;
+/*
+     Handle case in which the non-centrality parameter is
+     (essentially) zero.
+*/
+    cumf(f,dfn,dfd,cum,ccum);
+    return;
+S20:
+    xnonc = *pnonc/2.0e0;
+/*
+     Calculate the central term of the poisson weighting factor.
+*/
+    icent = xnonc;
+    if(icent == 0) icent = 1;
+/*
+     Compute central weight term
+*/
+    T1 = (double)(icent+1);
+    centwt = exp(-xnonc+(double)icent*log(xnonc)-alngam(&T1));
+/*
+     Compute central incomplete beta term
+     Assure that minimum of arg to beta and 1 - arg is computed
+          accurately.
+*/
+    prod = *dfn**f;
+    dsum = *dfd+prod;
+    yy = *dfd/dsum;
+    if(yy > half) {
+        xx = prod/dsum;
+        yy = done-xx;
+    }
+    else  xx = done-yy;
+    T2 = *dfn*half+(double)icent;
+    T3 = *dfd*half;
+    bratio(&T2,&T3,&xx,&yy,&betdn,&dummy,&ierr);
+    adn = *dfn/2.0e0+(double)icent;
+    aup = adn;
+    b = *dfd/2.0e0;
+    betup = betdn;
+    sum = centwt*betdn;
+/*
+     Now sum terms backward from icent until convergence or all done
+*/
+    xmult = centwt;
+    i = icent;
+    T4 = adn+b;
+    T5 = adn+1.0e0;
+    dnterm = exp(alngam(&T4)-alngam(&T5)-alngam(&b)+adn*log(xx)+b*log(yy));
+S30:
+    if(qsmall(xmult*betdn) || i <= 0) goto S40;
+    xmult *= ((double)i/xnonc);
+    i -= 1;
+    adn -= 1.0;
+    dnterm = (adn+1.0)/((adn+b)*xx)*dnterm;
+    betdn += dnterm;
+    sum += (xmult*betdn);
+    goto S30;
+S40:
+    i = icent+1;
+/*
+     Now sum forwards until convergence
+*/
+    xmult = centwt;
+    if(aup-1.0+b == 0) upterm = exp(-alngam(&aup)-alngam(&b)+(aup-1.0)*log(xx)+
+      b*log(yy));
+    else  {
+        T6 = aup-1.0+b;
+        upterm = exp(alngam(&T6)-alngam(&aup)-alngam(&b)+(aup-1.0)*log(xx)+b*
+          log(yy));
+    }
+    goto S60;
+S50:
+    if(qsmall(xmult*betup)) goto S70;
+S60:
+    xmult *= (xnonc/(double)i);
+    i += 1;
+    aup += 1.0;
+    upterm = (aup+b-2.0e0)*xx/(aup-1.0)*upterm;
+    betup -= upterm;
+    sum += (xmult*betup);
+    goto S50;
+S70:
+    *cum = sum;
+    *ccum = 0.5e0+(0.5e0-*cum);
+    return;
+#undef qsmall
+#undef half
+#undef done
+} /* END */
+
+/***=====================================================================***/
+static void cumgam(double *x,double *a,double *cum,double *ccum)
+/*
+**********************************************************************
+
+     void cumgam(double *x,double *a,double *cum,double *ccum)
+           Double precision cUMulative incomplete GAMma distribution
+
+
+                              Function
+
+
+     Computes   the  cumulative        of    the     incomplete   gamma
+     distribution, i.e., the integral from 0 to X of
+          (1/GAM(A))*EXP(-T)*T**(A-1) DT
+     where GAM(A) is the complete gamma function of A, i.e.,
+          GAM(A) = integral from 0 to infinity of
+                    EXP(-T)*T**(A-1) DT
+
+
+                              Arguments
+
+
+     X --> The upper limit of integration of the incomplete gamma.
+                                                X is DOUBLE PRECISION
+
+     A --> The shape parameter of the incomplete gamma.
+                                                A is DOUBLE PRECISION
+
+     CUM <-- Cumulative incomplete gamma distribution.
+                                        CUM is DOUBLE PRECISION
+
+     CCUM <-- Compliment of Cumulative incomplete gamma distribution.
+                                                CCUM is DOUBLE PRECISIO
+
+
+                              Method
+
+
+     Calls the routine GRATIO.
+
+**********************************************************************
+*/
+{
+static int K1 = 0;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    if(!(*x <= 0.0e0)) goto S10;
+    *cum = 0.0e0;
+    *ccum = 1.0e0;
+    return;
+S10:
+    gratio(a,x,cum,ccum,&K1);
+/*
+     Call gratio routine
+*/
+    return;
+} /* END */
+
+/***=====================================================================***/
+static void cumnbn(double *s,double *xn,double *pr,double *ompr,
+        double *cum,double *ccum)
+/*
+**********************************************************************
+
+     void cumnbn(double *s,double *xn,double *pr,double *ompr,
+            double *cum,double *ccum)
+
+                    CUmulative Negative BINomial distribution
+
+
+                              Function
+
+
+     Returns the probability that it there will be S or fewer failures
+     before there are XN successes, with each binomial trial having
+     a probability of success PR.
+
+     Prob(# failures = S | XN successes, PR)  =
+                        ( XN + S - 1 )
+                        (            ) * PR^XN * (1-PR)^S
+                        (      S     )
+
+
+                              Arguments
+
+
+     S --> The number of failures
+                                                  S is DOUBLE PRECISION
+
+     XN --> The number of successes
+                                                  XN is DOUBLE PRECISIO
+
+     PR --> The probability of success in each binomial trial.
+                                                  PR is DOUBLE PRECISIO
+
+     OMPR --> 1 - PR
+                                                  OMPR is DOUBLE PRECIS
+
+     CUM <-- Cumulative negative binomial distribution.
+                                                  CUM is DOUBLE PRECISI
+
+     CCUM <-- Compliment of Cumulative negative binomial distribution.
+                                                  CCUM is DOUBLE PRECIS
+
+
+                              Method
+
+
+     Formula  26.5.26    of   Abramowitz  and    Stegun,  Handbook   of
+     Mathematical   Functions (1966) is   used  to reduce the  negative
+     binomial distribution to the cumulative beta distribution.
+
+**********************************************************************
+*/
+{
+static double T1;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    T1 = *s+1.e0;
+    cumbet(pr,ompr,xn,&T1,cum,ccum);
+    return;
+} /* END */
+
+/***=====================================================================***/
+static void cumnor(double *arg,double *result,double *ccum)
+/*
+**********************************************************************
+
+     void cumnor(double *arg,double *result,double *ccum)
+
+
+                              Function
+
+
+     Computes the cumulative  of    the  normal   distribution,   i.e.,
+     the integral from -infinity to x of
+          (1/sqrt(2*pi)) exp(-u*u/2) du
+
+     X --> Upper limit of integration.
+                                        X is DOUBLE PRECISION
+
+     RESULT <-- Cumulative normal distribution.
+                                        RESULT is DOUBLE PRECISION
+
+     CCUM <-- Compliment of Cumulative normal distribution.
+                                        CCUM is DOUBLE PRECISION
+
+     Renaming of function ANORM from:
+
+     Cody, W.D. (1993). "ALGORITHM 715: SPECFUN - A Portabel FORTRAN
+     Package of Special Function Routines and Test Drivers"
+     acm Transactions on Mathematical Software. 19, 22-32.
+
+     with slight modifications to return ccum and to deal with
+     machine constants.
+
+**********************************************************************
+  Original Comments:
+------------------------------------------------------------------
+
+ This function evaluates the normal distribution function:
+
+                              / x
+                     1       |       -t*t/2
+          P(x) = ----------- |      e       dt
+                 sqrt(2 pi)  |
+                             /-oo
+
+   The main computation evaluates near-minimax approximations
+   derived from those in "Rational Chebyshev approximations for
+   the error function" by W. J. Cody, Math. Comp., 1969, 631-637.
+   This transportable program uses rational functions that
+   theoretically approximate the normal distribution function to
+   at least 18 significant decimal digits.  The accuracy achieved
+   depends on the arithmetic system, the compiler, the intrinsic
+   functions, and proper selection of the machine-dependent
+   constants.
+
+*******************************************************************
+*******************************************************************
+
+ Explanation of machine-dependent constants.
+
+   MIN   = smallest machine representable number.
+
+   EPS   = argument below which anorm(x) may be represented by
+           0.5  and above which  x*x  will not underflow.
+           A conservative value is the largest machine number X
+           such that   1.0 + X = 1.0   to machine precision.
+*******************************************************************
+*******************************************************************
+
+ Error returns
+
+  The program returns  ANORM = 0     for  ARG .LE. XLOW.
+
+
+ Intrinsic functions required are:
+
+     ABS, AINT, EXP
+
+
+  Author: W. J. Cody
+          Mathematics and Computer Science Division
+          Argonne National Laboratory
+          Argonne, IL 60439
+
+  Latest modification: March 15, 1992
+
+------------------------------------------------------------------
+*/
+{
+static double a[5] = {
+    2.2352520354606839287e00,1.6102823106855587881e02,1.0676894854603709582e03,
+    1.8154981253343561249e04,6.5682337918207449113e-2
+};
+static double b[4] = {
+    4.7202581904688241870e01,9.7609855173777669322e02,1.0260932208618978205e04,
+    4.5507789335026729956e04
+};
+static double c[9] = {
+    3.9894151208813466764e-1,8.8831497943883759412e00,9.3506656132177855979e01,
+    5.9727027639480026226e02,2.4945375852903726711e03,6.8481904505362823326e03,
+    1.1602651437647350124e04,9.8427148383839780218e03,1.0765576773720192317e-8
+};
+static double d[8] = {
+    2.2266688044328115691e01,2.3538790178262499861e02,1.5193775994075548050e03,
+    6.4855582982667607550e03,1.8615571640885098091e04,3.4900952721145977266e04,
+    3.8912003286093271411e04,1.9685429676859990727e04
+};
+static double half = 0.5e0;
+static double p[6] = {
+    2.1589853405795699e-1,1.274011611602473639e-1,2.2235277870649807e-2,
+    1.421619193227893466e-3,2.9112874951168792e-5,2.307344176494017303e-2
+};
+static double one = 1.0e0;
+static double q[5] = {
+    1.28426009614491121e00,4.68238212480865118e-1,6.59881378689285515e-2,
+    3.78239633202758244e-3,7.29751555083966205e-5
+};
+static double sixten = 1.60e0;
+static double sqrpi = 3.9894228040143267794e-1;
+static double thrsh = 0.66291e0;
+static double root32 = 5.656854248e0;
+static double zero = 0.0e0;
+static int K1 = 1;
+static int K2 = 2;
+static int i;
+static double del,eps,temp,x,xden,xnum,y,xsq,min;
+/*
+------------------------------------------------------------------
+  Machine dependent constants
+------------------------------------------------------------------
+*/
+    eps = spmpar(&K1)*0.5e0;
+    min = spmpar(&K2);
+    x = *arg;
+    y = fabs(x);
+    if(y <= thrsh) {
+/*
+------------------------------------------------------------------
+  Evaluate  anorm  for  |X| <= 0.66291
+------------------------------------------------------------------
+*/
+        xsq = zero;
+        if(y > eps) xsq = x*x;
+        xnum = a[4]*xsq;
+        xden = xsq;
+        for(i=0; i<3; i++) {
+            xnum = (xnum+a[i])*xsq;
+            xden = (xden+b[i])*xsq;
+        }
+        *result = x*(xnum+a[3])/(xden+b[3]);
+        temp = *result;
+        *result = half+temp;
+        *ccum = half-temp;
+    }
+/*
+------------------------------------------------------------------
+  Evaluate  anorm  for 0.66291 <= |X| <= sqrt(32)
+------------------------------------------------------------------
+*/
+    else if(y <= root32) {
+        xnum = c[8]*y;
+        xden = y;
+        for(i=0; i<7; i++) {
+            xnum = (xnum+c[i])*y;
+            xden = (xden+d[i])*y;
+        }
+        *result = (xnum+c[7])/(xden+d[7]);
+        xsq = fifdint(y*sixten)/sixten;
+        del = (y-xsq)*(y+xsq);
+        *result = exp(-(xsq*xsq*half))*exp(-(del*half))**result;
+        *ccum = one-*result;
+        if(x > zero) {
+            temp = *result;
+            *result = *ccum;
+            *ccum = temp;
+        }
+    }
+/*
+------------------------------------------------------------------
+  Evaluate  anorm  for |X| > sqrt(32)
+------------------------------------------------------------------
+*/
+    else  {
+        *result = zero;
+        xsq = one/(x*x);
+        xnum = p[5]*xsq;
+        xden = xsq;
+        for(i=0; i<4; i++) {
+            xnum = (xnum+p[i])*xsq;
+            xden = (xden+q[i])*xsq;
+        }
+        *result = xsq*(xnum+p[4])/(xden+q[4]);
+        *result = (sqrpi-*result)/y;
+        xsq = fifdint(x*sixten)/sixten;
+        del = (x-xsq)*(x+xsq);
+        *result = exp(-(xsq*xsq*half))*exp(-(del*half))**result;
+        *ccum = one-*result;
+        if(x > zero) {
+            temp = *result;
+            *result = *ccum;
+            *ccum = temp;
+        }
+    }
+    if(*result < min) *result = 0.0e0;
+/*
+------------------------------------------------------------------
+  Fix up for negative argument, erf, etc.
+------------------------------------------------------------------
+----------Last card of ANORM ----------
+*/
+    if(*ccum < min) *ccum = 0.0e0;
+} /* END */
+
+/***=====================================================================***/
+static void cumpoi(double *s,double *xlam,double *cum,double *ccum)
+/*
+**********************************************************************
+
+     void cumpoi(double *s,double *xlam,double *cum,double *ccum)
+                    CUMulative POIsson distribution
+
+
+                              Function
+
+
+     Returns the  probability  of  S   or  fewer events in  a   Poisson
+     distribution with mean XLAM.
+
+
+                              Arguments
+
+
+     S --> Upper limit of cumulation of the Poisson.
+                                                  S is DOUBLE PRECISION
+
+     XLAM --> Mean of the Poisson distribution.
+                                                  XLAM is DOUBLE PRECIS
+
+     CUM <-- Cumulative poisson distribution.
+                                        CUM is DOUBLE PRECISION
+
+     CCUM <-- Compliment of Cumulative poisson distribution.
+                                                  CCUM is DOUBLE PRECIS
+
+
+                              Method
+
+
+     Uses formula  26.4.21   of   Abramowitz and  Stegun,  Handbook  of
+     Mathematical   Functions  to reduce   the   cumulative Poisson  to
+     the cumulative chi-square distribution.
+
+**********************************************************************
+*/
+{
+static double chi,df;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    df = 2.0e0*(*s+1.0e0);
+    chi = 2.0e0**xlam;
+    cumchi(&chi,&df,ccum,cum);
+    return;
+} /* END */
+
+/***=====================================================================***/
+static void cumt(double *t,double *df,double *cum,double *ccum)
+/*
+**********************************************************************
+
+     void cumt(double *t,double *df,double *cum,double *ccum)
+                    CUMulative T-distribution
+
+
+                              Function
+
+
+     Computes the integral from -infinity to T of the t-density.
+
+
+                              Arguments
+
+
+     T --> Upper limit of integration of the t-density.
+                                                  T is DOUBLE PRECISION
+
+     DF --> Degrees of freedom of the t-distribution.
+                                                  DF is DOUBLE PRECISIO
+
+     CUM <-- Cumulative t-distribution.
+                                                  CCUM is DOUBLE PRECIS
+
+     CCUM <-- Compliment of Cumulative t-distribution.
+                                                  CCUM is DOUBLE PRECIS
+
+
+                              Method
+
+
+     Formula 26.5.27   of     Abramowitz  and   Stegun,    Handbook  of
+     Mathematical Functions  is   used   to  reduce the  t-distribution
+     to an incomplete beta.
+
+**********************************************************************
+*/
+{
+static double K2 = 0.5e0;
+static double xx,a,oma,tt,yy,dfptt,T1;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    tt = *t**t;
+    dfptt = *df+tt;
+    xx = *df/dfptt;
+    yy = tt/dfptt;
+    T1 = 0.5e0**df;
+    cumbet(&xx,&yy,&T1,&K2,&a,&oma);
+    if(!(*t <= 0.0e0)) goto S10;
+    *cum = 0.5e0*a;
+    *ccum = oma+*cum;
+    goto S20;
+S10:
+    *ccum = 0.5e0*a;
+    *cum = oma+*ccum;
+S20:
+    return;
+} /* END */
+
+/***=====================================================================***/
+static double dbetrm(double *a,double *b)
+/*
+**********************************************************************
+
+     double dbetrm(double *a,double *b)
+          Double Precision Sterling Remainder for Complete
+                    Beta Function
+
+
+                              Function
+
+
+     Log(Beta(A,B)) = Lgamma(A) + Lgamma(B) - Lgamma(A+B)
+     where Lgamma is the log of the (complete) gamma function
+
+     Let ZZ be approximation obtained if each log gamma is approximated
+     by Sterling's formula, i.e.,
+     Sterling(Z) = LOG( SQRT( 2*PI ) ) + ( Z-0.5 ) * LOG( Z ) - Z
+
+     Returns Log(Beta(A,B)) - ZZ
+
+
+                              Arguments
+
+
+     A --> One argument of the Beta
+                    DOUBLE PRECISION A
+
+     B --> The other argument of the Beta
+                    DOUBLE PRECISION B
+
+**********************************************************************
+*/
+{
+static double dbetrm,T1,T2,T3;
+/*
+     ..
+     .. Executable Statements ..
+*/
+/*
+     Try to sum from smallest to largest
+*/
+    T1 = *a+*b;
+    dbetrm = -dstrem(&T1);
+    T2 = fifdmax1(*a,*b);
+    dbetrm += dstrem(&T2);
+    T3 = fifdmin1(*a,*b);
+    dbetrm += dstrem(&T3);
+    return dbetrm;
+} /* END */
+
+/***=====================================================================***/
+static double devlpl(double a[],int *n,double *x)
+/*
+**********************************************************************
+
+     double devlpl(double a[],int *n,double *x)
+              Double precision EVALuate a PoLynomial at X
+
+
+                              Function
+
+
+     returns
+          A(1) + A(2)*X + ... + A(N)*X**(N-1)
+
+
+                              Arguments
+
+
+     A --> Array of coefficients of the polynomial.
+                                        A is DOUBLE PRECISION(N)
+
+     N --> Length of A, also degree of polynomial - 1.
+                                        N is INTEGER
+
+     X --> Point at which the polynomial is to be evaluated.
+                                        X is DOUBLE PRECISION
+
+**********************************************************************
+*/
+{
+static double devlpl,term;
+static int i;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    term = a[*n-1];
+    for(i= *n-1-1; i>=0; i--) term = a[i]+term**x;
+    devlpl = term;
+    return devlpl;
+} /* END */
+
+/***=====================================================================***/
+static double dexpm1(double *x)
+/*
+**********************************************************************
+
+     double dexpm1(double *x)
+            Evaluation of the function EXP(X) - 1
+
+
+                              Arguments
+
+
+     X --> Argument at which exp(x)-1 desired
+                    DOUBLE PRECISION X
+
+
+                              Method
+
+
+     Renaming of function rexp from code of:
+
+     DiDinato, A. R. and Morris,  A.   H.  Algorithm 708: Significant
+     Digit Computation of the Incomplete  Beta  Function Ratios.  ACM
+     Trans. Math.  Softw. 18 (1993), 360-373.
+
+**********************************************************************
+*/
+{
+static double p1 = .914041914819518e-09;
+static double p2 = .238082361044469e-01;
+static double q1 = -.499999999085958e+00;
+static double q2 = .107141568980644e+00;
+static double q3 = -.119041179760821e-01;
+static double q4 = .595130811860248e-03;
+static double dexpm1,w;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    if(fabs(*x) > 0.15e0) goto S10;
+    dexpm1 = *x*(((p2**x+p1)**x+1.0e0)/((((q4**x+q3)**x+q2)**x+q1)**x+1.0e0));
+    return dexpm1;
+S10:
+    w = exp(*x);
+    if(*x > 0.0e0) goto S20;
+    dexpm1 = w-0.5e0-0.5e0;
+    return dexpm1;
+S20:
+    dexpm1 = w*(0.5e0+(0.5e0-1.0e0/w));
+    return dexpm1;
+} /* END */
+
+/***=====================================================================***/
+static double dinvnr(double *p,double *q)
+/*
+**********************************************************************
+
+     double dinvnr(double *p,double *q)
+     Double precision NoRmal distribution INVerse
+
+
+                              Function
+
+
+     Returns X  such that CUMNOR(X)  =   P,  i.e., the  integral from -
+     infinity to X of (1/SQRT(2*PI)) EXP(-U*U/2) dU is P
+
+
+                              Arguments
+
+
+     P --> The probability whose normal deviate is sought.
+                    P is DOUBLE PRECISION
+
+     Q --> 1-P
+                    P is DOUBLE PRECISION
+
+
+                              Method
+
+
+     The  rational   function   on  page 95    of Kennedy  and  Gentle,
+     Statistical Computing, Marcel Dekker, NY , 1980 is used as a start
+     value for the Newton method of finding roots.
+
+
+                              Note
+
+
+     If P or Q .lt. machine EPS returns +/- DINVNR(EPS)
+
+**********************************************************************
+*/
+{
+#define maxit 100
+#define eps (1.0e-13)
+#define r2pi 0.3989422804014326e0
+#define nhalf (-0.5e0)
+#define dennor(x) (r2pi*exp(nhalf*(x)*(x)))
+static double dinvnr,strtx,xcur,cum,ccum,pp,dx;
+static int i;
+static unsigned long qporq;
+/*
+     ..
+     .. Executable Statements ..
+*/
+/*
+     FIND MINIMUM OF P AND Q
+*/
+    qporq = *p <= *q;
+    if(!qporq) goto S10;
+    pp = *p;
+    goto S20;
+S10:
+    pp = *q;
+S20:
+/*
+     INITIALIZATION STEP
+*/
+    strtx = stvaln(&pp);
+    xcur = strtx;
+/*
+     NEWTON INTERATIONS
+*/
+    for(i=1; i<=maxit; i++) {
+        cumnor(&xcur,&cum,&ccum);
+        dx = (cum-pp)/dennor(xcur);
+        xcur -= dx;
+        if(fabs(dx/xcur) < eps) goto S40;
+    }
+    dinvnr = strtx;
+/*
+     IF WE GET HERE, NEWTON HAS FAILED
+*/
+    if(!qporq) dinvnr = -dinvnr;
+    return dinvnr;
+S40:
+/*
+     IF WE GET HERE, NEWTON HAS SUCCEDED
+*/
+    dinvnr = xcur;
+    if(!qporq) dinvnr = -dinvnr;
+    return dinvnr;
+#undef maxit
+#undef eps
+#undef r2pi
+#undef nhalf
+#undef dennor
+} /* END */
+
+/***=====================================================================***/
+static void E0000(int IENTRY,int *status,double *x,double *fx,
+          unsigned long *qleft,unsigned long *qhi,double *zabsst,
+          double *zabsto,double *zbig,double *zrelst,
+          double *zrelto,double *zsmall,double *zstpmu)
+{
+#define qxmon(zx,zy,zz) (int)((zx) <= (zy) && (zy) <= (zz))
+static double absstp,abstol,big,fbig,fsmall,relstp,reltol,small,step,stpmul,xhi,
+    xlb,xlo,xsave,xub,yy;
+static int i99999;
+static unsigned long qbdd,qcond,qdum1,qdum2,qincr,qlim,qok,qup;
+    switch(IENTRY){case 0: goto DINVR; case 1: goto DSTINV;}
+DINVR:
+    if(*status > 0) goto S310;
+    qcond = !qxmon(small,*x,big);
+    if(qcond){ ftnstop("SMALL,X,BIG nonmonotone in E0000"); *status=-1; return;}
+    xsave = *x;
+/*
+     See that SMALL and BIG bound the zero and set QINCR
+*/
+    *x = small;
+/*
+     GET-FUNCTION-VALUE
+*/
+    i99999 = 1;
+    goto S300;
+S10:
+    fsmall = *fx;
+    *x = big;
+/*
+     GET-FUNCTION-VALUE
+*/
+    i99999 = 2;
+    goto S300;
+S20:
+    fbig = *fx;
+    qincr = fbig > fsmall;
+    if(!qincr) goto S50;
+    if(fsmall <= 0.0e0) goto S30;
+    *status = -1;
+    *qleft = *qhi = 1;
+    return;
+S30:
+    if(fbig >= 0.0e0) goto S40;
+    *status = -1;
+    *qleft = *qhi = 0;
+    return;
+S40:
+    goto S80;
+S50:
+    if(fsmall >= 0.0e0) goto S60;
+    *status = -1;
+    *qleft = 1;
+    *qhi = 0;
+    return;
+S60:
+    if(fbig <= 0.0e0) goto S70;
+    *status = -1;
+    *qleft = 0;
+    *qhi = 1;
+    return;
+S80:
+S70:
+    *x = xsave;
+    step = fifdmax1(absstp,relstp*fabs(*x));
+/*
+      YY = F(X) - Y
+     GET-FUNCTION-VALUE
+*/
+    i99999 = 3;
+    goto S300;
+S90:
+    yy = *fx;
+    if(!(yy == 0.0e0)) goto S100;
+    *status = 0;
+    qok = 1;
+    return;
+S100:
+    qup = qincr && yy < 0.0e0 || !qincr && yy > 0.0e0;
+/*
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+     HANDLE CASE IN WHICH WE MUST STEP HIGHER
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+*/
+    if(!qup) goto S170;
+    xlb = xsave;
+    xub = fifdmin1(xlb+step,big);
+    goto S120;
+S110:
+    if(qcond) goto S150;
+S120:
+/*
+      YY = F(XUB) - Y
+*/
+    *x = xub;
+/*
+     GET-FUNCTION-VALUE
+*/
+    i99999 = 4;
+    goto S300;
+S130:
+    yy = *fx;
+    qbdd = qincr && yy >= 0.0e0 || !qincr && yy <= 0.0e0;
+    qlim = xub >= big;
+    qcond = qbdd || qlim;
+    if(qcond) goto S140;
+    step = stpmul*step;
+    xlb = xub;
+    xub = fifdmin1(xlb+step,big);
+S140:
+    goto S110;
+S150:
+    if(!(qlim && !qbdd)) goto S160;
+    *status = -1;
+    *qleft = 0;
+    *qhi = !qincr;
+    *x = big;
+    return;
+S160:
+    goto S240;
+S170:
+/*
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+     HANDLE CASE IN WHICH WE MUST STEP LOWER
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+*/
+    xub = xsave;
+    xlb = fifdmax1(xub-step,small);
+    goto S190;
+S180:
+    if(qcond) goto S220;
+S190:
+/*
+      YY = F(XLB) - Y
+*/
+    *x = xlb;
+/*
+     GET-FUNCTION-VALUE
+*/
+    i99999 = 5;
+    goto S300;
+S200:
+    yy = *fx;
+    qbdd = qincr && yy <= 0.0e0 || !qincr && yy >= 0.0e0;
+    qlim = xlb <= small;
+    qcond = qbdd || qlim;
+    if(qcond) goto S210;
+    step = stpmul*step;
+    xub = xlb;
+    xlb = fifdmax1(xub-step,small);
+S210:
+    goto S180;
+S220:
+    if(!(qlim && !qbdd)) goto S230;
+    *status = -1;
+    *qleft = 1;
+    *qhi = qincr;
+    *x = small;
+    return;
+S240:
+S230:
+    dstzr(&xlb,&xub,&abstol,&reltol);
+/*
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+     IF WE REACH HERE, XLB AND XUB BOUND THE ZERO OF F.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+*/
+    *status = 0;
+    goto S260;
+S250:
+    if(!(*status == 1)) goto S290;
+S260:
+    dzror(status,x,fx,&xlo,&xhi,&qdum1,&qdum2);
+    if(!(*status == 1)) goto S280;
+/*
+     GET-FUNCTION-VALUE
+*/
+    i99999 = 6;
+    goto S300;
+S280:
+S270:
+    goto S250;
+S290:
+    *x = xlo;
+    *status = 0;
+    return;
+DSTINV:
+    small = *zsmall;
+    big = *zbig;
+    absstp = *zabsst;
+    relstp = *zrelst;
+    stpmul = *zstpmu;
+    abstol = *zabsto;
+    reltol = *zrelto;
+    return;
+S300:
+/*
+     TO GET-FUNCTION-VALUE
+*/
+    *status = 1;
+    return;
+S310:
+    switch((int)i99999){case 1: goto S10;case 2: goto S20;case 3: goto S90;case
+      4: goto S130;case 5: goto S200;case 6: goto S270;default: break;}
+#undef qxmon
+} /* END */
+
+/***=====================================================================***/
+static void dinvr(int *status,double *x,double *fx,
+       unsigned long *qleft,unsigned long *qhi)
+/*
+**********************************************************************
+
+     void dinvr(int *status,double *x,double *fx,
+           unsigned long *qleft,unsigned long *qhi)
+
+          Double precision
+          bounds the zero of the function and invokes zror
+                    Reverse Communication
+
+
+                              Function
+
+
+     Bounds the    function  and  invokes  ZROR   to perform the   zero
+     finding.  STINVR  must  have   been  called  before this   routine
+     in order to set its parameters.
+
+
+                              Arguments
+
+
+     STATUS <--> At the beginning of a zero finding problem, STATUS
+                 should be set to 0 and INVR invoked.  (The value
+                 of parameters other than X will be ignored on this cal
+
+                 When INVR needs the function evaluated, it will set
+                 STATUS to 1 and return.  The value of the function
+                 should be set in FX and INVR again called without
+                 changing any of its other parameters.
+
+                 When INVR has finished without error, it will return
+                 with STATUS 0.  In that case X is approximately a root
+                 of F(X).
+
+                 If INVR cannot bound the function, it returns status
+                 -1 and sets QLEFT and QHI.
+                         INTEGER STATUS
+
+     X <-- The value of X at which F(X) is to be evaluated.
+                         DOUBLE PRECISION X
+
+     FX --> The value of F(X) calculated when INVR returns with
+            STATUS = 1.
+                         DOUBLE PRECISION FX
+
+     QLEFT <-- Defined only if QMFINV returns .FALSE.  In that
+          case it is .TRUE. If the stepping search terminated
+          unsucessfully at SMALL.  If it is .FALSE. the search
+          terminated unsucessfully at BIG.
+                    QLEFT is LOGICAL
+
+     QHI <-- Defined only if QMFINV returns .FALSE.  In that
+          case it is .TRUE. if F(X) .GT. Y at the termination
+          of the search and .FALSE. if F(X) .LT. Y at the
+          termination of the search.
+                    QHI is LOGICAL
+
+**********************************************************************
+*/
+{
+    E0000(0,status,x,fx,qleft,qhi,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
+} /* END */
+
+/***=====================================================================***/
+static void dstinv(double *zsmall,double *zbig,double *zabsst,
+        double *zrelst,double *zstpmu,double *zabsto,
+        double *zrelto)
+/*
+**********************************************************************
+      void dstinv(double *zsmall,double *zbig,double *zabsst,
+            double *zrelst,double *zstpmu,double *zabsto,
+            double *zrelto)
+
+      Double Precision - SeT INverse finder - Reverse Communication
+                              Function
+     Concise Description - Given a monotone function F finds X
+     such that F(X) = Y.  Uses Reverse communication -- see invr.
+     This routine sets quantities needed by INVR.
+          More Precise Description of INVR -
+     F must be a monotone function, the results of QMFINV are
+     otherwise undefined.  QINCR must be .TRUE. if F is non-
+     decreasing and .FALSE. if F is non-increasing.
+     QMFINV will return .TRUE. if and only if F(SMALL) and
+     F(BIG) bracket Y, i. e.,
+          QINCR is .TRUE. and F(SMALL).LE.Y.LE.F(BIG) or
+          QINCR is .FALSE. and F(BIG).LE.Y.LE.F(SMALL)
+     if QMFINV returns .TRUE., then the X returned satisfies
+     the following condition.  let
+               TOL(X) = MAX(ABSTOL,RELTOL*ABS(X))
+     then if QINCR is .TRUE.,
+          F(X-TOL(X)) .LE. Y .LE. F(X+TOL(X))
+     and if QINCR is .FALSE.
+          F(X-TOL(X)) .GE. Y .GE. F(X+TOL(X))
+                              Arguments
+     SMALL --> The left endpoint of the interval to be
+          searched for a solution.
+                    SMALL is DOUBLE PRECISION
+     BIG --> The right endpoint of the interval to be
+          searched for a solution.
+                    BIG is DOUBLE PRECISION
+     ABSSTP, RELSTP --> The initial step size in the search
+          is MAX(ABSSTP,RELSTP*ABS(X)). See algorithm.
+                    ABSSTP is DOUBLE PRECISION
+                    RELSTP is DOUBLE PRECISION
+     STPMUL --> When a step doesn't bound the zero, the step
+                size is multiplied by STPMUL and another step
+                taken.  A popular value is 2.0
+                    DOUBLE PRECISION STPMUL
+     ABSTOL, RELTOL --> Two numbers that determine the accuracy
+          of the solution.  See function for a precise definition.
+                    ABSTOL is DOUBLE PRECISION
+                    RELTOL is DOUBLE PRECISION
+                              Method
+     Compares F(X) with Y for the input value of X then uses QINCR
+     to determine whether to step left or right to bound the
+     desired x.  the initial step size is
+          MAX(ABSSTP,RELSTP*ABS(S)) for the input value of X.
+     Iteratively steps right or left until it bounds X.
+     At each step which doesn't bound X, the step size is doubled.
+     The routine is careful never to step beyond SMALL or BIG.  If
+     it hasn't bounded X at SMALL or BIG, QMFINV returns .FALSE.
+     after setting QLEFT and QHI.
+     If X is successfully bounded then Algorithm R of the paper
+     'Two Efficient Algorithms with Guaranteed Convergence for
+     Finding a Zero of a Function' by J. C. P. Bus and
+     T. J. Dekker in ACM Transactions on Mathematical
+     Software, Volume 1, No. 4 page 330 (DEC. '75) is employed
+     to find the zero of the function F(X)-Y. This is routine
+     QRZERO.
+**********************************************************************
+*/
+{
+    E0000(1,NULL,NULL,NULL,NULL,NULL,zabsst,zabsto,zbig,zrelst,zrelto,zsmall,
+    zstpmu);
+} /* END */
+
+/***=====================================================================***/
+static double dlanor(double *x)
+/*
+**********************************************************************
+
+     double dlanor(double *x)
+           Double precision Logarith of the Asymptotic Normal
+
+
+                              Function
+
+
+      Computes the logarithm of the cumulative normal distribution
+      from abs( x ) to infinity for abs( x ) >= 5.
+
+
+                              Arguments
+
+
+      X --> Value at which cumulative normal to be evaluated
+                     DOUBLE PRECISION X
+
+
+                              Method
+
+
+      23 term expansion of formula 26.2.12 of Abramowitz and Stegun.
+      The relative error at X = 5 is about 0.5E-5.
+
+
+                              Note
+
+
+      ABS(X) must be >= 5 else there is an error stop.
+
+**********************************************************************
+*/
+{
+#define dlsqpi 0.91893853320467274177e0
+static double coef[12] = {
+    -1.0e0,3.0e0,-15.0e0,105.0e0,-945.0e0,10395.0e0,-135135.0e0,2027025.0e0,
+    -34459425.0e0,654729075.0e0,-13749310575.e0,316234143225.0e0
+};
+static int K1 = 12;
+static double dlanor,approx,correc,xx,xx2,T2;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    xx = fabs(*x);
+    if(xx < 5.0e0){ ftnstop("Argument too small in DLANOR"); return 66.6; }
+    approx = -dlsqpi-0.5e0*xx*xx-log(xx);
+    xx2 = xx*xx;
+    T2 = 1.0e0/xx2;
+    correc = devlpl(coef,&K1,&T2)/xx2;
+    correc = dln1px(&correc);
+    dlanor = approx+correc;
+    return dlanor;
+#undef dlsqpi
+} /* END */
+
+/***=====================================================================***/
+static double dln1mx(double *x)
+/*
+**********************************************************************
+
+     double dln1mx(double *x)
+               Double precision LN(1-X)
+
+
+                              Function
+
+
+     Returns ln(1-x) for small x (good accuracy if x .le. 0.1).
+     Note that the obvious code of
+               LOG(1.0-X)
+     won't work for small X because 1.0-X loses accuracy
+
+
+                              Arguments
+
+
+     X --> Value for which ln(1-x) is desired.
+                                        X is DOUBLE PRECISION
+
+
+                              Method
+
+
+     If X > 0.1, the obvious code above is used ELSE
+     The Taylor series for 1-x is expanded to 20 terms.
+
+**********************************************************************
+*/
+{
+static double dln1mx,T1;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    T1 = -*x;
+    dln1mx = dln1px(&T1);
+    return dln1mx;
+} /* END */
+
+/***=====================================================================***/
+static double dln1px(double *a)
+/*
+**********************************************************************
+
+     double dln1px(double *a)
+               Double precision LN(1+X)
+
+
+                              Function
+
+
+     Returns ln(1+x)
+     Note that the obvious code of
+               LOG(1.0+X)
+     won't work for small X because 1.0+X loses accuracy
+
+
+                              Arguments
+
+
+     X --> Value for which ln(1-x) is desired.
+                                        X is DOUBLE PRECISION
+
+
+                              Method
+
+
+     Renames ALNREL from:
+     DiDinato, A. R. and Morris,  A.   H.  Algorithm 708: Significant
+     Digit Computation of the Incomplete  Beta  Function Ratios.  ACM
+     Trans. Math.  Softw. 18 (1993), 360-373.
+
+**********************************************************************
+-----------------------------------------------------------------------
+            EVALUATION OF THE FUNCTION LN(1 + A)
+-----------------------------------------------------------------------
+*/
+{
+static double p1 = -.129418923021993e+01;
+static double p2 = .405303492862024e+00;
+static double p3 = -.178874546012214e-01;
+static double q1 = -.162752256355323e+01;
+static double q2 = .747811014037616e+00;
+static double q3 = -.845104217945565e-01;
+static double dln1px,t,t2,w,x;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    if(fabs(*a) > 0.375e0) goto S10;
+    t = *a/(*a+2.0e0);
+    t2 = t*t;
+    w = (((p3*t2+p2)*t2+p1)*t2+1.0e0)/(((q3*t2+q2)*t2+q1)*t2+1.0e0);
+    dln1px = 2.0e0*t*w;
+    return dln1px;
+S10:
+    x = 1.e0+*a;
+    dln1px = log(x);
+    return dln1px;
+} /* END */
+
+/***=====================================================================***/
+static double dlnbet(double *a0,double *b0)
+/*
+**********************************************************************
+
+     double dlnbet(a0,b0)
+          Double precision LN of the complete BETa
+
+
+                              Function
+
+
+     Returns the natural log of the complete beta function,
+     i.e.,
+
+                  ln( Gamma(a)*Gamma(b) / Gamma(a+b)
+
+
+                              Arguments
+
+
+   A,B --> The (symmetric) arguments to the complete beta
+                  DOUBLE PRECISION A, B
+
+
+                              Method
+
+
+     Renames BETALN from:
+     DiDinato, A. R. and Morris,  A.   H.  Algorithm 708: Significant
+     Digit Computation of the Incomplete  Beta  Function Ratios.  ACM
+     Trans. Math.  Softw. 18 (1993), 360-373.
+
+**********************************************************************
+-----------------------------------------------------------------------
+     EVALUATION OF THE LOGARITHM OF THE BETA FUNCTION
+-----------------------------------------------------------------------
+     E = 0.5*LN(2*PI)
+--------------------------
+*/
+{
+static double e = .918938533204673e0;
+static double dlnbet,a,b,c,h,u,v,w,z;
+static int i,n;
+static double T1;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    a = fifdmin1(*a0,*b0);
+    b = fifdmax1(*a0,*b0);
+    if(a >= 8.0e0) goto S100;
+    if(a >= 1.0e0) goto S20;
+/*
+-----------------------------------------------------------------------
+                   PROCEDURE WHEN A .LT. 1
+-----------------------------------------------------------------------
+*/
+    if(b >= 8.0e0) goto S10;
+    T1 = a+b;
+    dlnbet = gamln(&a)+(gamln(&b)-gamln(&T1));
+    return dlnbet;
+S10:
+    dlnbet = gamln(&a)+algdiv(&a,&b);
+    return dlnbet;
+S20:
+/*
+-----------------------------------------------------------------------
+                PROCEDURE WHEN 1 .LE. A .LT. 8
+-----------------------------------------------------------------------
+*/
+    if(a > 2.0e0) goto S40;
+    if(b > 2.0e0) goto S30;
+    dlnbet = gamln(&a)+gamln(&b)-gsumln(&a,&b);
+    return dlnbet;
+S30:
+    w = 0.0e0;
+    if(b < 8.0e0) goto S60;
+    dlnbet = gamln(&a)+algdiv(&a,&b);
+    return dlnbet;
+S40:
+/*
+                REDUCTION OF A WHEN B .LE. 1000
+*/
+    if(b > 1000.0e0) goto S80;
+    n = a-1.0e0;
+    w = 1.0e0;
+    for(i=1; i<=n; i++) {
+        a -= 1.0e0;
+        h = a/b;
+        w *= (h/(1.0e0+h));
+    }
+    w = log(w);
+    if(b < 8.0e0) goto S60;
+    dlnbet = w+gamln(&a)+algdiv(&a,&b);
+    return dlnbet;
+S60:
+/*
+                 REDUCTION OF B WHEN B .LT. 8
+*/
+    n = b-1.0e0;
+    z = 1.0e0;
+    for(i=1; i<=n; i++) {
+        b -= 1.0e0;
+        z *= (b/(a+b));
+    }
+    dlnbet = w+log(z)+(gamln(&a)+(gamln(&b)-gsumln(&a,&b)));
+    return dlnbet;
+S80:
+/*
+                REDUCTION OF A WHEN B .GT. 1000
+*/
+    n = a-1.0e0;
+    w = 1.0e0;
+    for(i=1; i<=n; i++) {
+        a -= 1.0e0;
+        w *= (a/(1.0e0+a/b));
+    }
+    dlnbet = log(w)-(double)n*log(b)+(gamln(&a)+algdiv(&a,&b));
+    return dlnbet;
+S100:
+/*
+-----------------------------------------------------------------------
+                   PROCEDURE WHEN A .GE. 8
+-----------------------------------------------------------------------
+*/
+    w = bcorr(&a,&b);
+    h = a/b;
+    c = h/(1.0e0+h);
+    u = -((a-0.5e0)*log(c));
+    v = b*alnrel(&h);
+    if(u <= v) goto S110;
+    dlnbet = -(0.5e0*log(b))+e+w-v-u;
+    return dlnbet;
+S110:
+    dlnbet = -(0.5e0*log(b))+e+w-u-v;
+    return dlnbet;
+} /* END */
+
+/***=====================================================================***/
+static double dlngam(double *a)
+/*
+**********************************************************************
+
+     double dlngam(double *a)
+                 Double precision LN of the GAMma function
+
+
+                              Function
+
+
+     Returns the natural logarithm of GAMMA(X).
+
+
+                              Arguments
+
+
+     X --> value at which scaled log gamma is to be returned
+                    X is DOUBLE PRECISION
+
+
+                              Method
+
+
+     Renames GAMLN from:
+     DiDinato, A. R. and Morris,  A.   H.  Algorithm 708: Significant
+     Digit Computation of the Incomplete  Beta  Function Ratios.  ACM
+     Trans. Math.  Softw. 18 (1993), 360-373.
+
+**********************************************************************
+-----------------------------------------------------------------------
+            EVALUATION OF LN(GAMMA(A)) FOR POSITIVE A
+-----------------------------------------------------------------------
+     WRITTEN BY ALFRED H. MORRIS
+          NAVAL SURFACE WARFARE CENTER
+          DAHLGREN, VIRGINIA
+--------------------------
+     D = 0.5*(LN(2*PI) - 1)
+--------------------------
+*/
+{
+static double c0 = .833333333333333e-01;
+static double c1 = -.277777777760991e-02;
+static double c2 = .793650666825390e-03;
+static double c3 = -.595202931351870e-03;
+static double c4 = .837308034031215e-03;
+static double c5 = -.165322962780713e-02;
+static double d = .418938533204673e0;
+static double dlngam,t,w;
+static int i,n;
+static double T1;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    if(*a > 0.8e0) goto S10;
+    dlngam = gamln1(a)-log(*a);
+    return dlngam;
+S10:
+    if(*a > 2.25e0) goto S20;
+    t = *a-0.5e0-0.5e0;
+    dlngam = gamln1(&t);
+    return dlngam;
+S20:
+    if(*a >= 10.0e0) goto S40;
+    n = *a-1.25e0;
+    t = *a;
+    w = 1.0e0;
+    for(i=1; i<=n; i++) {
+        t -= 1.0e0;
+        w = t*w;
+    }
+    T1 = t-1.0e0;
+    dlngam = gamln1(&T1)+log(w);
+    return dlngam;
+S40:
+    t = pow(1.0e0/ *a,2.0);
+    w = (((((c5*t+c4)*t+c3)*t+c2)*t+c1)*t+c0)/ *a;
+    dlngam = d+w+(*a-0.5e0)*(log(*a)-1.0e0);
+    return dlngam;
+} /* END */
+
+/***=====================================================================***/
+static double dstrem(double *z)
+{
+/*
+**********************************************************************
+     double dstrem(double *z)
+             Double precision Sterling Remainder
+                              Function
+     Returns   Log(Gamma(Z))  -  Sterling(Z)  where   Sterling(Z)  is
+     Sterling's Approximation to Log(Gamma(Z))
+     Sterling(Z) = LOG( SQRT( 2*PI ) ) + ( Z-0.5 ) * LOG( Z ) - Z
+                              Arguments
+     Z --> Value at which Sterling remainder calculated
+           Must be positive.
+                  DOUBLE PRECISION Z
+                              Method
+     If Z >= 6 uses 9 terms of series in Bernoulli numbers
+     (Values calculated using Maple)
+     Otherwise computes difference explicitly
+**********************************************************************
+*/
+#define hln2pi 0.91893853320467274178e0
+#define ncoef 10
+static double coef[ncoef] = {
+    0.0e0,0.0833333333333333333333333333333e0,
+    -0.00277777777777777777777777777778e0,0.000793650793650793650793650793651e0,
+    -0.000595238095238095238095238095238e0,
+    0.000841750841750841750841750841751e0,-0.00191752691752691752691752691753e0,
+    0.00641025641025641025641025641026e0,-0.0295506535947712418300653594771e0,
+    0.179644372368830573164938490016e0
+};
+static int K1 = 10;
+static double dstrem,sterl,T2;
+/*
+     ..
+     .. Executable Statements ..
+*/
+/*
+    For information, here are the next 11 coefficients of the
+    remainder term in Sterling's formula
+            -1.39243221690590111642743221691
+            13.4028640441683919944789510007
+            -156.848284626002017306365132452
+            2193.10333333333333333333333333
+            -36108.7712537249893571732652192
+            691472.268851313067108395250776
+            -0.152382215394074161922833649589D8
+            0.382900751391414141414141414141D9
+            -0.108822660357843910890151491655D11
+            0.347320283765002252252252252252D12
+            -0.123696021422692744542517103493D14
+*/
+    if(*z <= 0.0e0){ ftnstop("nonpositive argument in DSTREM"); return 66.6; }
+    if(!(*z > 6.0e0)) goto S10;
+    T2 = 1.0e0/pow(*z,2.0);
+    dstrem = devlpl(coef,&K1,&T2)**z;
+    goto S20;
+S10:
+    sterl = hln2pi+(*z-0.5e0)*log(*z)-*z;
+    dstrem = dlngam(z)-sterl;
+S20:
+    return dstrem;
+#undef hln2pi
+#undef ncoef
+} /* END */
+
+/***=====================================================================***/
+static double dt1(double *p,double *q,double *df)
+/*
+**********************************************************************
+
+     double dt1(double *p,double *q,double *df)
+     Double precision Initalize Approximation to
+           INVerse of the cumulative T distribution
+
+
+                              Function
+
+
+     Returns  the  inverse   of  the T   distribution   function, i.e.,
+     the integral from 0 to INVT of the T density is P. This is an
+     initial approximation
+
+
+                              Arguments
+
+
+     P --> The p-value whose inverse from the T distribution is
+          desired.
+                    P is DOUBLE PRECISION
+
+     Q --> 1-P.
+                    Q is DOUBLE PRECISION
+
+     DF --> Degrees of freedom of the T distribution.
+                    DF is DOUBLE PRECISION
+
+**********************************************************************
+*/
+{
+static double coef[4][5] = {
+    1.0e0,1.0e0,0.0e0,0.0e0,0.0e0,3.0e0,16.0e0,5.0e0,0.0e0,0.0e0,-15.0e0,17.0e0,
+    19.0e0,3.0e0,0.0e0,-945.0e0,-1920.0e0,1482.0e0,776.0e0,79.0e0
+};
+static double denom[4] = {
+    4.0e0,96.0e0,384.0e0,92160.0e0
+};
+static int ideg[4] = {
+    2,3,4,5
+};
+static double dt1,denpow,sum,term,x,xp,xx;
+static int i;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    x = fabs(dinvnr(p,q));
+    xx = x*x;
+    sum = x;
+    denpow = 1.0e0;
+    for(i=0; i<4; i++) {
+        term = devlpl(&coef[i][0],&ideg[i],&xx)*x;
+        denpow *= *df;
+        sum += (term/(denpow*denom[i]));
+    }
+    if(!(*p >= 0.5e0)) goto S20;
+    xp = sum;
+    goto S30;
+S20:
+    xp = -sum;
+S30:
+    dt1 = xp;
+    return dt1;
+} /* END */
+
+/***=====================================================================***/
+static void E0001(int IENTRY,int *status,double *x,double *fx,
+          double *xlo,double *xhi,unsigned long *qleft,
+          unsigned long *qhi,double *zabstl,double *zreltl,
+          double *zxhi,double *zxlo)
+{
+#define ftol(zx) (0.5e0*fifdmax1(abstol,reltol*fabs((zx))))
+static double a,abstol,b,c,d,fa,fb,fc,fd,fda,fdb,m,mb,p,q,reltol,tol,w,xxhi,xxlo;
+static int ext,i99999;
+static unsigned long first,qrzero;
+    switch(IENTRY){case 0: goto DZROR; case 1: goto DSTZR;}
+DZROR:
+    if(*status > 0) goto S280;
+    *xlo = xxlo;
+    *xhi = xxhi;
+    b = *x = *xlo;
+/*
+     GET-FUNCTION-VALUE
+*/
+    i99999 = 1;
+    goto S270;
+S10:
+    fb = *fx;
+    *xlo = *xhi;
+    a = *x = *xlo;
+/*
+     GET-FUNCTION-VALUE
+*/
+    i99999 = 2;
+    goto S270;
+S20:
+/*
+     Check that F(ZXLO) < 0 < F(ZXHI)  or
+                F(ZXLO) > 0 > F(ZXHI)
+*/
+    if(!(fb < 0.0e0)) goto S40;
+    if(!(*fx < 0.0e0)) goto S30;
+    *status = -1;
+    *qleft = *fx < fb;
+    *qhi = 0;
+    return;
+S40:
+S30:
+    if(!(fb > 0.0e0)) goto S60;
+    if(!(*fx > 0.0e0)) goto S50;
+    *status = -1;
+    *qleft = *fx > fb;
+    *qhi = 1;
+    return;
+S60:
+S50:
+    fa = *fx;
+    first = 1;
+S70:
+    c = a;
+    fc = fa;
+    ext = 0;
+S80:
+    if(!(fabs(fc) < fabs(fb))) goto S100;
+    if(!(c != a)) goto S90;
+    d = a;
+    fd = fa;
+S90:
+    a = b;
+    fa = fb;
+    *xlo = c;
+    b = *xlo;
+    fb = fc;
+    c = a;
+    fc = fa;
+S100:
+    tol = ftol(*xlo);
+    m = (c+b)*.5e0;
+    mb = m-b;
+    if(!(fabs(mb) > tol)) goto S240;
+    if(!(ext > 3)) goto S110;
+    w = mb;
+    goto S190;
+S110:
+    tol = fifdsign(tol,mb);
+    p = (b-a)*fb;
+    if(!first) goto S120;
+    q = fa-fb;
+    first = 0;
+    goto S130;
+S120:
+    fdb = (fd-fb)/(d-b);
+    fda = (fd-fa)/(d-a);
+    p = fda*p;
+    q = fdb*fa-fda*fb;
+S130:
+    if(!(p < 0.0e0)) goto S140;
+    p = -p;
+    q = -q;
+S140:
+    if(ext == 3) p *= 2.0e0;
+    if(!(p*1.0e0 == 0.0e0 || p <= q*tol)) goto S150;
+    w = tol;
+    goto S180;
+S150:
+    if(!(p < mb*q)) goto S160;
+    w = p/q;
+    goto S170;
+S160:
+    w = mb;
+S190:
+S180:
+S170:
+    d = a;
+    fd = fa;
+    a = b;
+    fa = fb;
+    b += w;
+    *xlo = b;
+    *x = *xlo;
+/*
+     GET-FUNCTION-VALUE
+*/
+    i99999 = 3;
+    goto S270;
+S200:
+    fb = *fx;
+    if(!(fc*fb >= 0.0e0)) goto S210;
+    goto S70;
+S210:
+    if(!(w == mb)) goto S220;
+    ext = 0;
+    goto S230;
+S220:
+    ext += 1;
+S230:
+    goto S80;
+S240:
+    *xhi = c;
+    qrzero = fc >= 0.0e0 && fb <= 0.0e0 || fc < 0.0e0 && fb >= 0.0e0;
+    if(!qrzero) goto S250;
+    *status = 0;
+    goto S260;
+S250:
+    *status = -1;
+S260:
+    return;
+DSTZR:
+    xxlo = *zxlo;
+    xxhi = *zxhi;
+    abstol = *zabstl;
+    reltol = *zreltl;
+    return;
+S270:
+/*
+     TO GET-FUNCTION-VALUE
+*/
+    *status = 1;
+    return;
+S280:
+    switch((int)i99999){case 1: goto S10;case 2: goto S20;case 3: goto S200;
+      default: break;}
+#undef ftol
+} /* END */
+
+/***=====================================================================***/
+static void dzror(int *status,double *x,double *fx,double *xlo,
+       double *xhi,unsigned long *qleft,unsigned long *qhi)
+/*
+**********************************************************************
+
+     void dzror(int *status,double *x,double *fx,double *xlo,
+           double *xhi,unsigned long *qleft,unsigned long *qhi)
+
+     Double precision ZeRo of a function -- Reverse Communication
+
+
+                              Function
+
+
+     Performs the zero finding.  STZROR must have been called before
+     this routine in order to set its parameters.
+
+
+                              Arguments
+
+
+     STATUS <--> At the beginning of a zero finding problem, STATUS
+                 should be set to 0 and ZROR invoked.  (The value
+                 of other parameters will be ignored on this call.)
+
+                 When ZROR needs the function evaluated, it will set
+                 STATUS to 1 and return.  The value of the function
+                 should be set in FX and ZROR again called without
+                 changing any of its other parameters.
+
+                 When ZROR has finished without error, it will return
+                 with STATUS 0.  In that case (XLO,XHI) bound the answe
+
+                 If ZROR finds an error (which implies that F(XLO)-Y an
+                 F(XHI)-Y have the same sign, it returns STATUS -1.  In
+                 this case, XLO and XHI are undefined.
+                         INTEGER STATUS
+
+     X <-- The value of X at which F(X) is to be evaluated.
+                         DOUBLE PRECISION X
+
+     FX --> The value of F(X) calculated when ZROR returns with
+            STATUS = 1.
+                         DOUBLE PRECISION FX
+
+     XLO <-- When ZROR returns with STATUS = 0, XLO bounds the
+             inverval in X containing the solution below.
+                         DOUBLE PRECISION XLO
+
+     XHI <-- When ZROR returns with STATUS = 0, XHI bounds the
+             inverval in X containing the solution above.
+                         DOUBLE PRECISION XHI
+
+     QLEFT <-- .TRUE. if the stepping search terminated unsucessfully
+                at XLO.  If it is .FALSE. the search terminated
+                unsucessfully at XHI.
+                    QLEFT is LOGICAL
+
+     QHI <-- .TRUE. if F(X) .GT. Y at the termination of the
+              search and .FALSE. if F(X) .LT. Y at the
+              termination of the search.
+                    QHI is LOGICAL
+
+**********************************************************************
+*/
+{
+    E0001(0,status,x,fx,xlo,xhi,qleft,qhi,NULL,NULL,NULL,NULL);
+} /* END */
+
+/***=====================================================================***/
+static void dstzr(double *zxlo,double *zxhi,double *zabstl,double *zreltl)
+/*
+**********************************************************************
+     void dstzr(double *zxlo,double *zxhi,double *zabstl,double *zreltl)
+     Double precision SeT ZeRo finder - Reverse communication version
+                              Function
+     Sets quantities needed by ZROR.  The function of ZROR
+     and the quantities set is given here.
+     Concise Description - Given a function F
+     find XLO such that F(XLO) = 0.
+          More Precise Description -
+     Input condition. F is a double precision function of a single
+     double precision argument and XLO and XHI are such that
+          F(XLO)*F(XHI)  .LE.  0.0
+     If the input condition is met, QRZERO returns .TRUE.
+     and output values of XLO and XHI satisfy the following
+          F(XLO)*F(XHI)  .LE. 0.
+          ABS(F(XLO)  .LE. ABS(F(XHI)
+          ABS(XLO-XHI)  .LE. TOL(X)
+     where
+          TOL(X) = MAX(ABSTOL,RELTOL*ABS(X))
+     If this algorithm does not find XLO and XHI satisfying
+     these conditions then QRZERO returns .FALSE.  This
+     implies that the input condition was not met.
+                              Arguments
+     XLO --> The left endpoint of the interval to be
+           searched for a solution.
+                    XLO is DOUBLE PRECISION
+     XHI --> The right endpoint of the interval to be
+           for a solution.
+                    XHI is DOUBLE PRECISION
+     ABSTOL, RELTOL --> Two numbers that determine the accuracy
+                      of the solution.  See function for a
+                      precise definition.
+                    ABSTOL is DOUBLE PRECISION
+                    RELTOL is DOUBLE PRECISION
+                              Method
+     Algorithm R of the paper 'Two Efficient Algorithms with
+     Guaranteed Convergence for Finding a Zero of a Function'
+     by J. C. P. Bus and T. J. Dekker in ACM Transactions on
+     Mathematical Software, Volume 1, no. 4 page 330
+     (Dec. '75) is employed to find the zero of F(X)-Y.
+**********************************************************************
+*/
+{
+    E0001(1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,zabstl,zreltl,zxhi,zxlo);
+} /* END */
+
+/***=====================================================================***/
+static double erf1(double *x)
+/*
+-----------------------------------------------------------------------
+             EVALUATION OF THE REAL ERROR FUNCTION
+-----------------------------------------------------------------------
+*/
+{
+static double c = .564189583547756e0;
+static double a[5] = {
+    .771058495001320e-04,-.133733772997339e-02,.323076579225834e-01,
+    .479137145607681e-01,.128379167095513e+00
+};
+static double b[3] = {
+    .301048631703895e-02,.538971687740286e-01,.375795757275549e+00
+};
+static double p[8] = {
+    -1.36864857382717e-07,5.64195517478974e-01,7.21175825088309e+00,
+    4.31622272220567e+01,1.52989285046940e+02,3.39320816734344e+02,
+    4.51918953711873e+02,3.00459261020162e+02
+};
+static double q[8] = {
+    1.00000000000000e+00,1.27827273196294e+01,7.70001529352295e+01,
+    2.77585444743988e+02,6.38980264465631e+02,9.31354094850610e+02,
+    7.90950925327898e+02,3.00459260956983e+02
+};
+static double r[5] = {
+    2.10144126479064e+00,2.62370141675169e+01,2.13688200555087e+01,
+    4.65807828718470e+00,2.82094791773523e-01
+};
+static double s[4] = {
+    9.41537750555460e+01,1.87114811799590e+02,9.90191814623914e+01,
+    1.80124575948747e+01
+};
+static double erf1,ax,bot,t,top,x2;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    ax = fabs(*x);
+    if(ax > 0.5e0) goto S10;
+    t = *x**x;
+    top = (((a[0]*t+a[1])*t+a[2])*t+a[3])*t+a[4]+1.0e0;
+    bot = ((b[0]*t+b[1])*t+b[2])*t+1.0e0;
+    erf1 = *x*(top/bot);
+    return erf1;
+S10:
+    if(ax > 4.0e0) goto S20;
+    top = ((((((p[0]*ax+p[1])*ax+p[2])*ax+p[3])*ax+p[4])*ax+p[5])*ax+p[6])*ax+p[
+      7];
+    bot = ((((((q[0]*ax+q[1])*ax+q[2])*ax+q[3])*ax+q[4])*ax+q[5])*ax+q[6])*ax+q[
+      7];
+    erf1 = 0.5e0+(0.5e0-exp(-(*x**x))*top/bot);
+    if(*x < 0.0e0) erf1 = -erf1;
+    return erf1;
+S20:
+    if(ax >= 5.8e0) goto S30;
+    x2 = *x**x;
+    t = 1.0e0/x2;
+    top = (((r[0]*t+r[1])*t+r[2])*t+r[3])*t+r[4];
+    bot = (((s[0]*t+s[1])*t+s[2])*t+s[3])*t+1.0e0;
+    erf1 = (c-top/(x2*bot))/ax;
+    erf1 = 0.5e0+(0.5e0-exp(-x2)*erf1);
+    if(*x < 0.0e0) erf1 = -erf1;
+    return erf1;
+S30:
+    erf1 = fifdsign(1.0e0,*x);
+    return erf1;
+} /* END */
+
+/***=====================================================================***/
+static double erfc1(int *ind,double *x)
+/*
+-----------------------------------------------------------------------
+         EVALUATION OF THE COMPLEMENTARY ERROR FUNCTION
+
+          ERFC1(IND,X) = ERFC(X)            IF IND = 0
+          ERFC1(IND,X) = EXP(X*X)*ERFC(X)   OTHERWISE
+-----------------------------------------------------------------------
+*/
+{
+static double c = .564189583547756e0;
+static double a[5] = {
+    .771058495001320e-04,-.133733772997339e-02,.323076579225834e-01,
+    .479137145607681e-01,.128379167095513e+00
+};
+static double b[3] = {
+    .301048631703895e-02,.538971687740286e-01,.375795757275549e+00
+};
+static double p[8] = {
+    -1.36864857382717e-07,5.64195517478974e-01,7.21175825088309e+00,
+    4.31622272220567e+01,1.52989285046940e+02,3.39320816734344e+02,
+    4.51918953711873e+02,3.00459261020162e+02
+};
+static double q[8] = {
+    1.00000000000000e+00,1.27827273196294e+01,7.70001529352295e+01,
+    2.77585444743988e+02,6.38980264465631e+02,9.31354094850610e+02,
+    7.90950925327898e+02,3.00459260956983e+02
+};
+static double r[5] = {
+    2.10144126479064e+00,2.62370141675169e+01,2.13688200555087e+01,
+    4.65807828718470e+00,2.82094791773523e-01
+};
+static double s[4] = {
+    9.41537750555460e+01,1.87114811799590e+02,9.90191814623914e+01,
+    1.80124575948747e+01
+};
+static int K1 = 1;
+static double erfc1,ax,bot,e,t,top,w;
+/*
+     ..
+     .. Executable Statements ..
+*/
+/*
+                     ABS(X) .LE. 0.5
+*/
+    ax = fabs(*x);
+    if(ax > 0.5e0) goto S10;
+    t = *x**x;
+    top = (((a[0]*t+a[1])*t+a[2])*t+a[3])*t+a[4]+1.0e0;
+    bot = ((b[0]*t+b[1])*t+b[2])*t+1.0e0;
+    erfc1 = 0.5e0+(0.5e0-*x*(top/bot));
+    if(*ind != 0) erfc1 = exp(t)*erfc1;
+    return erfc1;
+S10:
+/*
+                  0.5 .LT. ABS(X) .LE. 4
+*/
+    if(ax > 4.0e0) goto S20;
+    top = ((((((p[0]*ax+p[1])*ax+p[2])*ax+p[3])*ax+p[4])*ax+p[5])*ax+p[6])*ax+p[
+      7];
+    bot = ((((((q[0]*ax+q[1])*ax+q[2])*ax+q[3])*ax+q[4])*ax+q[5])*ax+q[6])*ax+q[
+      7];
+    erfc1 = top/bot;
+    goto S40;
+S20:
+/*
+                      ABS(X) .GT. 4
+*/
+    if(*x <= -5.6e0) goto S60;
+    if(*ind != 0) goto S30;
+    if(*x > 100.0e0) goto S70;
+    if(*x**x > -exparg(&K1)) goto S70;
+S30:
+    t = pow(1.0e0/ *x,2.0);
+    top = (((r[0]*t+r[1])*t+r[2])*t+r[3])*t+r[4];
+    bot = (((s[0]*t+s[1])*t+s[2])*t+s[3])*t+1.0e0;
+    erfc1 = (c-t*top/bot)/ax;
+S40:
+/*
+                      FINAL ASSEMBLY
+*/
+    if(*ind == 0) goto S50;
+    if(*x < 0.0e0) erfc1 = 2.0e0*exp(*x**x)-erfc1;
+    return erfc1;
+S50:
+    w = *x**x;
+    t = w;
+    e = w-t;
+    erfc1 = (0.5e0+(0.5e0-e))*exp(-t)*erfc1;
+    if(*x < 0.0e0) erfc1 = 2.0e0-erfc1;
+    return erfc1;
+S60:
+/*
+             LIMIT VALUE FOR LARGE NEGATIVE X
+*/
+    erfc1 = 2.0e0;
+    if(*ind != 0) erfc1 = 2.0e0*exp(*x**x);
+    return erfc1;
+S70:
+/*
+             LIMIT VALUE FOR LARGE POSITIVE X
+                       WHEN IND = 0
+*/
+    erfc1 = 0.0e0;
+    return erfc1;
+} /* END */
+
+/***=====================================================================***/
+static double esum(int *mu,double *x)
+/*
+-----------------------------------------------------------------------
+                    EVALUATION OF EXP(MU + X)
+-----------------------------------------------------------------------
+*/
+{
+static double esum,w;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    if(*x > 0.0e0) goto S10;
+    if(*mu < 0) goto S20;
+    w = (double)*mu+*x;
+    if(w > 0.0e0) goto S20;
+    esum = exp(w);
+    return esum;
+S10:
+    if(*mu > 0) goto S20;
+    w = (double)*mu+*x;
+    if(w < 0.0e0) goto S20;
+    esum = exp(w);
+    return esum;
+S20:
+    w = *mu;
+    esum = exp(w)*exp(*x);
+    return esum;
+} /* END */
+
+/***=====================================================================***/
+static double exparg(int *l)
+/*
+--------------------------------------------------------------------
+     IF L = 0 THEN  EXPARG(L) = THE LARGEST POSITIVE W FOR WHICH
+     EXP(W) CAN BE COMPUTED.
+
+     IF L IS NONZERO THEN  EXPARG(L) = THE LARGEST NEGATIVE W FOR
+     WHICH THE COMPUTED VALUE OF EXP(W) IS NONZERO.
+
+     NOTE... ONLY AN APPROXIMATE VALUE FOR EXPARG(L) IS NEEDED.
+--------------------------------------------------------------------
+*/
+{
+static int K1 = 4;
+static int K2 = 9;
+static int K3 = 10;
+static double exparg,lnb;
+static int b,m;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    b = ipmpar(&K1);
+    if(b != 2) goto S10;
+    lnb = .69314718055995e0;
+    goto S40;
+S10:
+    if(b != 8) goto S20;
+    lnb = 2.0794415416798e0;
+    goto S40;
+S20:
+    if(b != 16) goto S30;
+    lnb = 2.7725887222398e0;
+    goto S40;
+S30:
+    lnb = log((double)b);
+S40:
+    if(*l == 0) goto S50;
+    m = ipmpar(&K2)-1;
+    exparg = 0.99999e0*((double)m*lnb);
+    return exparg;
+S50:
+    m = ipmpar(&K3);
+    exparg = 0.99999e0*((double)m*lnb);
+    return exparg;
+} /* END */
+
+/***=====================================================================***/
+static double fpser(double *a,double *b,double *x,double *eps)
+/*
+-----------------------------------------------------------------------
+
+                 EVALUATION OF I (A,B)
+                                X
+
+          FOR B .LT. MIN(EPS,EPS*A) AND X .LE. 0.5.
+
+-----------------------------------------------------------------------
+
+                  SET  FPSER = X**A
+*/
+{
+static int K1 = 1;
+static double fpser,an,c,s,t,tol;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    fpser = 1.0e0;
+    if(*a <= 1.e-3**eps) goto S10;
+    fpser = 0.0e0;
+    t = *a*log(*x);
+    if(t < exparg(&K1)) return fpser;
+    fpser = exp(t);
+S10:
+/*
+                NOTE THAT 1/B(A,B) = B
+*/
+    fpser = *b/ *a*fpser;
+    tol = *eps/ *a;
+    an = *a+1.0e0;
+    t = *x;
+    s = t/an;
+S20:
+    an += 1.0e0;
+    t = *x*t;
+    c = t/an;
+    s += c;
+    if(fabs(c) > tol) goto S20;
+    fpser *= (1.0e0+*a*s);
+    return fpser;
+} /* END */
+
+/***=====================================================================***/
+static double gam1(double *a)
+/*
+     ------------------------------------------------------------------
+     COMPUTATION OF 1/GAMMA(A+1) - 1  FOR -0.5 .LE. A .LE. 1.5
+     ------------------------------------------------------------------
+*/
+{
+static double s1 = .273076135303957e+00;
+static double s2 = .559398236957378e-01;
+static double p[7] = {
+    .577215664901533e+00,-.409078193005776e+00,-.230975380857675e+00,
+    .597275330452234e-01,.766968181649490e-02,-.514889771323592e-02,
+    .589597428611429e-03
+};
+static double q[5] = {
+    .100000000000000e+01,.427569613095214e+00,.158451672430138e+00,
+    .261132021441447e-01,.423244297896961e-02
+};
+static double r[9] = {
+    -.422784335098468e+00,-.771330383816272e+00,-.244757765222226e+00,
+    .118378989872749e+00,.930357293360349e-03,-.118290993445146e-01,
+    .223047661158249e-02,.266505979058923e-03,-.132674909766242e-03
+};
+static double gam1,bot,d,t,top,w,T1;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    t = *a;
+    d = *a-0.5e0;
+    if(d > 0.0e0) t = d-0.5e0;
+    T1 = t;
+    if(T1 < 0) goto S40;
+    else if(T1 == 0) goto S10;
+    else  goto S20;
+S10:
+    gam1 = 0.0e0;
+    return gam1;
+S20:
+    top = (((((p[6]*t+p[5])*t+p[4])*t+p[3])*t+p[2])*t+p[1])*t+p[0];
+    bot = (((q[4]*t+q[3])*t+q[2])*t+q[1])*t+1.0e0;
+    w = top/bot;
+    if(d > 0.0e0) goto S30;
+    gam1 = *a*w;
+    return gam1;
+S30:
+    gam1 = t/ *a*(w-0.5e0-0.5e0);
+    return gam1;
+S40:
+    top = (((((((r[8]*t+r[7])*t+r[6])*t+r[5])*t+r[4])*t+r[3])*t+r[2])*t+r[1])*t+
+      r[0];
+    bot = (s2*t+s1)*t+1.0e0;
+    w = top/bot;
+    if(d > 0.0e0) goto S50;
+    gam1 = *a*(w+0.5e0+0.5e0);
+    return gam1;
+S50:
+    gam1 = t*w/ *a;
+    return gam1;
+} /* END */
+
+/***=====================================================================***/
+static void gaminv(double *a,double *x,double *x0,double *p,double *q,
+        int *ierr)
+/*
+ ----------------------------------------------------------------------
+            INVERSE INCOMPLETE GAMMA RATIO FUNCTION
+
+     GIVEN POSITIVE A, AND NONEGATIVE P AND Q WHERE P + Q = 1.
+     THEN X IS COMPUTED WHERE P(A,X) = P AND Q(A,X) = Q. SCHRODER
+     ITERATION IS EMPLOYED. THE ROUTINE ATTEMPTS TO COMPUTE X
+     TO 10 SIGNIFICANT DIGITS IF THIS IS POSSIBLE FOR THE
+     PARTICULAR COMPUTER ARITHMETIC BEING USED.
+
+                      ------------
+
+     X IS A VARIABLE. IF P = 0 THEN X IS ASSIGNED THE VALUE 0,
+     AND IF Q = 0 THEN X IS SET TO THE LARGEST FLOATING POINT
+     NUMBER AVAILABLE. OTHERWISE, GAMINV ATTEMPTS TO OBTAIN
+     A SOLUTION FOR P(A,X) = P AND Q(A,X) = Q. IF THE ROUTINE
+     IS SUCCESSFUL THEN THE SOLUTION IS STORED IN X.
+
+     X0 IS AN OPTIONAL INITIAL APPROXIMATION FOR X. IF THE USER
+     DOES NOT WISH TO SUPPLY AN INITIAL APPROXIMATION, THEN SET
+     X0 .LE. 0.
+
+     IERR IS A VARIABLE THAT REPORTS THE STATUS OF THE RESULTS.
+     WHEN THE ROUTINE TERMINATES, IERR HAS ONE OF THE FOLLOWING
+     VALUES ...
+
+       IERR =  0    THE SOLUTION WAS OBTAINED. ITERATION WAS
+                    NOT USED.
+       IERR.GT.0    THE SOLUTION WAS OBTAINED. IERR ITERATIONS
+                    WERE PERFORMED.
+       IERR = -2    (INPUT ERROR) A .LE. 0
+       IERR = -3    NO SOLUTION WAS OBTAINED. THE RATIO Q/A
+                    IS TOO LARGE.
+       IERR = -4    (INPUT ERROR) P + Q .NE. 1
+       IERR = -6    20 ITERATIONS WERE PERFORMED. THE MOST
+                    RECENT VALUE OBTAINED FOR X IS GIVEN.
+                    THIS CANNOT OCCUR IF X0 .LE. 0.
+       IERR = -7    ITERATION FAILED. NO VALUE IS GIVEN FOR X.
+                    THIS MAY OCCUR WHEN X IS APPROXIMATELY 0.
+       IERR = -8    A VALUE FOR X HAS BEEN OBTAINED, BUT THE
+                    ROUTINE IS NOT CERTAIN OF ITS ACCURACY.
+                    ITERATION CANNOT BE PERFORMED IN THIS
+                    CASE. IF X0 .LE. 0, THIS CAN OCCUR ONLY
+                    WHEN P OR Q IS APPROXIMATELY 0. IF X0 IS
+                    POSITIVE THEN THIS CAN OCCUR WHEN A IS
+                    EXCEEDINGLY CLOSE TO X AND A IS EXTREMELY
+                    LARGE (SAY A .GE. 1.E20).
+ ----------------------------------------------------------------------
+     WRITTEN BY ALFRED H. MORRIS, JR.
+        NAVAL SURFACE WEAPONS CENTER
+        DAHLGREN, VIRGINIA
+     -------------------
+*/
+{
+static double a0 = 3.31125922108741e0;
+static double a1 = 11.6616720288968e0;
+static double a2 = 4.28342155967104e0;
+static double a3 = .213623493715853e0;
+static double b1 = 6.61053765625462e0;
+static double b2 = 6.40691597760039e0;
+static double b3 = 1.27364489782223e0;
+static double b4 = .036117081018842e0;
+static double c = .577215664901533e0;
+static double ln10 = 2.302585e0;
+static double tol = 1.e-5;
+static double amin[2] = {
+    500.0e0,100.0e0
+};
+static double bmin[2] = {
+    1.e-28,1.e-13
+};
+static double dmin[2] = {
+    1.e-06,1.e-04
+};
+static double emin[2] = {
+    2.e-03,6.e-03
+};
+static double eps0[2] = {
+    1.e-10,1.e-08
+};
+static int K1 = 1;
+static int K2 = 2;
+static int K3 = 3;
+static int K8 = 0;
+static double am1,amax,ap1,ap2,ap3,apn,b,c1,c2,c3,c4,c5,d,e,e2,eps,g,h,pn,qg,qn,
+    r,rta,s,s2,sum,t,u,w,xmax,xmin,xn,y,z;
+static int iop;
+static double T4,T5,T6,T7,T9;
+/*
+     ..
+     .. Executable Statements ..
+*/
+/*
+     ****** E, XMIN, AND XMAX ARE MACHINE DEPENDENT CONSTANTS.
+            E IS THE SMALLEST NUMBER FOR WHICH 1.0 + E .GT. 1.0.
+            XMIN IS THE SMALLEST POSITIVE NUMBER AND XMAX IS THE
+            LARGEST POSITIVE NUMBER.
+*/
+    e = spmpar(&K1);
+    xmin = spmpar(&K2);
+    xmax = spmpar(&K3);
+    *x = 0.0e0;
+    if(*a <= 0.0e0) goto S300;
+    t = *p+*q-1.e0;
+    if(fabs(t) > e) goto S320;
+    *ierr = 0;
+    if(*p == 0.0e0) return;
+    if(*q == 0.0e0) goto S270;
+    if(*a == 1.0e0) goto S280;
+    e2 = 2.0e0*e;
+    amax = 0.4e-10/(e*e);
+    iop = 1;
+    if(e > 1.e-10) iop = 2;
+    eps = eps0[iop-1];
+    xn = *x0;
+    if(*x0 > 0.0e0) goto S160;
+/*
+        SELECTION OF THE INITIAL APPROXIMATION XN OF X
+                       WHEN A .LT. 1
+*/
+    if(*a > 1.0e0) goto S80;
+    T4 = *a+1.0e0;
+    g = Xgamm(&T4);
+    qg = *q*g;
+    if(qg == 0.0e0) goto S360;
+    b = qg/ *a;
+    if(qg > 0.6e0**a) goto S40;
+    if(*a >= 0.30e0 || b < 0.35e0) goto S10;
+    t = exp(-(b+c));
+    u = t*exp(t);
+    xn = t*exp(u);
+    goto S160;
+S10:
+    if(b >= 0.45e0) goto S40;
+    if(b == 0.0e0) goto S360;
+    y = -log(b);
+    s = 0.5e0+(0.5e0-*a);
+    z = log(y);
+    t = y-s*z;
+    if(b < 0.15e0) goto S20;
+    xn = y-s*log(t)-log(1.0e0+s/(t+1.0e0));
+    goto S220;
+S20:
+    if(b <= 0.01e0) goto S30;
+    u = ((t+2.0e0*(3.0e0-*a))*t+(2.0e0-*a)*(3.0e0-*a))/((t+(5.0e0-*a))*t+2.0e0);
+    xn = y-s*log(t)-log(u);
+    goto S220;
+S30:
+    c1 = -(s*z);
+    c2 = -(s*(1.0e0+c1));
+    c3 = s*((0.5e0*c1+(2.0e0-*a))*c1+(2.5e0-1.5e0**a));
+    c4 = -(s*(((c1/3.0e0+(2.5e0-1.5e0**a))*c1+((*a-6.0e0)**a+7.0e0))*c1+(
+      (11.0e0**a-46.0)**a+47.0e0)/6.0e0));
+    c5 = -(s*((((-(c1/4.0e0)+(11.0e0**a-17.0e0)/6.0e0)*c1+((-(3.0e0**a)+13.0e0)*
+      *a-13.0e0))*c1+0.5e0*(((2.0e0**a-25.0e0)**a+72.0e0)**a-61.0e0))*c1+((
+      (25.0e0**a-195.0e0)**a+477.0e0)**a-379.0e0)/12.0e0));
+    xn = (((c5/y+c4)/y+c3)/y+c2)/y+c1+y;
+    if(*a > 1.0e0) goto S220;
+    if(b > bmin[iop-1]) goto S220;
+    *x = xn;
+    return;
+S40:
+    if(b**q > 1.e-8) goto S50;
+    xn = exp(-(*q/ *a+c));
+    goto S70;
+S50:
+    if(*p <= 0.9e0) goto S60;
+    T5 = -*q;
+    xn = exp((alnrel(&T5)+gamln1(a))/ *a);
+    goto S70;
+S60:
+    xn = exp(log(*p*g)/ *a);
+S70:
+    if(xn == 0.0e0) goto S310;
+    t = 0.5e0+(0.5e0-xn/(*a+1.0e0));
+    xn /= t;
+    goto S160;
+S80:
+/*
+        SELECTION OF THE INITIAL APPROXIMATION XN OF X
+                       WHEN A .GT. 1
+*/
+    if(*q <= 0.5e0) goto S90;
+    w = log(*p);
+    goto S100;
+S90:
+    w = log(*q);
+S100:
+    t = sqrt(-(2.0e0*w));
+    s = t-(((a3*t+a2)*t+a1)*t+a0)/((((b4*t+b3)*t+b2)*t+b1)*t+1.0e0);
+    if(*q > 0.5e0) s = -s;
+    rta = sqrt(*a);
+    s2 = s*s;
+    xn = *a+s*rta+(s2-1.0e0)/3.0e0+s*(s2-7.0e0)/(36.0e0*rta)-((3.0e0*s2+7.0e0)*
+      s2-16.0e0)/(810.0e0**a)+s*((9.0e0*s2+256.0e0)*s2-433.0e0)/(38880.0e0**a*
+      rta);
+    xn = fifdmax1(xn,0.0e0);
+    if(*a < amin[iop-1]) goto S110;
+    *x = xn;
+    d = 0.5e0+(0.5e0-*x/ *a);
+    if(fabs(d) <= dmin[iop-1]) return;
+S110:
+    if(*p <= 0.5e0) goto S130;
+    if(xn < 3.0e0**a) goto S220;
+    y = -(w+gamln(a));
+    d = fifdmax1(2.0e0,*a*(*a-1.0e0));
+    if(y < ln10*d) goto S120;
+    s = 1.0e0-*a;
+    z = log(y);
+    goto S30;
+S120:
+    t = *a-1.0e0;
+    T6 = -(t/(xn+1.0e0));
+    xn = y+t*log(xn)-alnrel(&T6);
+    T7 = -(t/(xn+1.0e0));
+    xn = y+t*log(xn)-alnrel(&T7);
+    goto S220;
+S130:
+    ap1 = *a+1.0e0;
+    if(xn > 0.70e0*ap1) goto S170;
+    w += gamln(&ap1);
+    if(xn > 0.15e0*ap1) goto S140;
+    ap2 = *a+2.0e0;
+    ap3 = *a+3.0e0;
+    *x = exp((w+*x)/ *a);
+    *x = exp((w+*x-log(1.0e0+*x/ap1*(1.0e0+*x/ap2)))/ *a);
+    *x = exp((w+*x-log(1.0e0+*x/ap1*(1.0e0+*x/ap2)))/ *a);
+    *x = exp((w+*x-log(1.0e0+*x/ap1*(1.0e0+*x/ap2*(1.0e0+*x/ap3))))/ *a);
+    xn = *x;
+    if(xn > 1.e-2*ap1) goto S140;
+    if(xn <= emin[iop-1]*ap1) return;
+    goto S170;
+S140:
+    apn = ap1;
+    t = xn/apn;
+    sum = 1.0e0+t;
+S150:
+    apn += 1.0e0;
+    t *= (xn/apn);
+    sum += t;
+    if(t > 1.e-4) goto S150;
+    t = w-log(sum);
+    xn = exp((xn+t)/ *a);
+    xn *= (1.0e0-(*a*log(xn)-xn-t)/(*a-xn));
+    goto S170;
+S160:
+/*
+                 SCHRODER ITERATION USING P
+*/
+    if(*p > 0.5e0) goto S220;
+S170:
+    if(*p <= 1.e10*xmin) goto S350;
+    am1 = *a-0.5e0-0.5e0;
+S180:
+    if(*a <= amax) goto S190;
+    d = 0.5e0+(0.5e0-xn/ *a);
+    if(fabs(d) <= e2) goto S350;
+S190:
+    if(*ierr >= 20) goto S330;
+    *ierr += 1;
+    gratio(a,&xn,&pn,&qn,&K8);
+    if(pn == 0.0e0 || qn == 0.0e0) goto S350;
+    r = rcomp(a,&xn);
+    if(r == 0.0e0) goto S350;
+    t = (pn-*p)/r;
+    w = 0.5e0*(am1-xn);
+    if(fabs(t) <= 0.1e0 && fabs(w*t) <= 0.1e0) goto S200;
+    *x = xn*(1.0e0-t);
+    if(*x <= 0.0e0) goto S340;
+    d = fabs(t);
+    goto S210;
+S200:
+    h = t*(1.0e0+w*t);
+    *x = xn*(1.0e0-h);
+    if(*x <= 0.0e0) goto S340;
+    if(fabs(w) >= 1.0e0 && fabs(w)*t*t <= eps) return;
+    d = fabs(h);
+S210:
+    xn = *x;
+    if(d > tol) goto S180;
+    if(d <= eps) return;
+    if(fabs(*p-pn) <= tol**p) return;
+    goto S180;
+S220:
+/*
+                 SCHRODER ITERATION USING Q
+*/
+    if(*q <= 1.e10*xmin) goto S350;
+    am1 = *a-0.5e0-0.5e0;
+S230:
+    if(*a <= amax) goto S240;
+    d = 0.5e0+(0.5e0-xn/ *a);
+    if(fabs(d) <= e2) goto S350;
+S240:
+    if(*ierr >= 20) goto S330;
+    *ierr += 1;
+    gratio(a,&xn,&pn,&qn,&K8);
+    if(pn == 0.0e0 || qn == 0.0e0) goto S350;
+    r = rcomp(a,&xn);
+    if(r == 0.0e0) goto S350;
+    t = (*q-qn)/r;
+    w = 0.5e0*(am1-xn);
+    if(fabs(t) <= 0.1e0 && fabs(w*t) <= 0.1e0) goto S250;
+    *x = xn*(1.0e0-t);
+    if(*x <= 0.0e0) goto S340;
+    d = fabs(t);
+    goto S260;
+S250:
+    h = t*(1.0e0+w*t);
+    *x = xn*(1.0e0-h);
+    if(*x <= 0.0e0) goto S340;
+    if(fabs(w) >= 1.0e0 && fabs(w)*t*t <= eps) return;
+    d = fabs(h);
+S260:
+    xn = *x;
+    if(d > tol) goto S230;
+    if(d <= eps) return;
+    if(fabs(*q-qn) <= tol**q) return;
+    goto S230;
+S270:
+/*
+                       SPECIAL CASES
+*/
+    *x = xmax;
+    return;
+S280:
+    if(*q < 0.9e0) goto S290;
+    T9 = -*p;
+    *x = -alnrel(&T9);
+    return;
+S290:
+    *x = -log(*q);
+    return;
+S300:
+/*
+                       ERROR RETURN
+*/
+    *ierr = -2;
+    return;
+S310:
+    *ierr = -3;
+    return;
+S320:
+    *ierr = -4;
+    return;
+S330:
+    *ierr = -6;
+    return;
+S340:
+    *ierr = -7;
+    return;
+S350:
+    *x = xn;
+    *ierr = -8;
+    return;
+S360:
+    *x = xmax;
+    *ierr = -8;
+    return;
+} /* END */
+
+/***=====================================================================***/
+static double gamln(double *a)
+/*
+-----------------------------------------------------------------------
+            EVALUATION OF LN(GAMMA(A)) FOR POSITIVE A
+-----------------------------------------------------------------------
+     WRITTEN BY ALFRED H. MORRIS
+          NAVAL SURFACE WARFARE CENTER
+          DAHLGREN, VIRGINIA
+--------------------------
+     D = 0.5*(LN(2*PI) - 1)
+--------------------------
+*/
+{
+static double c0 = .833333333333333e-01;
+static double c1 = -.277777777760991e-02;
+static double c2 = .793650666825390e-03;
+static double c3 = -.595202931351870e-03;
+static double c4 = .837308034031215e-03;
+static double c5 = -.165322962780713e-02;
+static double d = .418938533204673e0;
+static double gamln,t,w;
+static int i,n;
+static double T1;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    if(*a > 0.8e0) goto S10;
+    gamln = gamln1(a)-log(*a);
+    return gamln;
+S10:
+    if(*a > 2.25e0) goto S20;
+    t = *a-0.5e0-0.5e0;
+    gamln = gamln1(&t);
+    return gamln;
+S20:
+    if(*a >= 10.0e0) goto S40;
+    n = *a-1.25e0;
+    t = *a;
+    w = 1.0e0;
+    for(i=1; i<=n; i++) {
+        t -= 1.0e0;
+        w = t*w;
+    }
+    T1 = t-1.0e0;
+    gamln = gamln1(&T1)+log(w);
+    return gamln;
+S40:
+    t = pow(1.0e0/ *a,2.0);
+    w = (((((c5*t+c4)*t+c3)*t+c2)*t+c1)*t+c0)/ *a;
+    gamln = d+w+(*a-0.5e0)*(log(*a)-1.0e0);
+    return gamln;
+} /* END */
+
+/***=====================================================================***/
+static double gamln1(double *a)
+/*
+-----------------------------------------------------------------------
+     EVALUATION OF LN(GAMMA(1 + A)) FOR -0.2 .LE. A .LE. 1.25
+-----------------------------------------------------------------------
+*/
+{
+static double p0 = .577215664901533e+00;
+static double p1 = .844203922187225e+00;
+static double p2 = -.168860593646662e+00;
+static double p3 = -.780427615533591e+00;
+static double p4 = -.402055799310489e+00;
+static double p5 = -.673562214325671e-01;
+static double p6 = -.271935708322958e-02;
+static double q1 = .288743195473681e+01;
+static double q2 = .312755088914843e+01;
+static double q3 = .156875193295039e+01;
+static double q4 = .361951990101499e+00;
+static double q5 = .325038868253937e-01;
+static double q6 = .667465618796164e-03;
+static double r0 = .422784335098467e+00;
+static double r1 = .848044614534529e+00;
+static double r2 = .565221050691933e+00;
+static double r3 = .156513060486551e+00;
+static double r4 = .170502484022650e-01;
+static double r5 = .497958207639485e-03;
+static double s1 = .124313399877507e+01;
+static double s2 = .548042109832463e+00;
+static double s3 = .101552187439830e+00;
+static double s4 = .713309612391000e-02;
+static double s5 = .116165475989616e-03;
+static double gamln1,w,x;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    if(*a >= 0.6e0) goto S10;
+    w = ((((((p6**a+p5)**a+p4)**a+p3)**a+p2)**a+p1)**a+p0)/((((((q6**a+q5)**a+
+      q4)**a+q3)**a+q2)**a+q1)**a+1.0e0);
+    gamln1 = -(*a*w);
+    return gamln1;
+S10:
+    x = *a-0.5e0-0.5e0;
+    w = (((((r5*x+r4)*x+r3)*x+r2)*x+r1)*x+r0)/(((((s5*x+s4)*x+s3)*x+s2)*x+s1)*x
+      +1.0e0);
+    gamln1 = x*w;
+    return gamln1;
+} /* END */
+
+/***=====================================================================***/
+static double Xgamm(double *a)
+/*
+-----------------------------------------------------------------------
+
+         EVALUATION OF THE GAMMA FUNCTION FOR REAL ARGUMENTS
+
+                           -----------
+
+     GAMMA(A) IS ASSIGNED THE VALUE 0 WHEN THE GAMMA FUNCTION CANNOT
+     BE COMPUTED.
+
+-----------------------------------------------------------------------
+     WRITTEN BY ALFRED H. MORRIS, JR.
+          NAVAL SURFACE WEAPONS CENTER
+          DAHLGREN, VIRGINIA
+-----------------------------------------------------------------------
+*/
+{
+static double d = .41893853320467274178e0;
+static double pi = 3.1415926535898e0;
+static double r1 = .820756370353826e-03;
+static double r2 = -.595156336428591e-03;
+static double r3 = .793650663183693e-03;
+static double r4 = -.277777777770481e-02;
+static double r5 = .833333333333333e-01;
+static double p[7] = {
+    .539637273585445e-03,.261939260042690e-02,.204493667594920e-01,
+    .730981088720487e-01,.279648642639792e+00,.553413866010467e+00,1.0e0
+};
+static double q[7] = {
+    -.832979206704073e-03,.470059485860584e-02,.225211131035340e-01,
+    -.170458969313360e+00,-.567902761974940e-01,.113062953091122e+01,1.0e0
+};
+static int K2 = 3;
+static int K3 = 0;
+static double Xgamm,bot,g,lnx,s,t,top,w,x,z;
+static int i,j,m,n,T1;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    Xgamm = 0.0e0;
+    x = *a;
+    if(fabs(*a) >= 15.0e0) goto S110;
+/*
+-----------------------------------------------------------------------
+            EVALUATION OF GAMMA(A) FOR ABS(A) .LT. 15
+-----------------------------------------------------------------------
+*/
+    t = 1.0e0;
+    m = fifidint(*a)-1;
+/*
+     LET T BE THE PRODUCT OF A-J WHEN A .GE. 2
+*/
+    T1 = m;
+    if(T1 < 0) goto S40;
+    else if(T1 == 0) goto S30;
+    else  goto S10;
+S10:
+    for(j=1; j<=m; j++) {
+        x -= 1.0e0;
+        t = x*t;
+    }
+S30:
+    x -= 1.0e0;
+    goto S80;
+S40:
+/*
+     LET T BE THE PRODUCT OF A+J WHEN A .LT. 1
+*/
+    t = *a;
+    if(*a > 0.0e0) goto S70;
+    m = -m-1;
+    if(m == 0) goto S60;
+    for(j=1; j<=m; j++) {
+        x += 1.0e0;
+        t = x*t;
+    }
+S60:
+    x += (0.5e0+0.5e0);
+    t = x*t;
+    if(t == 0.0e0) return Xgamm;
+S70:
+/*
+     THE FOLLOWING CODE CHECKS IF 1/T CAN OVERFLOW. THIS
+     CODE MAY BE OMITTED IF DESIRED.
+*/
+    if(fabs(t) >= 1.e-30) goto S80;
+    if(fabs(t)*spmpar(&K2) <= 1.0001e0) return Xgamm;
+    Xgamm = 1.0e0/t;
+    return Xgamm;
+S80:
+/*
+     COMPUTE GAMMA(1 + X) FOR  0 .LE. X .LT. 1
+*/
+    top = p[0];
+    bot = q[0];
+    for(i=1; i<7; i++) {
+        top = p[i]+x*top;
+        bot = q[i]+x*bot;
+    }
+    Xgamm = top/bot;
+/*
+     TERMINATION
+*/
+    if(*a < 1.0e0) goto S100;
+    Xgamm *= t;
+    return Xgamm;
+S100:
+    Xgamm /= t;
+    return Xgamm;
+S110:
+/*
+-----------------------------------------------------------------------
+            EVALUATION OF GAMMA(A) FOR ABS(A) .GE. 15
+-----------------------------------------------------------------------
+*/
+    if(fabs(*a) >= 1.e3) return Xgamm;
+    if(*a > 0.0e0) goto S120;
+    x = -*a;
+    n = x;
+    t = x-(double)n;
+    if(t > 0.9e0) t = 1.0e0-t;
+    s = sin(pi*t)/pi;
+    if(fifmod(n,2) == 0) s = -s;
+    if(s == 0.0e0) return Xgamm;
+S120:
+/*
+     COMPUTE THE MODIFIED ASYMPTOTIC SUM
+*/
+    t = 1.0e0/(x*x);
+    g = ((((r1*t+r2)*t+r3)*t+r4)*t+r5)/x;
+/*
+     ONE MAY REPLACE THE NEXT STATEMENT WITH  LNX = ALOG(X)
+     BUT LESS ACCURACY WILL NORMALLY BE OBTAINED.
+*/
+    lnx = log(x);
+/*
+     FINAL ASSEMBLY
+*/
+    z = x;
+    g = d+g+(z-0.5e0)*(lnx-1.e0);
+    w = g;
+    t = g-w;
+    if(w > 0.99999e0*exparg(&K3)) return Xgamm;
+    Xgamm = exp(w)*(1.0e0+t);
+    if(*a < 0.0e0) Xgamm = 1.0e0/(Xgamm*s)/x;
+    return Xgamm;
+} /* END */
+
+/***=====================================================================***/
+static void grat1(double *a,double *x,double *r,double *p,double *q,
+       double *eps)
+{
+static int K2 = 0;
+static double a2n,a2nm1,am0,an,an0,b2n,b2nm1,c,cma,g,h,j,l,sum,t,tol,w,z,T1,T3;
+/*
+     ..
+     .. Executable Statements ..
+*/
+/*
+-----------------------------------------------------------------------
+        EVALUATION OF THE INCOMPLETE GAMMA RATIO FUNCTIONS
+                      P(A,X) AND Q(A,X)
+     IT IS ASSUMED THAT A .LE. 1.  EPS IS THE TOLERANCE TO BE USED.
+     THE INPUT ARGUMENT R HAS THE VALUE E**(-X)*X**A/GAMMA(A).
+-----------------------------------------------------------------------
+*/
+    if(*a**x == 0.0e0) goto S120;
+    if(*a == 0.5e0) goto S100;
+    if(*x < 1.1e0) goto S10;
+    goto S60;
+S10:
+/*
+             TAYLOR SERIES FOR P(A,X)/X**A
+*/
+    an = 3.0e0;
+    c = *x;
+    sum = *x/(*a+3.0e0);
+    tol = 0.1e0**eps/(*a+1.0e0);
+S20:
+    an += 1.0e0;
+    c = -(c*(*x/an));
+    t = c/(*a+an);
+    sum += t;
+    if(fabs(t) > tol) goto S20;
+    j = *a**x*((sum/6.0e0-0.5e0/(*a+2.0e0))**x+1.0e0/(*a+1.0e0));
+    z = *a*log(*x);
+    h = gam1(a);
+    g = 1.0e0+h;
+    if(*x < 0.25e0) goto S30;
+    if(*a < *x/2.59e0) goto S50;
+    goto S40;
+S30:
+    if(z > -.13394e0) goto S50;
+S40:
+    w = exp(z);
+    *p = w*g*(0.5e0+(0.5e0-j));
+    *q = 0.5e0+(0.5e0-*p);
+    return;
+S50:
+    l = rexp(&z);
+    w = 0.5e0+(0.5e0+l);
+    *q = (w*j-l)*g-h;
+    if(*q < 0.0e0) goto S90;
+    *p = 0.5e0+(0.5e0-*q);
+    return;
+S60:
+/*
+              CONTINUED FRACTION EXPANSION
+*/
+    a2nm1 = a2n = 1.0e0;
+    b2nm1 = *x;
+    b2n = *x+(1.0e0-*a);
+    c = 1.0e0;
+S70:
+    a2nm1 = *x*a2n+c*a2nm1;
+    b2nm1 = *x*b2n+c*b2nm1;
+    am0 = a2nm1/b2nm1;
+    c += 1.0e0;
+    cma = c-*a;
+    a2n = a2nm1+cma*a2n;
+    b2n = b2nm1+cma*b2n;
+    an0 = a2n/b2n;
+    if(fabs(an0-am0) >= *eps*an0) goto S70;
+    *q = *r*an0;
+    *p = 0.5e0+(0.5e0-*q);
+    return;
+S80:
+/*
+                SPECIAL CASES
+*/
+    *p = 0.0e0;
+    *q = 1.0e0;
+    return;
+S90:
+    *p = 1.0e0;
+    *q = 0.0e0;
+    return;
+S100:
+    if(*x >= 0.25e0) goto S110;
+    T1 = sqrt(*x);
+    *p = erf1(&T1);
+    *q = 0.5e0+(0.5e0-*p);
+    return;
+S110:
+    T3 = sqrt(*x);
+    *q = erfc1(&K2,&T3);
+    *p = 0.5e0+(0.5e0-*q);
+    return;
+S120:
+    if(*x <= *a) goto S80;
+    goto S90;
+} /* END */
+
+/***=====================================================================***/
+static void gratio(double *a,double *x,double *ans,double *qans,int *ind)
+/*
+ ----------------------------------------------------------------------
+        EVALUATION OF THE INCOMPLETE GAMMA RATIO FUNCTIONS
+                      P(A,X) AND Q(A,X)
+
+                        ----------
+
+     IT IS ASSUMED THAT A AND X ARE NONNEGATIVE, WHERE A AND X
+     ARE NOT BOTH 0.
+
+     ANS AND QANS ARE VARIABLES. GRATIO ASSIGNS ANS THE VALUE
+     P(A,X) AND QANS THE VALUE Q(A,X). IND MAY BE ANY INTEGER.
+     IF IND = 0 THEN THE USER IS REQUESTING AS MUCH ACCURACY AS
+     POSSIBLE (UP TO 14 SIGNIFICANT DIGITS). OTHERWISE, IF
+     IND = 1 THEN ACCURACY IS REQUESTED TO WITHIN 1 UNIT OF THE
+     6-TH SIGNIFICANT DIGIT, AND IF IND .NE. 0,1 THEN ACCURACY
+     IS REQUESTED TO WITHIN 1 UNIT OF THE 3RD SIGNIFICANT DIGIT.
+
+     ERROR RETURN ...
+        ANS IS ASSIGNED THE VALUE 2 WHEN A OR X IS NEGATIVE,
+     WHEN A*X = 0, OR WHEN P(A,X) AND Q(A,X) ARE INDETERMINANT.
+     P(A,X) AND Q(A,X) ARE COMPUTATIONALLY INDETERMINANT WHEN
+     X IS EXCEEDINGLY CLOSE TO A AND A IS EXTREMELY LARGE.
+ ----------------------------------------------------------------------
+     WRITTEN BY ALFRED H. MORRIS, JR.
+        NAVAL SURFACE WEAPONS CENTER
+        DAHLGREN, VIRGINIA
+     --------------------
+*/
+{
+static double alog10 = 2.30258509299405e0;
+static double d10 = -.185185185185185e-02;
+static double d20 = .413359788359788e-02;
+static double d30 = .649434156378601e-03;
+static double d40 = -.861888290916712e-03;
+static double d50 = -.336798553366358e-03;
+static double d60 = .531307936463992e-03;
+static double d70 = .344367606892378e-03;
+static double rt2pin = .398942280401433e0;
+static double rtpi = 1.77245385090552e0;
+static double third = .333333333333333e0;
+static double acc0[3] = {
+    5.e-15,5.e-7,5.e-4
+};
+static double big[3] = {
+    20.0e0,14.0e0,10.0e0
+};
+static double d0[13] = {
+    .833333333333333e-01,-.148148148148148e-01,.115740740740741e-02,
+    .352733686067019e-03,-.178755144032922e-03,.391926317852244e-04,
+    -.218544851067999e-05,-.185406221071516e-05,.829671134095309e-06,
+    -.176659527368261e-06,.670785354340150e-08,.102618097842403e-07,
+    -.438203601845335e-08
+};
+static double d1[12] = {
+    -.347222222222222e-02,.264550264550265e-02,-.990226337448560e-03,
+    .205761316872428e-03,-.401877572016461e-06,-.180985503344900e-04,
+    .764916091608111e-05,-.161209008945634e-05,.464712780280743e-08,
+    .137863344691572e-06,-.575254560351770e-07,.119516285997781e-07
+};
+static double d2[10] = {
+    -.268132716049383e-02,.771604938271605e-03,.200938786008230e-05,
+    -.107366532263652e-03,.529234488291201e-04,-.127606351886187e-04,
+    .342357873409614e-07,.137219573090629e-05,-.629899213838006e-06,
+    .142806142060642e-06
+};
+static double d3[8] = {
+    .229472093621399e-03,-.469189494395256e-03,.267720632062839e-03,
+    -.756180167188398e-04,-.239650511386730e-06,.110826541153473e-04,
+    -.567495282699160e-05,.142309007324359e-05
+};
+static double d4[6] = {
+    .784039221720067e-03,-.299072480303190e-03,-.146384525788434e-05,
+    .664149821546512e-04,-.396836504717943e-04,.113757269706784e-04
+};
+static double d5[4] = {
+    -.697281375836586e-04,.277275324495939e-03,-.199325705161888e-03,
+    .679778047793721e-04
+};
+static double d6[2] = {
+    -.592166437353694e-03,.270878209671804e-03
+};
+static double e00[3] = {
+    .25e-3,.25e-1,.14e0
+};
+static double x00[3] = {
+    31.0e0,17.0e0,9.7e0
+};
+static int K1 = 1;
+static int K2 = 0;
+static double a2n,a2nm1,acc,am0,amn,an,an0,apn,b2n,b2nm1,c,c0,c1,c2,c3,c4,c5,c6,
+    cma,e,e0,g,h,j,l,r,rta,rtx,s,sum,t,t1,tol,twoa,u,w,x0,y,z;
+static int i,iop,m,max,n;
+static double wk[20],T3;
+static int T4,T5;
+static double T6,T7;
+/*
+     ..
+     .. Executable Statements ..
+*/
+/*
+     --------------------
+     ****** E IS A MACHINE DEPENDENT CONSTANT. E IS THE SMALLEST
+            FLOATING POINT NUMBER FOR WHICH 1.0 + E .GT. 1.0 .
+*/
+    e = spmpar(&K1);
+    if(*a < 0.0e0 || *x < 0.0e0) goto S430;
+    if(*a == 0.0e0 && *x == 0.0e0) goto S430;
+    if(*a**x == 0.0e0) goto S420;
+    iop = *ind+1;
+    if(iop != 1 && iop != 2) iop = 3;
+    acc = fifdmax1(acc0[iop-1],e);
+    e0 = e00[iop-1];
+    x0 = x00[iop-1];
+/*
+            SELECT THE APPROPRIATE ALGORITHM
+*/
+    if(*a >= 1.0e0) goto S10;
+    if(*a == 0.5e0) goto S390;
+    if(*x < 1.1e0) goto S160;
+    t1 = *a*log(*x)-*x;
+    u = *a*exp(t1);
+    if(u == 0.0e0) goto S380;
+    r = u*(1.0e0+gam1(a));
+    goto S250;
+S10:
+    if(*a >= big[iop-1]) goto S30;
+    if(*a > *x || *x >= x0) goto S20;
+    twoa = *a+*a;
+    m = fifidint(twoa);
+    if(twoa != (double)m) goto S20;
+    i = m/2;
+    if(*a == (double)i) goto S210;
+    goto S220;
+S20:
+    t1 = *a*log(*x)-*x;
+    r = exp(t1)/Xgamm(a);
+    goto S40;
+S30:
+    l = *x/ *a;
+    if(l == 0.0e0) goto S370;
+    s = 0.5e0+(0.5e0-l);
+    z = rlog(&l);
+    if(z >= 700.0e0/ *a) goto S410;
+    y = *a*z;
+    rta = sqrt(*a);
+    if(fabs(s) <= e0/rta) goto S330;
+    if(fabs(s) <= 0.4e0) goto S270;
+    t = pow(1.0e0/ *a,2.0);
+    t1 = (((0.75e0*t-1.0e0)*t+3.5e0)*t-105.0e0)/(*a*1260.0e0);
+    t1 -= y;
+    r = rt2pin*rta*exp(t1);
+S40:
+    if(r == 0.0e0) goto S420;
+    if(*x <= fifdmax1(*a,alog10)) goto S50;
+    if(*x < x0) goto S250;
+    goto S100;
+S50:
+/*
+                 TAYLOR SERIES FOR P/R
+*/
+    apn = *a+1.0e0;
+    t = *x/apn;
+    wk[0] = t;
+    for(n=2; n<=20; n++) {
+        apn += 1.0e0;
+        t *= (*x/apn);
+        if(t <= 1.e-3) goto S70;
+        wk[n-1] = t;
+    }
+    n = 20;
+S70:
+    sum = t;
+    tol = 0.5e0*acc;
+S80:
+    apn += 1.0e0;
+    t *= (*x/apn);
+    sum += t;
+    if(t > tol) goto S80;
+    max = n-1;
+    for(m=1; m<=max; m++) {
+        n -= 1;
+        sum += wk[n-1];
+    }
+    *ans = r/ *a*(1.0e0+sum);
+    *qans = 0.5e0+(0.5e0-*ans);
+    return;
+S100:
+/*
+                 ASYMPTOTIC EXPANSION
+*/
+    amn = *a-1.0e0;
+    t = amn/ *x;
+    wk[0] = t;
+    for(n=2; n<=20; n++) {
+        amn -= 1.0e0;
+        t *= (amn/ *x);
+        if(fabs(t) <= 1.e-3) goto S120;
+        wk[n-1] = t;
+    }
+    n = 20;
+S120:
+    sum = t;
+S130:
+    if(fabs(t) <= acc) goto S140;
+    amn -= 1.0e0;
+    t *= (amn/ *x);
+    sum += t;
+    goto S130;
+S140:
+    max = n-1;
+    for(m=1; m<=max; m++) {
+        n -= 1;
+        sum += wk[n-1];
+    }
+    *qans = r/ *x*(1.0e0+sum);
+    *ans = 0.5e0+(0.5e0-*qans);
+    return;
+S160:
+/*
+             TAYLOR SERIES FOR P(A,X)/X**A
+*/
+    an = 3.0e0;
+    c = *x;
+    sum = *x/(*a+3.0e0);
+    tol = 3.0e0*acc/(*a+1.0e0);
+S170:
+    an += 1.0e0;
+    c = -(c*(*x/an));
+    t = c/(*a+an);
+    sum += t;
+    if(fabs(t) > tol) goto S170;
+    j = *a**x*((sum/6.0e0-0.5e0/(*a+2.0e0))**x+1.0e0/(*a+1.0e0));
+    z = *a*log(*x);
+    h = gam1(a);
+    g = 1.0e0+h;
+    if(*x < 0.25e0) goto S180;
+    if(*a < *x/2.59e0) goto S200;
+    goto S190;
+S180:
+    if(z > -.13394e0) goto S200;
+S190:
+    w = exp(z);
+    *ans = w*g*(0.5e0+(0.5e0-j));
+    *qans = 0.5e0+(0.5e0-*ans);
+    return;
+S200:
+    l = rexp(&z);
+    w = 0.5e0+(0.5e0+l);
+    *qans = (w*j-l)*g-h;
+    if(*qans < 0.0e0) goto S380;
+    *ans = 0.5e0+(0.5e0-*qans);
+    return;
+S210:
+/*
+             FINITE SUMS FOR Q WHEN A .GE. 1
+                 AND 2*A IS AN INTEGER
+*/
+    sum = exp(-*x);
+    t = sum;
+    n = 1;
+    c = 0.0e0;
+    goto S230;
+S220:
+    rtx = sqrt(*x);
+    sum = erfc1(&K2,&rtx);
+    t = exp(-*x)/(rtpi*rtx);
+    n = 0;
+    c = -0.5e0;
+S230:
+    if(n == i) goto S240;
+    n += 1;
+    c += 1.0e0;
+    t = *x*t/c;
+    sum += t;
+    goto S230;
+S240:
+    *qans = sum;
+    *ans = 0.5e0+(0.5e0-*qans);
+    return;
+S250:
+/*
+              CONTINUED FRACTION EXPANSION
+*/
+    tol = fifdmax1(5.0e0*e,acc);
+    a2nm1 = a2n = 1.0e0;
+    b2nm1 = *x;
+    b2n = *x+(1.0e0-*a);
+    c = 1.0e0;
+S260:
+    a2nm1 = *x*a2n+c*a2nm1;
+    b2nm1 = *x*b2n+c*b2nm1;
+    am0 = a2nm1/b2nm1;
+    c += 1.0e0;
+    cma = c-*a;
+    a2n = a2nm1+cma*a2n;
+    b2n = b2nm1+cma*b2n;
+    an0 = a2n/b2n;
+    if(fabs(an0-am0) >= tol*an0) goto S260;
+    *qans = r*an0;
+    *ans = 0.5e0+(0.5e0-*qans);
+    return;
+S270:
+/*
+                GENERAL TEMME EXPANSION
+*/
+    if(fabs(s) <= 2.0e0*e && *a*e*e > 3.28e-3) goto S430;
+    c = exp(-y);
+    T3 = sqrt(y);
+    w = 0.5e0*erfc1(&K1,&T3);
+    u = 1.0e0/ *a;
+    z = sqrt(z+z);
+    if(l < 1.0e0) z = -z;
+    T4 = iop-2;
+    if(T4 < 0) goto S280;
+    else if(T4 == 0) goto S290;
+    else  goto S300;
+S280:
+    if(fabs(s) <= 1.e-3) goto S340;
+    c0 = ((((((((((((d0[12]*z+d0[11])*z+d0[10])*z+d0[9])*z+d0[8])*z+d0[7])*z+d0[
+      6])*z+d0[5])*z+d0[4])*z+d0[3])*z+d0[2])*z+d0[1])*z+d0[0])*z-third;
+    c1 = (((((((((((d1[11]*z+d1[10])*z+d1[9])*z+d1[8])*z+d1[7])*z+d1[6])*z+d1[5]
+      )*z+d1[4])*z+d1[3])*z+d1[2])*z+d1[1])*z+d1[0])*z+d10;
+    c2 = (((((((((d2[9]*z+d2[8])*z+d2[7])*z+d2[6])*z+d2[5])*z+d2[4])*z+d2[3])*z+
+      d2[2])*z+d2[1])*z+d2[0])*z+d20;
+    c3 = (((((((d3[7]*z+d3[6])*z+d3[5])*z+d3[4])*z+d3[3])*z+d3[2])*z+d3[1])*z+
+      d3[0])*z+d30;
+    c4 = (((((d4[5]*z+d4[4])*z+d4[3])*z+d4[2])*z+d4[1])*z+d4[0])*z+d40;
+    c5 = (((d5[3]*z+d5[2])*z+d5[1])*z+d5[0])*z+d50;
+    c6 = (d6[1]*z+d6[0])*z+d60;
+    t = ((((((d70*u+c6)*u+c5)*u+c4)*u+c3)*u+c2)*u+c1)*u+c0;
+    goto S310;
+S290:
+    c0 = (((((d0[5]*z+d0[4])*z+d0[3])*z+d0[2])*z+d0[1])*z+d0[0])*z-third;
+    c1 = (((d1[3]*z+d1[2])*z+d1[1])*z+d1[0])*z+d10;
+    c2 = d2[0]*z+d20;
+    t = (c2*u+c1)*u+c0;
+    goto S310;
+S300:
+    t = ((d0[2]*z+d0[1])*z+d0[0])*z-third;
+S310:
+    if(l < 1.0e0) goto S320;
+    *qans = c*(w+rt2pin*t/rta);
+    *ans = 0.5e0+(0.5e0-*qans);
+    return;
+S320:
+    *ans = c*(w-rt2pin*t/rta);
+    *qans = 0.5e0+(0.5e0-*ans);
+    return;
+S330:
+/*
+               TEMME EXPANSION FOR L = 1
+*/
+    if(*a*e*e > 3.28e-3) goto S430;
+    c = 0.5e0+(0.5e0-y);
+    w = (0.5e0-sqrt(y)*(0.5e0+(0.5e0-y/3.0e0))/rtpi)/c;
+    u = 1.0e0/ *a;
+    z = sqrt(z+z);
+    if(l < 1.0e0) z = -z;
+    T5 = iop-2;
+    if(T5 < 0) goto S340;
+    else if(T5 == 0) goto S350;
+    else  goto S360;
+S340:
+    c0 = ((((((d0[6]*z+d0[5])*z+d0[4])*z+d0[3])*z+d0[2])*z+d0[1])*z+d0[0])*z-
+      third;
+    c1 = (((((d1[5]*z+d1[4])*z+d1[3])*z+d1[2])*z+d1[1])*z+d1[0])*z+d10;
+    c2 = ((((d2[4]*z+d2[3])*z+d2[2])*z+d2[1])*z+d2[0])*z+d20;
+    c3 = (((d3[3]*z+d3[2])*z+d3[1])*z+d3[0])*z+d30;
+    c4 = (d4[1]*z+d4[0])*z+d40;
+    c5 = (d5[1]*z+d5[0])*z+d50;
+    c6 = d6[0]*z+d60;
+    t = ((((((d70*u+c6)*u+c5)*u+c4)*u+c3)*u+c2)*u+c1)*u+c0;
+    goto S310;
+S350:
+    c0 = (d0[1]*z+d0[0])*z-third;
+    c1 = d1[0]*z+d10;
+    t = (d20*u+c1)*u+c0;
+    goto S310;
+S360:
+    t = d0[0]*z-third;
+    goto S310;
+S370:
+/*
+                     SPECIAL CASES
+*/
+    *ans = 0.0e0;
+    *qans = 1.0e0;
+    return;
+S380:
+    *ans = 1.0e0;
+    *qans = 0.0e0;
+    return;
+S390:
+    if(*x >= 0.25e0) goto S400;
+    T6 = sqrt(*x);
+    *ans = erf1(&T6);
+    *qans = 0.5e0+(0.5e0-*ans);
+    return;
+S400:
+    T7 = sqrt(*x);
+    *qans = erfc1(&K2,&T7);
+    *ans = 0.5e0+(0.5e0-*qans);
+    return;
+S410:
+    if(fabs(s) <= 2.0e0*e) goto S430;
+S420:
+    if(*x <= *a) goto S370;
+    goto S380;
+S430:
+/*
+                     ERROR RETURN
+*/
+    *ans = 2.0e0;
+    return;
+} /* END */
+
+/***=====================================================================***/
+static double gsumln(double *a,double *b)
+/*
+-----------------------------------------------------------------------
+          EVALUATION OF THE FUNCTION LN(GAMMA(A + B))
+          FOR 1 .LE. A .LE. 2  AND  1 .LE. B .LE. 2
+-----------------------------------------------------------------------
+*/
+{
+static double gsumln,x,T1,T2;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    x = *a+*b-2.e0;
+    if(x > 0.25e0) goto S10;
+    T1 = 1.0e0+x;
+    gsumln = gamln1(&T1);
+    return gsumln;
+S10:
+    if(x > 1.25e0) goto S20;
+    gsumln = gamln1(&x)+alnrel(&x);
+    return gsumln;
+S20:
+    T2 = x-1.0e0;
+    gsumln = gamln1(&T2)+log(x*(1.0e0+x));
+    return gsumln;
+} /* END */
+
+/***=====================================================================***/
+static double psi(double *xx)
+/*
+---------------------------------------------------------------------
+
+                 EVALUATION OF THE DIGAMMA FUNCTION
+
+                           -----------
+
+     PSI(XX) IS ASSIGNED THE VALUE 0 WHEN THE DIGAMMA FUNCTION CANNOT
+     BE COMPUTED.
+
+     THE MAIN COMPUTATION INVOLVES EVALUATION OF RATIONAL CHEBYSHEV
+     APPROXIMATIONS PUBLISHED IN MATH. COMP. 27, 123-127(1973) BY
+     CODY, STRECOK AND THACHER.
+
+---------------------------------------------------------------------
+     PSI WAS WRITTEN AT ARGONNE NATIONAL LABORATORY FOR THE FUNPACK
+     PACKAGE OF SPECIAL FUNCTION SUBROUTINES. PSI WAS MODIFIED BY
+     A.H. MORRIS (NSWC).
+---------------------------------------------------------------------
+*/
+{
+static double dx0 = 1.461632144968362341262659542325721325e0;
+static double piov4 = .785398163397448e0;
+static double p1[7] = {
+    .895385022981970e-02,.477762828042627e+01,.142441585084029e+03,
+    .118645200713425e+04,.363351846806499e+04,.413810161269013e+04,
+    .130560269827897e+04
+};
+static double p2[4] = {
+    -.212940445131011e+01,-.701677227766759e+01,-.448616543918019e+01,
+    -.648157123766197e+00
+};
+static double q1[6] = {
+    .448452573429826e+02,.520752771467162e+03,.221000799247830e+04,
+    .364127349079381e+04,.190831076596300e+04,.691091682714533e-05
+};
+static double q2[4] = {
+    .322703493791143e+02,.892920700481861e+02,.546117738103215e+02,
+    .777788548522962e+01
+};
+static int K1 = 3;
+static int K2 = 1;
+static double psi,aug,den,sgn,upper,w,x,xmax1,xmx0,xsmall,z;
+static int i,m,n,nq;
+/*
+     ..
+     .. Executable Statements ..
+*/
+/*
+---------------------------------------------------------------------
+     MACHINE DEPENDENT CONSTANTS ...
+        XMAX1  = THE SMALLEST POSITIVE FLOATING POINT CONSTANT
+                 WITH ENTIRELY INTEGER REPRESENTATION.  ALSO USED
+                 AS NEGATIVE OF LOWER BOUND ON ACCEPTABLE NEGATIVE
+                 ARGUMENTS AND AS THE POSITIVE ARGUMENT BEYOND WHICH
+                 PSI MAY BE REPRESENTED AS ALOG(X).
+        XSMALL = ABSOLUTE ARGUMENT BELOW WHICH PI*COTAN(PI*X)
+                 MAY BE REPRESENTED BY 1/X.
+---------------------------------------------------------------------
+*/
+    xmax1 = ipmpar(&K1);
+    xmax1 = fifdmin1(xmax1,1.0e0/spmpar(&K2));
+    xsmall = 1.e-9;
+    x = *xx;
+    aug = 0.0e0;
+    if(x >= 0.5e0) goto S50;
+/*
+---------------------------------------------------------------------
+     X .LT. 0.5,  USE REFLECTION FORMULA
+     PSI(1-X) = PSI(X) + PI * COTAN(PI*X)
+---------------------------------------------------------------------
+*/
+    if(fabs(x) > xsmall) goto S10;
+    if(x == 0.0e0) goto S100;
+/*
+---------------------------------------------------------------------
+     0 .LT. ABS(X) .LE. XSMALL.  USE 1/X AS A SUBSTITUTE
+     FOR  PI*COTAN(PI*X)
+---------------------------------------------------------------------
+*/
+    aug = -(1.0e0/x);
+    goto S40;
+S10:
+/*
+---------------------------------------------------------------------
+     REDUCTION OF ARGUMENT FOR COTAN
+---------------------------------------------------------------------
+*/
+    w = -x;
+    sgn = piov4;
+    if(w > 0.0e0) goto S20;
+    w = -w;
+    sgn = -sgn;
+S20:
+/*
+---------------------------------------------------------------------
+     MAKE AN ERROR EXIT IF X .LE. -XMAX1
+---------------------------------------------------------------------
+*/
+    if(w >= xmax1) goto S100;
+    nq = fifidint(w);
+    w -= (double)nq;
+    nq = fifidint(w*4.0e0);
+    w = 4.0e0*(w-(double)nq*.25e0);
+/*
+---------------------------------------------------------------------
+     W IS NOW RELATED TO THE FRACTIONAL PART OF  4.0 * X.
+     ADJUST ARGUMENT TO CORRESPOND TO VALUES IN FIRST
+     QUADRANT AND DETERMINE SIGN
+---------------------------------------------------------------------
+*/
+    n = nq/2;
+    if(n+n != nq) w = 1.0e0-w;
+    z = piov4*w;
+    m = n/2;
+    if(m+m != n) sgn = -sgn;
+/*
+---------------------------------------------------------------------
+     DETERMINE FINAL VALUE FOR  -PI*COTAN(PI*X)
+---------------------------------------------------------------------
+*/
+    n = (nq+1)/2;
+    m = n/2;
+    m += m;
+    if(m != n) goto S30;
+/*
+---------------------------------------------------------------------
+     CHECK FOR SINGULARITY
+---------------------------------------------------------------------
+*/
+    if(z == 0.0e0) goto S100;
+/*
+---------------------------------------------------------------------
+     USE COS/SIN AS A SUBSTITUTE FOR COTAN, AND
+     SIN/COS AS A SUBSTITUTE FOR TAN
+---------------------------------------------------------------------
+*/
+    aug = sgn*(cos(z)/sin(z)*4.0e0);
+    goto S40;
+S30:
+    aug = sgn*(sin(z)/cos(z)*4.0e0);
+S40:
+    x = 1.0e0-x;
+S50:
+    if(x > 3.0e0) goto S70;
+/*
+---------------------------------------------------------------------
+     0.5 .LE. X .LE. 3.0
+---------------------------------------------------------------------
+*/
+    den = x;
+    upper = p1[0]*x;
+    for(i=1; i<=5; i++) {
+        den = (den+q1[i-1])*x;
+        upper = (upper+p1[i+1-1])*x;
+    }
+    den = (upper+p1[6])/(den+q1[5]);
+    xmx0 = x-dx0;
+    psi = den*xmx0+aug;
+    return psi;
+S70:
+/*
+---------------------------------------------------------------------
+     IF X .GE. XMAX1, PSI = LN(X)
+---------------------------------------------------------------------
+*/
+    if(x >= xmax1) goto S90;
+/*
+---------------------------------------------------------------------
+     3.0 .LT. X .LT. XMAX1
+---------------------------------------------------------------------
+*/
+    w = 1.0e0/(x*x);
+    den = w;
+    upper = p2[0]*w;
+    for(i=1; i<=3; i++) {
+        den = (den+q2[i-1])*w;
+        upper = (upper+p2[i+1-1])*w;
+    }
+    aug = upper/(den+q2[3])-0.5e0/x+aug;
+S90:
+    psi = aug+log(x);
+    return psi;
+S100:
+/*
+---------------------------------------------------------------------
+     ERROR RETURN
+---------------------------------------------------------------------
+*/
+    psi = 0.0e0;
+    return psi;
+} /* END */
+
+/***=====================================================================***/
+static double rcomp(double *a,double *x)
+/*
+     -------------------
+     EVALUATION OF EXP(-X)*X**A/GAMMA(A)
+     -------------------
+     RT2PIN = 1/SQRT(2*PI)
+     -------------------
+*/
+{
+static double rt2pin = .398942280401433e0;
+static double rcomp,t,t1,u;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    rcomp = 0.0e0;
+    if(*a >= 20.0e0) goto S20;
+    t = *a*log(*x)-*x;
+    if(*a >= 1.0e0) goto S10;
+    rcomp = *a*exp(t)*(1.0e0+gam1(a));
+    return rcomp;
+S10:
+    rcomp = exp(t)/Xgamm(a);
+    return rcomp;
+S20:
+    u = *x/ *a;
+    if(u == 0.0e0) return rcomp;
+    t = pow(1.0e0/ *a,2.0);
+    t1 = (((0.75e0*t-1.0e0)*t+3.5e0)*t-105.0e0)/(*a*1260.0e0);
+    t1 -= (*a*rlog(&u));
+    rcomp = rt2pin*sqrt(*a)*exp(t1);
+    return rcomp;
+} /* END */
+
+/***=====================================================================***/
+static double rexp(double *x)
+/*
+-----------------------------------------------------------------------
+            EVALUATION OF THE FUNCTION EXP(X) - 1
+-----------------------------------------------------------------------
+*/
+{
+static double p1 = .914041914819518e-09;
+static double p2 = .238082361044469e-01;
+static double q1 = -.499999999085958e+00;
+static double q2 = .107141568980644e+00;
+static double q3 = -.119041179760821e-01;
+static double q4 = .595130811860248e-03;
+static double rexp,w;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    if(fabs(*x) > 0.15e0) goto S10;
+    rexp = *x*(((p2**x+p1)**x+1.0e0)/((((q4**x+q3)**x+q2)**x+q1)**x+1.0e0));
+    return rexp;
+S10:
+    w = exp(*x);
+    if(*x > 0.0e0) goto S20;
+    rexp = w-0.5e0-0.5e0;
+    return rexp;
+S20:
+    rexp = w*(0.5e0+(0.5e0-1.0e0/w));
+    return rexp;
+} /* END */
+
+/***=====================================================================***/
+static double rlog(double *x)
+/*
+     -------------------
+     COMPUTATION OF  X - 1 - LN(X)
+     -------------------
+*/
+{
+static double a = .566749439387324e-01;
+static double b = .456512608815524e-01;
+static double p0 = .333333333333333e+00;
+static double p1 = -.224696413112536e+00;
+static double p2 = .620886815375787e-02;
+static double q1 = -.127408923933623e+01;
+static double q2 = .354508718369557e+00;
+static double rlog,r,t,u,w,w1;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    if(*x < 0.61e0 || *x > 1.57e0) goto S40;
+    if(*x < 0.82e0) goto S10;
+    if(*x > 1.18e0) goto S20;
+/*
+              ARGUMENT REDUCTION
+*/
+    u = *x-0.5e0-0.5e0;
+    w1 = 0.0e0;
+    goto S30;
+S10:
+    u = *x-0.7e0;
+    u /= 0.7e0;
+    w1 = a-u*0.3e0;
+    goto S30;
+S20:
+    u = 0.75e0**x-1.e0;
+    w1 = b+u/3.0e0;
+S30:
+/*
+               SERIES EXPANSION
+*/
+    r = u/(u+2.0e0);
+    t = r*r;
+    w = ((p2*t+p1)*t+p0)/((q2*t+q1)*t+1.0e0);
+    rlog = 2.0e0*t*(1.0e0/(1.0e0-r)-r*w)+w1;
+    return rlog;
+S40:
+    r = *x-0.5e0-0.5e0;
+    rlog = r-log(*x);
+    return rlog;
+} /* END */
+
+/***=====================================================================***/
+static double rlog1(double *x)
+/*
+-----------------------------------------------------------------------
+             EVALUATION OF THE FUNCTION X - LN(1 + X)
+-----------------------------------------------------------------------
+*/
+{
+static double a = .566749439387324e-01;
+static double b = .456512608815524e-01;
+static double p0 = .333333333333333e+00;
+static double p1 = -.224696413112536e+00;
+static double p2 = .620886815375787e-02;
+static double q1 = -.127408923933623e+01;
+static double q2 = .354508718369557e+00;
+static double rlog1,h,r,t,w,w1;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    if(*x < -0.39e0 || *x > 0.57e0) goto S40;
+    if(*x < -0.18e0) goto S10;
+    if(*x > 0.18e0) goto S20;
+/*
+              ARGUMENT REDUCTION
+*/
+    h = *x;
+    w1 = 0.0e0;
+    goto S30;
+S10:
+    h = *x+0.3e0;
+    h /= 0.7e0;
+    w1 = a-h*0.3e0;
+    goto S30;
+S20:
+    h = 0.75e0**x-0.25e0;
+    w1 = b+h/3.0e0;
+S30:
+/*
+               SERIES EXPANSION
+*/
+    r = h/(h+2.0e0);
+    t = r*r;
+    w = ((p2*t+p1)*t+p0)/((q2*t+q1)*t+1.0e0);
+    rlog1 = 2.0e0*t*(1.0e0/(1.0e0-r)-r*w)+w1;
+    return rlog1;
+S40:
+    w = *x+0.5e0+0.5e0;
+    rlog1 = *x-log(w);
+    return rlog1;
+} /* END */
+
+/***=====================================================================***/
+static double spmpar(int *i)
+/*
+-----------------------------------------------------------------------
+
+     SPMPAR PROVIDES THE SINGLE PRECISION MACHINE CONSTANTS FOR
+     THE COMPUTER BEING USED. IT IS ASSUMED THAT THE ARGUMENT
+     I IS AN INTEGER HAVING ONE OF THE VALUES 1, 2, OR 3. IF THE
+     SINGLE PRECISION ARITHMETIC BEING USED HAS M BASE B DIGITS AND
+     ITS SMALLEST AND LARGEST EXPONENTS ARE EMIN AND EMAX, THEN
+
+        SPMPAR(1) = B**(1 - M), THE MACHINE PRECISION,
+
+        SPMPAR(2) = B**(EMIN - 1), THE SMALLEST MAGNITUDE,
+
+        SPMPAR(3) = B**EMAX*(1 - B**(-M)), THE LARGEST MAGNITUDE.
+
+-----------------------------------------------------------------------
+     WRITTEN BY
+        ALFRED H. MORRIS, JR.
+        NAVAL SURFACE WARFARE CENTER
+        DAHLGREN VIRGINIA
+-----------------------------------------------------------------------
+-----------------------------------------------------------------------
+     MODIFIED BY BARRY W. BROWN TO RETURN DOUBLE PRECISION MACHINE
+     CONSTANTS FOR THE COMPUTER BEING USED.  THIS MODIFICATION WAS
+     MADE AS PART OF CONVERTING BRATIO TO DOUBLE PRECISION
+-----------------------------------------------------------------------
+*/
+{
+static int K1 = 4;
+static int K2 = 8;
+static int K3 = 9;
+static int K4 = 10;
+static double spmpar,b,binv,bm1,one,w,z;
+static int emax,emin,ibeta,m;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    if(*i > 1) goto S10;
+    b = ipmpar(&K1);
+    m = ipmpar(&K2);
+    spmpar = pow(b,(double)(1-m));
+    return spmpar;
+S10:
+    if(*i > 2) goto S20;
+    b = ipmpar(&K1);
+    emin = ipmpar(&K3);
+    one = 1.0;
+    binv = one/b;
+    w = pow(b,(double)(emin+2));
+    spmpar = w*binv*binv*binv;
+    return spmpar;
+S20:
+    ibeta = ipmpar(&K1);
+    m = ipmpar(&K2);
+    emax = ipmpar(&K4);
+    b = ibeta;
+    bm1 = ibeta-1;
+    one = 1.0;
+    z = pow(b,(double)(m-1));
+    w = ((z-one)*b+bm1)/(b*z);
+    z = pow(b,(double)(emax-2));
+    spmpar = w*z*b*b;
+    return spmpar;
+} /* END */
+
+/***=====================================================================***/
+static double stvaln(double *p)
+/*
+**********************************************************************
+
+     double stvaln(double *p)
+                    STarting VALue for Neton-Raphon
+                calculation of Normal distribution Inverse
+
+
+                              Function
+
+
+     Returns X  such that CUMNOR(X)  =   P,  i.e., the  integral from -
+     infinity to X of (1/SQRT(2*PI)) EXP(-U*U/2) dU is P
+
+
+                              Arguments
+
+
+     P --> The probability whose normal deviate is sought.
+                    P is DOUBLE PRECISION
+
+
+                              Method
+
+
+     The  rational   function   on  page 95    of Kennedy  and  Gentle,
+     Statistical Computing, Marcel Dekker, NY , 1980.
+
+**********************************************************************
+*/
+{
+static double xden[5] = {
+    0.993484626060e-1,0.588581570495e0,0.531103462366e0,0.103537752850e0,
+    0.38560700634e-2
+};
+static double xnum[5] = {
+    -0.322232431088e0,-1.000000000000e0,-0.342242088547e0,-0.204231210245e-1,
+    -0.453642210148e-4
+};
+static int K1 = 5;
+static double stvaln,sign,y,z;
+/*
+     ..
+     .. Executable Statements ..
+*/
+    if(!(*p <= 0.5e0)) goto S10;
+    sign = -1.0e0;
+    z = *p;
+    goto S20;
+S10:
+    sign = 1.0e0;
+    z = 1.0e0-*p;
+S20:
+    y = sqrt(-(2.0e0*log(z)));
+    stvaln = y+devlpl(xnum,&K1,&y)/devlpl(xden,&K1,&y);
+    stvaln = sign*stvaln;
+    return stvaln;
+} /* END */
+
+/***=====================================================================***/
+static double fifdint(double a)
+/************************************************************************
+FIFDINT:
+Truncates a double precision number to an integer and returns the
+value in a double.
+************************************************************************/
+/* a     -     number to be truncated */
+{
+  return (double) ((int) a);
+} /* END */
+
+/***=====================================================================***/
+static double fifdmax1(double a,double b)
+/************************************************************************
+FIFDMAX1:
+returns the maximum of two numbers a and b
+************************************************************************/
+/* a     -      first number */
+/* b     -      second number */
+{
+  if (a < b) return b;
+  else return a;
+} /* END */
+
+/***=====================================================================***/
+static double fifdmin1(double a,double b)
+/************************************************************************
+FIFDMIN1:
+returns the minimum of two numbers a and b
+************************************************************************/
+/* a     -     first number */
+/* b     -     second number */
+{
+  if (a < b) return a;
+  else return b;
+} /* END */
+
+/***=====================================================================***/
+static double fifdsign(double mag,double sign)
+/************************************************************************
+FIFDSIGN:
+transfers the sign of the variable "sign" to the variable "mag"
+************************************************************************/
+/* mag     -     magnitude */
+/* sign    -     sign to be transfered */
+{
+  if (mag < 0) mag = -mag;
+  if (sign < 0) mag = -mag;
+  return mag;
+
+} /* END */
+
+/***=====================================================================***/
+static long fifidint(double a)
+/************************************************************************
+FIFIDINT:
+Truncates a double precision number to a long integer
+************************************************************************/
+/* a - number to be truncated */
+{
+  if (a < 1.0) return (long) 0;
+  else return (long) a;
+} /* END */
+
+/***=====================================================================***/
+static long fifmod(long a,long b)
+/************************************************************************
+FIFMOD:
+returns the modulo of a and b
+************************************************************************/
+/* a - numerator */
+/* b - denominator */
+{
+  return a % b;
+} /* END */
+
+/***=====================================================================***/
+static void ftnstop(char* msg)
+/************************************************************************
+FTNSTOP:
+Prints msg to standard error and then exits
+************************************************************************/
+/* msg - error message */
+{
+  if (msg != NULL) fprintf(stderr,"*** CDFLIB ERROR: %s\n",msg);
+  /** exit(1); **/  /** RWCox - DON'T EXIT */
+} /* END */
+
+/***=====================================================================***/
+static int ipmpar(int *i)
+/*
+-----------------------------------------------------------------------
+
+     IPMPAR PROVIDES THE INTEGER MACHINE CONSTANTS FOR THE COMPUTER
+     THAT IS USED. IT IS ASSUMED THAT THE ARGUMENT I IS AN INTEGER
+     HAVING ONE OF THE VALUES 1-10. IPMPAR(I) HAS THE VALUE ...
+
+  INTEGERS.
+
+     ASSUME INTEGERS ARE REPRESENTED IN THE N-DIGIT, BASE-A FORM
+
+               SIGN ( X(N-1)*A**(N-1) + ... + X(1)*A + X(0) )
+
+               WHERE 0 .LE. X(I) .LT. A FOR I=0,...,N-1.
+
+     IPMPAR(1) = A, THE BASE.
+
+     IPMPAR(2) = N, THE NUMBER OF BASE-A DIGITS.
+
+     IPMPAR(3) = A**N - 1, THE LARGEST MAGNITUDE.
+
+  FLOATING-POINT NUMBERS.
+
+     IT IS ASSUMED THAT THE SINGLE AND DOUBLE PRECISION FLOATING
+     POINT ARITHMETICS HAVE THE SAME BASE, SAY B, AND THAT THE
+     NONZERO NUMBERS ARE REPRESENTED IN THE FORM
+
+               SIGN (B**E) * (X(1)/B + ... + X(M)/B**M)
+
+               WHERE X(I) = 0,1,...,B-1 FOR I=1,...,M,
+               X(1) .GE. 1, AND EMIN .LE. E .LE. EMAX.
+
+     IPMPAR(4) = B, THE BASE.
+
+  SINGLE-PRECISION
+
+     IPMPAR(5) = M, THE NUMBER OF BASE-B DIGITS.
+
+     IPMPAR(6) = EMIN, THE SMALLEST EXPONENT E.
+
+     IPMPAR(7) = EMAX, THE LARGEST EXPONENT E.
+
+  DOUBLE-PRECISION
+
+     IPMPAR(8) = M, THE NUMBER OF BASE-B DIGITS.
+
+     IPMPAR(9) = EMIN, THE SMALLEST EXPONENT E.
+
+     IPMPAR(10) = EMAX, THE LARGEST EXPONENT E.
+
+-----------------------------------------------------------------------
+
+     TO DEFINE THIS FUNCTION FOR THE COMPUTER BEING USED REMOVE
+     THE COMMENT DELIMITORS FROM THE DEFINITIONS DIRECTLY BELOW THE NAME
+     OF THE MACHINE
+
+*** RWCox: at this time, the IEEE parameters are enabled.
+
+-----------------------------------------------------------------------
+
+     IPMPAR IS AN ADAPTATION OF THE FUNCTION I1MACH, WRITTEN BY
+     P.A. FOX, A.D. HALL, AND N.L. SCHRYER (BELL LABORATORIES).
+     IPMPAR WAS FORMED BY A.H. MORRIS (NSWC). THE CONSTANTS ARE
+     FROM BELL LABORATORIES, NSWC, AND OTHER SOURCES.
+
+-----------------------------------------------------------------------
+     .. Scalar Arguments ..
+*/
+{
+static int imach[11];
+static int outval ;
+/*     MACHINE CONSTANTS FOR AMDAHL MACHINES. */
+/*
+   imach[1] = 2;
+   imach[2] = 31;
+   imach[3] = 2147483647;
+   imach[4] = 16;
+   imach[5] = 6;
+   imach[6] = -64;
+   imach[7] = 63;
+   imach[8] = 14;
+   imach[9] = -64;
+   imach[10] = 63;
+*/
+/*     MACHINE CONSTANTS FOR THE AT&T 3B SERIES, AT&T
+       PC 7300, AND AT&T 6300. */
+/*
+   imach[1] = 2;
+   imach[2] = 31;
+   imach[3] = 2147483647;
+   imach[4] = 2;
+   imach[5] = 24;
+   imach[6] = -125;
+   imach[7] = 128;
+   imach[8] = 53;
+   imach[9] = -1021;
+   imach[10] = 1024;
+*/
+/*     MACHINE CONSTANTS FOR THE BURROUGHS 1700 SYSTEM. */
+/*
+   imach[1] = 2;
+   imach[2] = 33;
+   imach[3] = 8589934591;
+   imach[4] = 2;
+   imach[5] = 24;
+   imach[6] = -256;
+   imach[7] = 255;
+   imach[8] = 60;
+   imach[9] = -256;
+   imach[10] = 255;
+*/
+/*     MACHINE CONSTANTS FOR THE BURROUGHS 5700 SYSTEM. */
+/*
+   imach[1] = 2;
+   imach[2] = 39;
+   imach[3] = 549755813887;
+   imach[4] = 8;
+   imach[5] = 13;
+   imach[6] = -50;
+   imach[7] = 76;
+   imach[8] = 26;
+   imach[9] = -50;
+   imach[10] = 76;
+*/
+/*     MACHINE CONSTANTS FOR THE BURROUGHS 6700/7700 SYSTEMS. */
+/*
+   imach[1] = 2;
+   imach[2] = 39;
+   imach[3] = 549755813887;
+   imach[4] = 8;
+   imach[5] = 13;
+   imach[6] = -50;
+   imach[7] = 76;
+   imach[8] = 26;
+   imach[9] = -32754;
+   imach[10] = 32780;
+*/
+/*     MACHINE CONSTANTS FOR THE CDC 6000/7000 SERIES
+       60 BIT ARITHMETIC, AND THE CDC CYBER 995 64 BIT
+       ARITHMETIC (NOS OPERATING SYSTEM). */
+/*
+   imach[1] = 2;
+   imach[2] = 48;
+   imach[3] = 281474976710655;
+   imach[4] = 2;
+   imach[5] = 48;
+   imach[6] = -974;
+   imach[7] = 1070;
+   imach[8] = 95;
+   imach[9] = -926;
+   imach[10] = 1070;
+*/
+/*     MACHINE CONSTANTS FOR THE CDC CYBER 995 64 BIT
+       ARITHMETIC (NOS/VE OPERATING SYSTEM). */
+/*
+   imach[1] = 2;
+   imach[2] = 63;
+   imach[3] = 9223372036854775807;
+   imach[4] = 2;
+   imach[5] = 48;
+   imach[6] = -4096;
+   imach[7] = 4095;
+   imach[8] = 96;
+   imach[9] = -4096;
+   imach[10] = 4095;
+*/
+/*     MACHINE CONSTANTS FOR THE CRAY 1, XMP, 2, AND 3. */
+/*
+   imach[1] = 2;
+   imach[2] = 63;
+   imach[3] = 9223372036854775807;
+   imach[4] = 2;
+   imach[5] = 47;
+   imach[6] = -8189;
+   imach[7] = 8190;
+   imach[8] = 94;
+   imach[9] = -8099;
+   imach[10] = 8190;
+*/
+/*     MACHINE CONSTANTS FOR THE DATA GENERAL ECLIPSE S/200. */
+/*
+   imach[1] = 2;
+   imach[2] = 15;
+   imach[3] = 32767;
+   imach[4] = 16;
+   imach[5] = 6;
+   imach[6] = -64;
+   imach[7] = 63;
+   imach[8] = 14;
+   imach[9] = -64;
+   imach[10] = 63;
+*/
+/*     MACHINE CONSTANTS FOR THE HARRIS 220. */
+/*
+   imach[1] = 2;
+   imach[2] = 23;
+   imach[3] = 8388607;
+   imach[4] = 2;
+   imach[5] = 23;
+   imach[6] = -127;
+   imach[7] = 127;
+   imach[8] = 38;
+   imach[9] = -127;
+   imach[10] = 127;
+*/
+/*     MACHINE CONSTANTS FOR THE HONEYWELL 600/6000
+       AND DPS 8/70 SERIES. */
+/*
+   imach[1] = 2;
+   imach[2] = 35;
+   imach[3] = 34359738367;
+   imach[4] = 2;
+   imach[5] = 27;
+   imach[6] = -127;
+   imach[7] = 127;
+   imach[8] = 63;
+   imach[9] = -127;
+   imach[10] = 127;
+*/
+/*     MACHINE CONSTANTS FOR THE HP 2100
+       3 WORD DOUBLE PRECISION OPTION WITH FTN4 */
+/*
+   imach[1] = 2;
+   imach[2] = 15;
+   imach[3] = 32767;
+   imach[4] = 2;
+   imach[5] = 23;
+   imach[6] = -128;
+   imach[7] = 127;
+   imach[8] = 39;
+   imach[9] = -128;
+   imach[10] = 127;
+*/
+/*     MACHINE CONSTANTS FOR THE HP 2100
+       4 WORD DOUBLE PRECISION OPTION WITH FTN4 */
+/*
+   imach[1] = 2;
+   imach[2] = 15;
+   imach[3] = 32767;
+   imach[4] = 2;
+   imach[5] = 23;
+   imach[6] = -128;
+   imach[7] = 127;
+   imach[8] = 55;
+   imach[9] = -128;
+   imach[10] = 127;
+*/
+/*     MACHINE CONSTANTS FOR THE HP 9000. */
+/*
+   imach[1] = 2;
+   imach[2] = 31;
+   imach[3] = 2147483647;
+   imach[4] = 2;
+   imach[5] = 24;
+   imach[6] = -126;
+   imach[7] = 128;
+   imach[8] = 53;
+   imach[9] = -1021;
+   imach[10] = 1024;
+*/
+/*     MACHINE CONSTANTS FOR THE IBM 360/370 SERIES,
+       THE ICL 2900, THE ITEL AS/6, THE XEROX SIGMA
+       5/7/9 AND THE SEL SYSTEMS 85/86. */
+/*
+   imach[1] = 2;
+   imach[2] = 31;
+   imach[3] = 2147483647;
+   imach[4] = 16;
+   imach[5] = 6;
+   imach[6] = -64;
+   imach[7] = 63;
+   imach[8] = 14;
+   imach[9] = -64;
+   imach[10] = 63;
+*/
+/*     MACHINE CONSTANTS FOR THE IBM PC. */
+/*
+   imach[1] = 2;
+   imach[2] = 31;
+   imach[3] = 2147483647;
+   imach[4] = 2;
+   imach[5] = 24;
+   imach[6] = -125;
+   imach[7] = 128;
+   imach[8] = 53;
+   imach[9] = -1021;
+   imach[10] = 1024;
+*/
+/*     MACHINE CONSTANTS FOR THE MACINTOSH II - ABSOFT
+       MACFORTRAN II. */
+/*
+   imach[1] = 2;
+   imach[2] = 31;
+   imach[3] = 2147483647;
+   imach[4] = 2;
+   imach[5] = 24;
+   imach[6] = -125;
+   imach[7] = 128;
+   imach[8] = 53;
+   imach[9] = -1021;
+   imach[10] = 1024;
+*/
+/*     MACHINE CONSTANTS FOR THE MICROVAX - VMS FORTRAN. */
+/*
+   imach[1] = 2;
+   imach[2] = 31;
+   imach[3] = 2147483647;
+   imach[4] = 2;
+   imach[5] = 24;
+   imach[6] = -127;
+   imach[7] = 127;
+   imach[8] = 56;
+   imach[9] = -127;
+   imach[10] = 127;
+*/
+/*     MACHINE CONSTANTS FOR THE PDP-10 (KA PROCESSOR). */
+/*
+   imach[1] = 2;
+   imach[2] = 35;
+   imach[3] = 34359738367;
+   imach[4] = 2;
+   imach[5] = 27;
+   imach[6] = -128;
+   imach[7] = 127;
+   imach[8] = 54;
+   imach[9] = -101;
+   imach[10] = 127;
+*/
+/*     MACHINE CONSTANTS FOR THE PDP-10 (KI PROCESSOR). */
+/*
+   imach[1] = 2;
+   imach[2] = 35;
+   imach[3] = 34359738367;
+   imach[4] = 2;
+   imach[5] = 27;
+   imach[6] = -128;
+   imach[7] = 127;
+   imach[8] = 62;
+   imach[9] = -128;
+   imach[10] = 127;
+*/
+/*     MACHINE CONSTANTS FOR THE PDP-11 FORTRAN SUPPORTING
+       32-BIT INTEGER ARITHMETIC. */
+/*
+   imach[1] = 2;
+   imach[2] = 31;
+   imach[3] = 2147483647;
+   imach[4] = 2;
+   imach[5] = 24;
+   imach[6] = -127;
+   imach[7] = 127;
+   imach[8] = 56;
+   imach[9] = -127;
+   imach[10] = 127;
+*/
+/*     MACHINE CONSTANTS FOR THE SEQUENT BALANCE 8000. */
+/*
+   imach[1] = 2;
+   imach[2] = 31;
+   imach[3] = 2147483647;
+   imach[4] = 2;
+   imach[5] = 24;
+   imach[6] = -125;
+   imach[7] = 128;
+   imach[8] = 53;
+   imach[9] = -1021;
+   imach[10] = 1024;
+*/
+/*     MACHINE CONSTANTS FOR THE SILICON GRAPHICS IRIS-4D
+       SERIES (MIPS R3000 PROCESSOR). */
+/*
+   imach[1] = 2;
+   imach[2] = 31;
+   imach[3] = 2147483647;
+   imach[4] = 2;
+   imach[5] = 24;
+   imach[6] = -125;
+   imach[7] = 128;
+   imach[8] = 53;
+   imach[9] = -1021;
+   imach[10] = 1024;
+*/
+/*     MACHINE CONSTANTS FOR IEEE ARITHMETIC MACHINES, SUCH AS THE AT&T
+       3B SERIES, MOTOROLA 68000 BASED MACHINES (E.G. SUN 3 AND AT&T
+       PC 7300), AND 8087 BASED MICROS (E.G. IBM PC AND AT&T 6300). */
+
+   imach[1] = 2;
+   imach[2] = 31;
+   imach[3] = 2147483647;
+   imach[4] = 2;
+   imach[5] = 24;
+   imach[6] = -125;
+   imach[7] = 128;
+   imach[8] = 53;
+   imach[9] = -1021;
+   imach[10] = 1024;
+
+/*     MACHINE CONSTANTS FOR THE UNIVAC 1100 SERIES. */
+/*
+   imach[1] = 2;
+   imach[2] = 35;
+   imach[3] = 34359738367;
+   imach[4] = 2;
+   imach[5] = 27;
+   imach[6] = -128;
+   imach[7] = 127;
+   imach[8] = 60;
+   imach[9] = -1024;
+   imach[10] = 1023;
+*/
+/*     MACHINE CONSTANTS FOR THE VAX 11/780. */
+/*
+   imach[1] = 2;
+   imach[2] = 31;
+   imach[3] = 2147483647;
+   imach[4] = 2;
+   imach[5] = 24;
+   imach[6] = -127;
+   imach[7] = 127;
+   imach[8] = 56;
+   imach[9] = -127;
+   imach[10] = 127;
+*/
+    outval  = imach[*i];
+    return outval ;
+}
+
+/*************************************************************************/
+/*************************************************************************/
+/************************ End of cdflib inclusion ************************/
+/*************************************************************************/
+/*************************************************************************/
+
+/*-----------------------------------------------------------------------*/
+typedef struct { double p,q ; } pqpair ;  /* for returning p=cdf q=1-cdf */
+/*-----------------------------------------------------------------------*/
+#undef  BIGG
+#define BIGG 9.99e+37                     /* a really big number (duh)   */
+/*-----------------------------------------------------------------------*/
+
+/*************************************************************************/
+/******** Internal functions for various statistical computations ********/
+/*************************************************************************/
+
+/*---------------------------------------------------------------
+  F statistic
+-----------------------------------------------------------------*/
+
+static double fstat_pq2s( pqpair pq , double dofnum , double dofden )
+{
+   int which , status ;
+   double p , q , f , dfn , dfd , bound ;
+
+   which  = 2 ;
+   p      = pq.p ; if( p <= 0.0 ) return 0.0 ;
+   q      = pq.q ; if( q <= 0.0 ) return BIGG ;
+   f      = 0.0 ;
+   dfn    = dofnum ;
+   dfd    = dofden ;
+
+   cdff( &which , &p , &q , &f , &dfn , &dfd , &status , &bound ) ;
+   return f ;
+}
+
+/*------------------------------*/
+
+static pqpair fstat_s2pq( double ff , double dofnum , double dofden )
+{
+   int which , status ;
+   double p , q , f , dfn , dfd , bound ;
+   pqpair pq={0.0,1.0} ;
+
+   which  = 1 ;
+   p      = 0.0 ;
+   q      = 1.0 ;
+   f      = ff ;     if( f   <= 0.0 ) return pq;
+   dfn    = dofnum ; if( dfn <= 0.0 ) return pq ;
+   dfd    = dofden ; if( dfd <= 0.0 ) return pq ;
+
+   cdff( &which , &p , &q , &f , &dfn , &dfd , &status , &bound ) ;
+   pq.p = p ; pq.q = q ; return pq ;
+}
+
+/*---------------------------------------------------------------
+  noncentral F statistic
+-----------------------------------------------------------------*/
+
+static double fnonc_pq2s( pqpair pq , double dofnum , double dofden , double nonc )
+{
+   int which , status ;
+   double p , q , f , dfn , dfd , bound , pnonc ;
+
+   which  = 2 ;
+   p      = pq.p ;   if( p <= 0.0 ) return 0.0 ;
+   q      = pq.q ;   if( q <= 0.0 ) return BIGG ;
+   f      = 0.0 ;
+   dfn    = dofnum ;
+   dfd    = dofden ;
+   pnonc  = nonc ;
+
+   cdffnc( &which , &p , &q , &f , &dfn , &dfd , &pnonc , &status , &bound ) ;
+   return f ;
+}
+
+/*------------------------------*/
+
+static pqpair fnonc_s2pq( double ff , double dofnum , double dofden , double nonc )
+{
+   int which , status ;
+   double p , q , f , dfn , dfd , bound , pnonc ;
+   pqpair pq={0.0,1.0} ;
+
+   which  = 1 ;
+   p      = 0.0 ;
+   q      = 1.0 ;
+   f      = ff ;     if(   f   <= 0.0 ) return pq ;
+   dfn    = dofnum ; if( dfn   <= 0.0 ) return pq ;
+   dfd    = dofden ; if( dfd   <= 0.0 ) return pq ;
+   pnonc  = nonc ;   if( pnonc <  0.0 ) return pq ;
+
+   cdffnc( &which , &p , &q , &f , &dfn , &dfd , &pnonc , &status , &bound ) ;
+   pq.p = p ; pq.q = q ; return pq ;
+}
+
+/*---------------------------------------------------------------
+  Standard Normal distribution
+-----------------------------------------------------------------*/
+
+static pqpair normal_s2pq( double zz )
+{
+   double p , q , x=zz ;
+   pqpair pq ;
+
+   cumnor( &x, &p, &q ) ;
+   pq.p = p ; pq.q = q ; return pq ;
+}
+
+/*------------------------------*/
+
+static double normal_pq2s( pqpair pq )
+{
+   double p=pq.p , q=pq.q ;
+
+   if( p <= 0.0 ) return -BIGG ;
+   if( q <= 0.0 ) return  BIGG ;
+   return dinvnr( &p,&q ) ;
+}
+
+/*----------------------------------------------------------------
+   Chi-square
+------------------------------------------------------------------*/
+
+static pqpair chisq_s2pq( double xx , double dof )
+{
+   int which , status ;
+   double p,q,x,df,bound ;
+   pqpair pq={0.0,1.0} ;
+
+   which  = 1 ;
+   p      = 0.0 ;
+   q      = 1.0 ;
+   x      = xx ;  if(   x <= 0.0 ) return pq ;
+   df     = dof ; if( dof <= 0.0 ) return pq ;
+
+   cdfchi( &which , &p , &q , &x , &df , &status , &bound ) ;
+   pq.p = p ; pq.q = q ; return pq ;
+}
+
+/*------------------------------*/
+
+static double chisq_pq2s( pqpair pq , double dof )
+{
+   int which , status ;
+   double p,q,x,df,bound ;
+
+   which  = 2 ;
+   p      = pq.p ; if( p <= 0.0 ) return  0.0 ;
+   q      = pq.q ; if( q <= 0.0 ) return BIGG ;
+   x      = 0.0 ;
+   df     = dof ;
+
+   cdfchi( &which , &p , &q , &x , &df , &status , &bound ) ;
+   return x ;
+}
+
+/*----------------------------------------------------------------
+   noncentral Chi-square
+------------------------------------------------------------------*/
+
+static pqpair chsqnonc_s2pq( double xx , double dof , double nonc )
+{
+   int which , status ;
+   double p,q,x,df,bound , pnonc ;
+   pqpair pq={0.0,1.0} ;
+
+   which  = 1 ;
+   p      = 0.0 ;
+   q      = 1.0 ;
+   x      = xx ;   if( x     <= 0.0 ) return pq ;
+   df     = dof ;  if( df    <= 0.0 ) return pq ;
+   pnonc  = nonc ; if( pnonc <  0.0 ) return pq ;
+
+   cdfchn( &which , &p , &q , &x , &df , &pnonc , &status , &bound ) ;
+   pq.p = p ; pq.q = q ; return pq ;
+}
+
+/*------------------------------*/
+
+static double chsqnonc_pq2s( pqpair pq , double dof , double nonc )
+{
+   int which , status ;
+   double p,q,x,df,bound , pnonc ;
+
+   which  = 2 ;
+   p      = pq.p ; if( p <= 0.0 ) return  0.0 ;
+   q      = pq.q ; if( q <= 0.0 ) return BIGG ;
+   x      = 0.0 ;
+   df     = dof ;
+   pnonc  = nonc ;
+
+   cdfchn( &which , &p , &q , &x , &df , &pnonc , &status , &bound ) ;
+   return x ;
+}
+
+/*----------------------------------------------------------------
+   Beta distribution
+------------------------------------------------------------------*/
+
+static pqpair beta_s2pq( double xx , double aa , double bb )
+{
+   int which , status ;
+   double p,q,x,y,a,b,bound ;
+   pqpair pq={0.0,1.0} ;
+
+   which  = 1 ;
+   p      = 0.0 ;
+   q      = 1.0 ;
+   x      = xx ;       if( x <= 0.0 ) return pq ;
+   y      = 1.0 - xx ; if( y <= 0.0 ){ pq.p=1.0; pq.q=0.0; return pq; }
+   a      = aa ;       if( a <  0.0 ) return pq ;
+   b      = bb ;       if( b <  0.0 ) return pq ;
+
+   cdfbet( &which , &p , &q , &x , &y , &a , &b ,  &status , &bound ) ;
+   pq.p = p ; pq.q = q ; return pq ;
+}
+
+/*------------------------------*/
+
+static double beta_pq2s( pqpair pq , double aa , double bb )
+{
+   int which , status ;
+   double p,q,x,y,a,b,bound ;
+
+   which  = 2 ;
+   p      = pq.p ; if( p <= 0.0 ) return 0.0 ;
+   q      = pq.q ; if( q <= 0.0 ) return 1.0 ;
+   x      = 0.0 ;
+   y      = 1.0 ;
+   a      = aa ;
+   b      = bb ;
+
+   cdfbet( &which , &p , &q , &x , &y , &a , &b ,  &status , &bound ) ;
+   return x ;
+}
+
+/*----------------------------------------------------------------
+   Binomial distribution
+   (that is, the probability that more than ss out of ntrial
+    trials were successful).
+------------------------------------------------------------------*/
+
+static pqpair binomial_s2pq( double ss , double ntrial , double ptrial )
+{
+   int which , status ;
+   double p,q, s,xn,pr,ompr,bound ;
+   pqpair pq={0.0,1.0} ;
+
+   which  = 1 ;
+   p      = 0.0 ;
+   q      = 1.0 ;
+   s      = ss ;            if( s  <  0.0 ) return pq ;
+   xn     = ntrial ;        if( xn <= 0.0 ) return pq ;
+   pr     = ptrial ;        if( pr <  0.0 ) return pq ;
+   ompr   = 1.0 - ptrial ;
+
+   cdfbin( &which , &p , &q , &s , &xn , &pr , &ompr , &status , &bound ) ;
+   pq.p = p ; pq.q = q ; return pq ;
+}
+
+/*------------------------------*/
+
+static double binomial_pq2s( pqpair pq , double ntrial , double ptrial )
+{
+   int which , status ;
+   double p,q, s,xn,pr,ompr,bound ;
+
+   which  = 2 ;
+   p      = pq.p ;
+   q      = pq.q ;
+   s      = 0.0 ;
+   xn     = ntrial ;
+   pr     = ptrial ;
+   ompr   = 1.0 - ptrial ;
+
+   cdfbin( &which , &p , &q , &s , &xn , &pr , &ompr , &status , &bound ) ;
+   return s ;
+}
+
+/*----------------------------------------------------------------
+   Gamma distribution.
+------------------------------------------------------------------*/
+
+static pqpair gamma_s2pq( double xx , double sh , double sc )
+{
+   int which , status ;
+   double p,q, x,shape,scale,bound ;
+   pqpair pq={0.0,1.0} ;
+
+   which  = 1 ;
+   p      = 0.0 ;
+   q      = 1.0 ;
+   x      = xx ;  if(     x <= 0.0 ) return pq ;
+   shape  = sh ;  if( shape <= 0.0 ) return pq ;
+   scale  = sc ;  if( scale <= 0.0 ) return pq ;
+
+   cdfgam( &which , &p , &q , &x , &shape , &scale , &status , &bound ) ;
+   pq.p = p ; pq.q = q ; return pq ;
+}
+
+/*------------------------------*/
+
+static double gamma_pq2s( pqpair pq , double sh , double sc )
+{
+   int which , status ;
+   double p,q, x,shape,scale,bound ;
+
+   which  = 2 ;
+   p      = pq.p ; if( p <= 0.0 ) return  0.0 ;
+   q      = pq.q ; if( q <= 0.0 ) return BIGG ;
+   x      = 0.0 ;
+   shape  = sh ;
+   scale  = sc ;
+
+   cdfgam( &which , &p , &q , &x , &shape , &scale , &status , &bound ) ;
+   return x ;
+}
+
+/*----------------------------------------------------------------
+   Poisson distribution
+------------------------------------------------------------------*/
+
+static pqpair poisson_s2pq( double xx , double lambda )
+{
+   int which , status ;
+   double p,q, s,xlam,bound ;
+   pqpair pq={0.0,1.0} ;
+
+   which  = 1 ;
+   p      = 0.0 ;
+   q      = 1.0 ;
+   s      = xx ;     if(    s < 0.0 ) return pq ;
+   xlam   = lambda ; if( xlam < 0.0 ) return pq ;
+
+   cdfpoi( &which , &p , &q , &s , &xlam , &status , &bound ) ;
+   pq.p = p ; pq.q = q ; return pq ;
+}
+
+/*------------------------------*/
+
+static double poisson_pq2s( pqpair pq , double lambda )
+{
+   int which , status ;
+   double p,q, s,xlam,bound ;
+
+   which  = 2 ;
+   p      = pq.p ;
+   q      = pq.q ;
+   s      = 0.0 ;
+   xlam   = lambda ;
+
+   cdfpoi( &which , &p , &q , &s , &xlam , &status , &bound ) ;
+   return s ;
+}
+
+/*----------------------------------------------------------------
+   T distribution.
+------------------------------------------------------------------*/
+
+static pqpair student_s2pq( double xx , double dof )
+{
+   int which , status ;
+   double p,q, s,xlam,bound ;
+   pqpair pq={0.0,1.0} ;
+
+   which  = 1 ;
+   p      = 0.0 ;
+   q      = 1.0 ;
+   s      = xx ;
+   xlam   = dof ;  if( xlam <= 0.0 ) return pq ;
+
+   cdft( &which , &p , &q , &s , &xlam , &status , &bound ) ;
+   pq.p = p ; pq.q = q ; return pq ;
+}
+
+/*------------------------------*/
+
+double student_pq2s( pqpair pq , double dof )
+{
+   int which , status ;
+   double p,q, s,xlam,bound ;
+
+   which  = 2 ;
+   p      = pq.p ;
+   q      = pq.q ;
+   s      = 0.0 ;
+   xlam   = dof ;
+
+   cdft( &which , &p , &q , &s , &xlam , &status , &bound ) ;
+   return s ;
+}
+
+/****************************************************************************/
+/* For the distributions below here, cdflib can't do what we want directly. */
+/****************************************************************************/
+
+/*----------------------------------------------------------------
+   Null correlation distribution.
+   Let x = (rr+1)/2; then x is Beta(dof/2,dof/2).
+------------------------------------------------------------------*/
+
+static pqpair correl_s2pq( double rr , double dof )  /* fake it with cdflib */
+{
+   return beta_s2pq( 0.5*(rr+1.0) , 0.5*dof , 0.5*dof ) ;
+}
+
+/*------------------------------*/
+
+static double correl_pq2s( pqpair pq , double dof )
+{
+   double xx = beta_pq2s( pq , 0.5*dof , 0.5*dof ) ;
+   return (2.0*xx-1.0) ;
+}
+
+/*----------------------------------------------------------------
+  Uniform U(0,1) distribution.
+------------------------------------------------------------------*/
+
+static pqpair uniform_s2pq( double xx )  /* this isn't too hard */
+{
+   pqpair pq ;
+        if( xx <= 0.0 ) pq.p = 0.0 ;
+   else if( xx >= 1.0 ) pq.p = 1.0 ;
+   else                 pq.p = xx  ;
+   pq.q = 1.0-xx ; return pq ;
+}
+
+/*------------------------------*/
+
+static double uniform_pq2s( pqpair pq )
+{
+   return pq.p ;   /* that was easy */
+}
+
+/*----------------------------------------------------------------
+  standard Logistic distribution.
+------------------------------------------------------------------*/
+
+static pqpair logistic_s2pq( double xx )  /* this isn't hard, either */
+{
+   pqpair pq ;
+   if( xx >= 0.0 ){ pq.q = 1.0/(1.0+exp( xx)); pq.p = 1.0-pq.q; }
+   else           { pq.p = 1.0/(1.0+exp(-xx)); pq.q = 1.0-pq.p; }
+   return pq ;
+}
+
+/*------------------------------*/
+
+static double logistic_pq2s( pqpair pq )
+{
+        if( pq.p <= 0.0 ) return -BIGG ;
+   else if( pq.q <= 0.0 ) return  BIGG ;
+
+   if( pq.p < pq.q ) return -log(1.0/pq.p-1.0) ;
+   else              return  log(1.0/pq.q-1.0) ;
+}
+
+/*----------------------------------------------------------------
+  standard Laplace distribution.
+------------------------------------------------------------------*/
+
+static pqpair laplace_s2pq( double xx )  /* easy */
+{
+   pqpair pq ;
+
+   if( xx >= 0.0 ){ pq.q = 0.5*exp(-xx) ; pq.p = 1.0-pq.q ; }
+   else           { pq.p = 0.5*exp( xx) ; pq.q = 1.0-pq.p ; }
+   return pq ;
+}
+
+/*------------------------------*/
+
+static double laplace_pq2s( pqpair pq )
+{
+        if( pq.p <= 0.0 ) return -BIGG ;
+   else if( pq.q <= 0.0 ) return  BIGG ;
+
+   if( pq.p < pq.q ) return  log(2.0*pq.p) ;
+   else              return -log(2.0*pq.q) ;
+}
+
+/*----------------------------------------------------------------
+   noncentral T distribution = hard calculation
+------------------------------------------------------------------*/
+
+/****************************************************************************
+  Noncentral t distribution function by
+    Professor K. Krishnamoorthy
+    Department of Mathematics
+    University of Louisiana at Lafayette
+  Manually translated from Fortran by RWC.
+*****************************************************************************/
+
+#if 0
+static double alng( double x )   /* log(Gamma(x)) from K */
+{
+   int indx ;
+   double xx,fterm,sum,valg ;
+   double b[9] = { 0.0 ,
+                   8.33333333333333e-2, 3.33333333333333e-2,
+                   2.52380952380952e-1, 5.25606469002695e-1,
+                   1.01152306812684e0,  1.51747364915329e0,
+                   2.26948897420496e0,  3.00991738325940e0   } ;
+
+   if( x < 8.0 ){ xx = x + 8.0 ; indx = 1 ; }
+   else         { xx = x       ; indx = 0 ; }
+
+   fterm = (xx-0.5)*log(xx) - xx + 9.1893853320467e-1 ;
+   sum = b[1]/(xx+b[2]/(xx+b[3]/(xx+b[4]/(xx+b[5]/(xx+b[6]/
+                                         (xx+b[7]/(xx+b[8]))))))) ;
+   valg = sum + fterm ;
+   if(indx)
+     valg = valg-log(x+7.0)-log(x+6.0)-log(x+5.0)
+                -log(x+4.0)-log(x+3.0)-log(x+2.0)-log(x+1.0)-log(x) ;
+   return valg ;
+}
+#else
+static double alng( double x ) /*-- replace with cdflib function --*/
+{
+  double xx=x ; return alngam( &xx ) ;
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+
+#if 0
+static double gaudf( double x )  /* N(0,1) cdf from K */
+{
+   static double p0=913.16744211475570 , p1=1024.60809538333800,
+                 p2=580.109897562908800, p3=202.102090717023000,
+                 p4=46.0649519338751400, p5=6.81311678753268400,
+                 p6=6.047379926867041e-1,p7=2.493381293151434e-2 ;
+   static double q0=1826.33488422951125, q1=3506.420597749092,
+                 q2=3044.77121163622200, q3=1566.104625828454,
+                 q4=523.596091947383490, q5=116.9795245776655,
+                 q6=17.1406995062577800, q7=1.515843318555982,
+                 q8=6.25e-2 ;
+   static double sqr2pi=2.506628274631001 ;
+   int check ;
+   double reslt,z , first,phi ;
+
+   if(x > 0.0){ z = x ; check = 1 ; }
+   else       { z =-x ; check = 0 ; }
+
+   if( z > 32.0 ) return (x > 0.0) ? 1.0 : 0.0 ;
+
+   first = exp(-0.5*z*z) ;
+   phi   = first/sqr2pi ;
+
+   if (z < 7.0)
+      reslt = first* (((((((p7*z+p6)*z+p5)*z+p4)*z+p3)*z+p2)*z+p1)*z+p0)
+                   /((((((((q8*z+q7)*z+q6)*z+q5)*z+q4)*z+q3)*z+q2)*z+q1)*z+q0);
+   else
+      reslt = phi/(z+1.0/(z+2.0/(z+3.0/(z+4.0/(z+6.0/(z+7.0)))))) ;
+
+   if(check) reslt = 1.0 - reslt ;
+   return reslt ;
+}
+#else
+static double gaudf( double x ) /*-- replace with cdflib func --*/
+{
+   double xx=x , p,q ;
+   cumnor( &xx, &p, &q ); return p;
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+
+#if 0
+static double betadf( double x , double p , double q ) /* Beta cdf from K */
+{
+   int check , ns ;
+   double result,betf,psq,xx,cx,pp,qq ;
+   double term,ai,rx,temp ;
+
+   if( x >= 1.0 ) return 1.0 ;
+   if( x <= 0.0 ) return 0.0 ;
+
+   betf = alng(p)+alng(q)-alng(p+q) ;
+   result=x ;
+   psq=p+q ;
+   cx=1.0-x ;
+   if(p < psq*x){ xx=cx ; cx=x ; pp=q ; qq=p ; check=1 ; }
+   else         { xx=x  ;        pp=p ; qq=q ; check=0 ; }
+
+   term=1.0 ;
+   ai=1.0 ;
+   result=1.0 ;
+   ns=(int)(qq+cx*psq) ;
+   rx=xx/cx ;
+L3:
+   temp=qq-ai ;
+   if(ns == 0) rx=xx ;
+L4:
+   term=term*temp*rx/(pp+ai) ;
+   result=result+term ;
+   temp=fabs(term) ;
+   if(temp <= 1.e-14 && temp <= 1.e-14*result) goto L5 ;
+   ai=ai+1.0 ;
+   ns=ns-1 ;
+   if(ns >= 0) goto L3 ;
+   temp=psq ;
+   psq=psq+1.0 ;
+   goto L4 ;
+
+L5:
+   result=result*exp(pp*log(xx)+(qq-1.0)*log(cx)-betf)/pp ;
+   if(check) result=1.0-result ;
+   return result ;
+}
+#else
+static double betadf( double x , double p , double q ) /*-- cdflib func --*/
+{
+   double xx=x,yy=1.0-x , aa=p,bb=q , pp,qq ;
+   cumbet( &xx,&yy , &aa,&bb , &pp,&qq ) ; return pp ;
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Krishnamoorthy's function for cdf of noncentral t, for df > 0,
+   translated into C by RW Cox [Mar 2004].
+   Note the original fails for delta=0, so we call the cdflib func for this.
+   A couple of other minor fixes are also included.
+-----------------------------------------------------------------------------*/
+
+static pqpair tnonc_s2pq( double t , double df , double delta )
+{
+   int indx , k , i ;
+   double x,del,tnd,ans,y,dels,a,b,c ;
+   double pkf,pkb,qkf,qkb , pgamf,pgamb,qgamf,qgamb ;
+   double pbetaf,pbetab,qbetaf,qbetab ;
+   double ptermf,qtermf,ptermb,qtermb,term ;
+   double rempois,delosq2,sum,cons,error ;
+
+   pqpair pq={0.0,1.0} ;  /* will be return value */
+   double ab1 ;
+
+   /*-- stupid user? --*/
+
+   if( df <= 0.0 ) return pq ;
+
+   /*-- non-centrality = 0? --*/
+
+   if( fabs(delta) < 1.e-8 ) return student_s2pq(t,df) ;
+
+   /*-- start K's code here --*/
+
+   if( t < 0.0 ){ x = -t ; del = -delta ; indx = 1 ; }  /* x will be */
+   else         { x =  t ; del =  delta ; indx = 0 ; }  /* positive */
+
+   ans = gaudf(-del) ;  /* prob that x <= 0 = Normal cdf */
+
+   /*-- the nearly trivial case of x=0 --*/
+
+   if( x == 0.0 ){ pq.p = ans; pq.q = 1.0-ans; return pq; }
+
+   if( df == 1.0 ) df = 1.0000001 ;  /** df=1 is BAD **/
+
+   y = x*x/(df+x*x) ;    /* between 0 and 1 */
+   dels = 0.5*del*del ;  /* will be positive */
+   k = (int)dels ;       /* 0, 1, 2, ... */
+   a = k+0.5 ;           /* might be as small as 0.5 */
+   c = k+1.0 ;
+   b = 0.5*df ;          /* might be as small as 0.0 */
+
+   pkf = exp(-dels+k*log(dels)-alng(k+1.0)) ;
+   pkb = pkf ;
+   qkf = exp(-dels+k*log(dels)-alng(k+1.0+0.5)) ;
+   qkb = qkf ;
+
+   pbetaf = betadf(y, a, b) ;
+   pbetab = pbetaf ;
+   qbetaf = betadf(y, c, b) ;
+   qbetab = qbetaf ;
+
+   ab1 = a+b-1.0 ;  /* might be as small as -0.5 */
+
+   /*-- RWCox: if a+b-1 < 0, log(Gamma(a+b-1)) won't work;
+               instead, use Gamma(a+b-1)=Gamma(a+b)/(a+b-1) --*/
+
+   if( ab1 > 0.0 )
+     pgamf = exp(alng(ab1)-alng(a)-alng(b)+(a-1.0)*log(y)+b*log(1.0-y)) ;
+   else
+     pgamf = exp(alng(a+b)-alng(a)-alng(b)+(a-1.0)*log(y)+b*log(1.0-y))/ab1 ;
+
+   pgamb = pgamf*y*(ab1)/a ;
+
+   /*-- we can't have c+b-1 < 0, so the above patchup isn't needed --*/
+
+   qgamf = exp(alng(c+b-1.0)-alng(c)-alng(b)+(c-1.0)*log(y) + b*log(1.0-y)) ;
+   qgamb = qgamf*y*(c+b-1.0)/c ;
+
+   rempois = 1.0 - pkf ;
+   delosq2 = del/1.4142135623731 ;
+   sum = pkf*pbetaf+delosq2*qkf*qbetaf ;
+   cons = 0.5*(1.0 + 0.5*fabs(delta)) ;
+   i = 0 ;
+L1:
+   i = i + 1 ;
+   pgamf = pgamf*y*(a+b+i-2.0)/(a+i-1.0) ;
+   pbetaf = pbetaf - pgamf ;
+   pkf = pkf*dels/(k+i) ;
+   ptermf = pkf*pbetaf ;
+   qgamf = qgamf*y*(c+b+i-2.0)/(c+i-1.0) ;
+   qbetaf = qbetaf - qgamf ;
+   qkf = qkf*dels/(k+i-1.0+1.5) ;
+   qtermf = qkf*qbetaf ;
+   term = ptermf + delosq2*qtermf  ;
+   sum = sum + term ;
+   error = rempois*cons*pbetaf ;
+   rempois = rempois - pkf ;
+
+   if( i > k ){
+     if( error <= 1.e-12 || i >= 9999 ) goto L2 ;
+     goto L1 ;
+   } else {
+     pgamb = pgamb*(a-i+1.0)/(y*(a+b-i)) ;
+     pbetab = pbetab + pgamb ;
+     pkb = (k-i+1.0)*pkb/dels ;
+     ptermb = pkb*pbetab  ;
+     qgamb = qgamb*(c-i+1.0)/(y*(c+b-i)) ;
+     qbetab = qbetab + qgamb ;
+     qkb = (k-i+1.0+0.5)*qkb/dels ;
+     qtermb = qkb*qbetab  ;
+     term =  ptermb + delosq2*qtermb ;
+     sum = sum + term  ;
+     rempois = rempois - pkb ;
+     if (rempois <= 1.e-12 || i >= 9999) goto L2 ;
+     goto L1 ;
+   }
+L2:
+   tnd = 0.5*sum + ans ;
+
+   /*-- return a pqpair, not just the cdf --*/
+
+   if( indx ){ pq.p = 1.0-tnd; pq.q = tnd    ; }
+   else      { pq.p = tnd    ; pq.q = 1.0-tnd; }
+   return pq ;
+}
+
+/*------------------------------*/
+/* Inverse to above function;
+   uses cdflib dstinv()/dinvr()
+   to solve the equation.
+--------------------------------*/
+
+static double tnonc_pq2s( pqpair pq , double dof , double nonc )
+{
+   double t ;  /* will be result */
+   double tbot,ttop , dt ;
+   double T6=1.e-50,T7=1.e-8 ;
+   double K4=0.5,K5=5.0 ;
+   double fx ;
+   unsigned long qhi,qleft ;
+   int status , qporq , ite ;
+   pqpair tpq ;
+
+   if( dof  <= 0.0 ) return  BIGG ;  /* bad user */
+   if( pq.p <= 0.0 ) return -BIGG ;
+   if( pq.q <= 0.0 ) return  BIGG ;
+
+   t = student_pq2s(pq,dof) ;   /* initial guess */
+
+   if( fabs(nonc) < 1.e-8 ) return t ;
+
+   t += 0.5*nonc ;  /* adjust up or down */
+
+   dt = 0.1 * fabs(t) ; if( dt < 1.0 ) dt = 1.0 ;  /* stepsize */
+
+   /* scan down for lower bound, below which cdf is < p */
+
+   tbot = t ;
+   for( ite=0 ; ite < 1000 ; ite++ ){
+     tpq = tnonc_s2pq( tbot , dof , nonc ) ;
+     if( tpq.p <= pq.p ) break ;
+     tbot -= dt ;
+   }
+   if( ite >= 1000 ) return -BIGG ;
+
+   /* scan up for upper bound, above which cdf is > p */
+
+   ttop = tbot+0.5*dt ;
+   for( ite=0 ; ite < 1000 ; ite++ ){
+     tpq = tnonc_s2pq( ttop , dof , nonc ) ;
+     if( tpq.p >= pq.p ) break ;
+     ttop += dt ;
+   }
+   if( ite >= 1000 ) return BIGG ;
+
+   t = 0.5*(tbot+ttop) ;  /* initial guess in middle */
+
+   /* initialize searching parameters */
+
+   dstinv(&tbot,&ttop,&K4,&K4,&K5,&T6,&T7);
+
+   status = 0 ; qporq = (pq.p <= pq.q) ;
+
+   while(1){
+
+     dinvr(&status,&t,&fx,&qleft,&qhi) ;
+
+     if( status != 1 ) return t ;  /* done! */
+
+     tpq = tnonc_s2pq( t , dof , nonc ) ;  /* get cdf */
+
+     /* goal of dinvr is to drive fx to zero */
+
+     fx = (qporq) ? pq.p-tpq.p : pq.q-tpq.q ;
+   }
+
+   return BIGG ;  /* unreachable */
+}
+
+/*----------------------------------------------------------------
+   Chi distribution (sqrt of chi-squared, duh).
+------------------------------------------------------------------*/
+
+static pqpair chi_s2pq( double xx , double dof )
+{
+   pqpair pq={0.0,1.0} ;
+
+   if( xx <= 0.0 || dof <= 0.0 ) return pq ;
+   return chisq_s2pq( xx*xx , dof ) ;
+}
+
+/*------------------------------*/
+
+static double chi_pq2s( pqpair pq , double dof )
+{
+   if( pq.p <= 0.0 ) return  0.0 ;
+   if( pq.q <= 0.0 ) return BIGG ;
+   return sqrt(chisq_pq2s(pq,dof)) ;
+}
+
+/*----------------------------------------------------------------
+   Extreme value type I: cdf(x) = exp(-exp(-x)).
+------------------------------------------------------------------*/
+
+static pqpair extval1_s2pq( double x )
+{
+   double p,q,y ; pqpair pq ;
+
+   if( x > -5.0 ){ y = exp(-x) ; p = exp(-y) ; }
+   else          { y = 1.0     ; p = 0.0     ; }
+
+   if( y >= 1.e-4 ) q = 1.0-p ;
+   else             q = y*(1.0+y*(-0.5+y*(1.0/6.0-y/24.0))) ;
+   pq.p = p ; pq.q = q ; return pq ;
+}
+
+/*------------------------------*/
+
+static double extval1_pq2s( pqpair pq )
+{
+        if( pq.p <= 0.0 ) return -BIGG ;
+   else if( pq.p >= 1.0 ) return  BIGG ;
+   return -log(-log(pq.p)) ;
+}
+
+/*----------------------------------------------------------------
+   Weibull distribution: cdf(x) = 1 - exp( -x^c ) for x>0 and c>0.
+------------------------------------------------------------------*/
+
+static pqpair weibull_s2pq( double x , double c )
+{
+   double y ;
+   pqpair pq={0.0,1.0} ;
+
+   if( x <= 0.0 || c <= 0.0 ) return pq ;
+
+   y = pow(x,c) ; pq.q = exp(-y) ;
+   if( y >= 1.e-4 ) pq.p = 1.0-pq.q ;
+   else             pq.p = y*(1.0+y*(-0.5+y*(1.0/6.0-y/24.0))) ;
+   return pq ;
+}
+
+/*------------------------------*/
+
+static double weibull_pq2s( pqpair pq , double c )
+{
+        if( pq.p <= 0.0 || c <= 0.0 ) return  0.0 ;
+   else if( pq.q <= 0.0             ) return BIGG ;
+   return pow( -log(pq.q) , 1.0/c ) ;
+}
+
+/*----------------------------------------------------------------
+   Inverse Gaussian:
+    density proportional to exp(-0.5*c(x+1/x))/x^1.5 (x,c >0).
+------------------------------------------------------------------*/
+
+static pqpair invgauss_s2pq( double x, double c )
+{
+   double y , p1,q1 , p2,q2 , v ;
+   pqpair pq={0.0,1.0} ;
+
+   if( x <= 0.0 || c <= 0.0 ) return pq ;
+
+   y = sqrt(c/x) ;
+   v =  y*(x-1.0) ; cumnor( &v , &p1,&q1 ) ;
+   v = -y*(x+1.0) ; cumnor( &v , &p2,&q2 ) ;
+   pq.p = p1 ;
+   if( p2 > 0.0 ) pq.p += exp(2.0*c+log(p2)) ;
+   pq.q = 1.0-pq.p ; return pq ;
+}
+
+/*------------------------------*/
+/* Inverse to above function;
+   uses cdflib dstinv()/dinvr()
+   to solve the equation.
+--------------------------------*/
+
+static double invgauss_pq2s( pqpair pq , double c )
+{
+   double t ;  /* will be result */
+   double tbot,ttop , dt ;
+   double T6=1.e-50,T7=1.e-8 ;
+   double K4=0.5,K5=5.0 ;
+   double fx ;
+   unsigned long qhi,qleft ;
+   int status , qporq , ite ;
+   pqpair tpq ;
+
+   if( c    <= 0.0 ) return  BIGG ;  /* bad user */
+   if( pq.p <= 0.0 ) return   0.0 ;
+   if( pq.q <= 0.0 ) return  BIGG ;
+
+   /* initial guess is t=1; scan down for lower bound */
+
+   tbot = 1.01 ; dt = 0.9 ;
+   for( ite=0 ; ite < 1000 ; ite++ ){
+     tpq = invgauss_s2pq( tbot , c ) ;
+     if( tpq.p <= pq.p ) break ;
+     tbot *= dt ;
+   }
+   if( ite >= 1000 ) return 0.0 ;
+
+   /* scan up for upper bound */
+
+   dt = 1.1 ; ttop = tbot*dt ;
+   for( ite=0 ; ite < 1000 ; ite++ ){
+     tpq = invgauss_s2pq( ttop , c ) ;
+     if( tpq.p >= pq.p ) break ;
+     ttop *= dt ;
+   }
+   if( ite >= 1000 ) return BIGG ;
+
+   t = sqrt(tbot*ttop) ; /* start at geometric mean */
+
+   /* initialize searching parameters */
+
+   dstinv(&tbot,&ttop,&K4,&K4,&K5,&T6,&T7);
+
+   status = 0 ; qporq = (pq.p <= pq.q) ;
+
+   while(1){
+
+     dinvr(&status,&t,&fx,&qleft,&qhi) ;
+
+     if( status != 1 ) return t ;  /* done! */
+
+     tpq = invgauss_s2pq( t , c ) ;
+
+     /* goal is to drive fx to zero */
+
+     fx = (qporq) ? pq.p-tpq.p : pq.q-tpq.q ;
+   }
+
+   return BIGG ;  /* unreachable */
+}
+
+/*--------------------------------------------------------------------------*/
+/*! Given a value, calculate both its cdf and reversed cdf (1.0-cdf).
+    If an error occurs, you'll probably get back {0.0,1.0}.
+    All the actual work is done in utility functions for each distribution.
+----------------------------------------------------------------------------*/
+
+static pqpair stat2pq( double val, int code, double p1,double p2,double p3 )
+{
+   pqpair pq={0.0,1.0} ;
+
+   switch( code ){
+
+     case NIFTI_INTENT_CORREL:     pq = correl_s2pq  ( val, p1 )      ; break;
+     case NIFTI_INTENT_TTEST:      pq = student_s2pq ( val, p1 )      ; break;
+     case NIFTI_INTENT_FTEST:      pq = fstat_s2pq   ( val, p1,p2 )   ; break;
+     case NIFTI_INTENT_ZSCORE:     pq = normal_s2pq  ( val )          ; break;
+     case NIFTI_INTENT_CHISQ:      pq = chisq_s2pq   ( val, p1 )      ; break;
+     case NIFTI_INTENT_BETA:       pq = beta_s2pq    ( val, p1,p2 )   ; break;
+     case NIFTI_INTENT_BINOM:      pq = binomial_s2pq( val, p1,p2 )   ; break;
+     case NIFTI_INTENT_GAMMA:      pq = gamma_s2pq   ( val, p1,p2 )   ; break;
+     case NIFTI_INTENT_POISSON:    pq = poisson_s2pq ( val, p1 )      ; break;
+     case NIFTI_INTENT_FTEST_NONC: pq = fnonc_s2pq   ( val, p1,p2,p3 ); break;
+     case NIFTI_INTENT_CHISQ_NONC: pq = chsqnonc_s2pq( val, p1,p2    ); break;
+     case NIFTI_INTENT_TTEST_NONC: pq = tnonc_s2pq   ( val, p1,p2 )   ; break;
+     case NIFTI_INTENT_CHI:        pq = chi_s2pq     ( val, p1 )      ; break;
+
+     /* these distributions are shifted and scaled copies of a standard case */
+
+     case NIFTI_INTENT_INVGAUSS:
+        if( p1 > 0.0 && p2 > 0.0 ) pq = invgauss_s2pq( val/p1,p2/p1 ) ; break;
+
+     case NIFTI_INTENT_WEIBULL:
+        if( p2 > 0.0 && p3 > 0.0 ) pq = weibull_s2pq ((val-p1)/p2,p3) ; break;
+
+     case NIFTI_INTENT_EXTVAL:
+                    if( p2 > 0.0 ) pq = extval1_s2pq ( (val-p1)/p2 )  ; break;
+
+     case NIFTI_INTENT_NORMAL:
+                    if( p2 > 0.0 ) pq = normal_s2pq  ( (val-p1)/p2 )  ; break;
+
+     case NIFTI_INTENT_LOGISTIC:
+                    if( p2 > 0.0 ) pq = logistic_s2pq( (val-p1)/p2 )  ; break;
+
+     case NIFTI_INTENT_LAPLACE:
+                    if( p2 > 0.0 ) pq = laplace_s2pq ( (val-p1)/p2 )  ; break;
+
+     case NIFTI_INTENT_UNIFORM:
+                    if( p2 > p1  ) pq = uniform_s2pq((val-p1)/(p2-p1)); break;
+
+     /* this case is trivial */
+
+     case NIFTI_INTENT_PVAL:       pq.p = 1.0-val ; pq.q = val        ; break;
+   }
+
+   return pq ;
+}
+
+/*--------------------------------------------------------------------------*/
+/*! Given a pq value (cdf and 1-cdf), compute the value that gives this.
+    If an error occurs, you'll probably get back a BIGG number.
+    All the actual work is done in utility functions for each distribution.
+----------------------------------------------------------------------------*/
+
+static double pq2stat( pqpair pq, int code, double p1,double p2,double p3 )
+{
+   double val=BIGG ;
+
+   if( pq.p < 0.0 || pq.q < 0.0 || pq.p > 1.0 || pq.q > 1.0 ) return val ;
+
+   switch( code ){
+
+     case NIFTI_INTENT_CORREL:     val = correl_pq2s  ( pq , p1 )      ; break;
+     case NIFTI_INTENT_TTEST:      val = student_pq2s ( pq , p1 )      ; break;
+     case NIFTI_INTENT_FTEST:      val = fstat_pq2s   ( pq , p1,p2 )   ; break;
+     case NIFTI_INTENT_ZSCORE:     val = normal_pq2s  ( pq )           ; break;
+     case NIFTI_INTENT_CHISQ:      val = chisq_pq2s   ( pq , p1 )      ; break;
+     case NIFTI_INTENT_BETA:       val = beta_pq2s    ( pq , p1,p2 )   ; break;
+     case NIFTI_INTENT_BINOM:      val = binomial_pq2s( pq , p1,p2 )   ; break;
+     case NIFTI_INTENT_GAMMA:      val = gamma_pq2s   ( pq , p1,p2 )   ; break;
+     case NIFTI_INTENT_POISSON:    val = poisson_pq2s ( pq , p1 )      ; break;
+     case NIFTI_INTENT_FTEST_NONC: val = fnonc_pq2s   ( pq , p1,p2,p3 ); break;
+     case NIFTI_INTENT_CHISQ_NONC: val = chsqnonc_pq2s( pq , p1,p2    ); break;
+     case NIFTI_INTENT_TTEST_NONC: val = tnonc_pq2s   ( pq , p1,p2 )   ; break;
+     case NIFTI_INTENT_CHI:        val = chi_pq2s     ( pq , p1 )      ; break;
+
+     /* these distributions are shifted and scaled copies of a standard case */
+
+     case NIFTI_INTENT_INVGAUSS:
+        if( p1 > 0.0 && p2 > 0.0 ) val = p1*invgauss_pq2s   ( pq,p2/p1); break;
+
+     case NIFTI_INTENT_WEIBULL:
+        if( p2 > 0.0 && p3 > 0.0 ) val = p1+p2*weibull_pq2s ( pq, p3 ) ; break;
+
+     case NIFTI_INTENT_EXTVAL:
+                    if( p2 > 0.0 ) val = p1+p2*extval1_pq2s ( pq )     ; break;
+
+     case NIFTI_INTENT_NORMAL:
+                    if( p2 > 0.0 ) val = p1+p2*normal_pq2s  ( pq )     ; break;
+
+     case NIFTI_INTENT_LOGISTIC:
+                    if( p2 > 0.0 ) val = p1+p2*logistic_pq2s( pq )     ; break;
+
+     case NIFTI_INTENT_LAPLACE:
+                    if( p2 > 0.0 ) val = p1+p2*laplace_pq2s ( pq )     ; break;
+
+     case NIFTI_INTENT_UNIFORM:
+                    if( p2 > p1  ) val = p1+(p2-p1)*uniform_pq2s(pq)   ; break;
+
+     /* this case is trivial */
+
+     case NIFTI_INTENT_PVAL:       val = pq.q                          ; break;
+   }
+
+   return val ;
+}
+
+/****************************************************************************/
+/*[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]*/
+/*..........................................................................*/
+/*............. AT LAST!  Functions to be called by the user! ..............*/
+/*..........................................................................*/
+/*[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]*/
+/****************************************************************************/
+
+/****************************************************************************
+ Statistical codes implemented here:
+
+     NIFTI_INTENT_CORREL     = correlation statistic
+     NIFTI_INTENT_TTEST      = t statistic (central)
+     NIFTI_INTENT_FTEST      = F statistic (central)
+     NIFTI_INTENT_ZSCORE     = N(0,1) statistic
+     NIFTI_INTENT_CHISQ      = Chi-squared (central)
+     NIFTI_INTENT_BETA       = Beta variable (central)
+     NIFTI_INTENT_BINOM      = Binomial variable
+     NIFTI_INTENT_GAMMA      = Gamma distribution
+     NIFTI_INTENT_POISSON    = Poisson distribution
+     NIFTI_INTENT_FTEST_NONC = noncentral F statistic
+     NIFTI_INTENT_CHISQ_NONC = noncentral chi-squared
+     NIFTI_INTENT_TTEST_NONC = noncentral t statistic
+     NIFTI_INTENT_CHI        = Chi statistic (central)
+     NIFTI_INTENT_INVGAUSS   = inverse Gaussian variable
+     NIFTI_INTENT_WEIBULL    = Weibull distribution
+     NIFTI_INTENT_EXTVAL     = Extreme value type I
+     NIFTI_INTENT_NORMAL     = N(mu,variance) normal
+     NIFTI_INTENT_LOGISTIC   = Logistic distribution
+     NIFTI_INTENT_LAPLACE    = Laplace distribution
+     NIFTI_INTENT_UNIFORM    = Uniform distribution
+     NIFTI_INTENT_PVAL       = "p-value"
+*****************************************************************************/
+
+static char *inam[]={ NULL , NULL ,
+                       "CORREL"   , "TTEST"   , "FTEST"      , "ZSCORE"     ,
+                       "CHISQ"    , "BETA"    , "BINOM"      , "GAMMA"      ,
+                       "POISSON"  , "NORMAL"  , "FTEST_NONC" , "CHISQ_NONC" ,
+                       "LOGISTIC" , "LAPLACE" , "UNIFORM"    , "TTEST_NONC" ,
+                       "WEIBULL"  , "CHI"     , "INVGAUSS"   , "EXTVAL"     ,
+                       "PVAL"     ,
+                     NULL } ;
+
+#include <ctype.h>
+#include <string.h>
+
+/*--------------------------------------------------------------------------*/
+/*! Given a string name for a statistic, return its integer code.
+    Returns -1 if not found.
+----------------------------------------------------------------------------*/
+
+int nifti_intent_code( char *name )
+{
+   char *unam , *upt ;
+   int ii ;
+
+   if( name == NULL || *name == '\0' ) return -1 ;
+
+   unam = strdup(name) ;
+   for( upt=unam ; *upt != '\0' ; upt++ ) *upt = (char)toupper(*upt) ;
+
+   for( ii=NIFTI_FIRST_STATCODE ; ii <= NIFTI_LAST_STATCODE ; ii++ )
+     if( strcmp(inam[ii],unam) == 0 ) break ;
+
+   free(unam) ;
+   return (ii <= NIFTI_LAST_STATCODE) ? ii : -1 ;
+}
+
+/*--------------------------------------------------------------------------*/
+/*! Given a value, return its cumulative distribution function (cdf):
+      - val      = statistic
+      - code     = NIFTI_INTENT_* statistical code
+      - p1,p2,p3 = parameters of the distribution
+
+    If an error occurs, you'll probably get back 0.0.
+----------------------------------------------------------------------------*/
+
+double nifti_stat2cdf( double val, int code, double p1,double p2,double p3 )
+{
+   pqpair pq ;
+   pq = stat2pq( val, code, p1,p2,p3 ) ;
+   return pq.p ;
+}
+
+/*--------------------------------------------------------------------------*/
+/*! Given a value, return its reversed cumulative distribution function
+   (1-cdf):
+      - val      = statistic
+      - code     = NIFTI_INTENT_* statistical code
+      - p1,p2,p3 = parameters of the distribution
+
+  If an error transpires, you'll probably get back 1.0.
+----------------------------------------------------------------------------*/
+
+double nifti_stat2rcdf( double val, int code, double p1,double p2,double p3 )
+{
+   pqpair pq ;
+   pq = stat2pq( val, code, p1,p2,p3 ) ;
+   return pq.q ;
+}
+
+/*--------------------------------------------------------------------------*/
+/*! Given a cdf probability, find the value that gave rise to it.
+     - p        = cdf; 0 < p < 1
+     - code     = NIFTI_INTENT_* statistical code
+     - p1,p2,p3 = parameters of the distribution
+
+  If an error transpires, you'll probably get back a BIGG number.
+----------------------------------------------------------------------------*/
+
+double nifti_cdf2stat( double p , int code, double p1,double p2,double p3 )
+{
+   pqpair pq ;
+   pq.p = p ; pq.q = 1.0-p ;
+   return pq2stat(pq,code,p1,p2,p3) ;
+}
+
+/*--------------------------------------------------------------------------*/
+/*! Given a reversed cdf probability, find the value that gave rise to it.
+     - q        = 1-cdf; 0 < q < 1
+     - code     = NIFTI_INTENT_* statistical code
+     - p1,p2,p3 = parameters of the distribution
+
+  If an error transpires, you'll probably get back a BIGG number.
+----------------------------------------------------------------------------*/
+
+double nifti_rcdf2stat( double q , int code, double p1,double p2,double p3 )
+{
+   pqpair pq ;
+   pq.p = 1.0-q ; pq.q = q ;
+   return pq2stat(pq,code,p1,p2,p3) ;
+}
+
+/*--------------------------------------------------------------------------*/
+/*! Given a statistic, compute a z-score from it.  That is, the output
+    is z such that cdf(z) of a N(0,1) variable is the same as the cdf
+    of the given distribution at val.
+----------------------------------------------------------------------------*/
+
+double nifti_stat2zscore( double val , int code, double p1,double p2,double p3 )
+{
+   pqpair pq ;
+
+   if( code == NIFTI_INTENT_ZSCORE ) return val ;           /* trivial */
+   if( code == NIFTI_INTENT_NORMAL ) return (val-p1)/p2 ;   /* almost so */
+
+   pq = stat2pq( val, code, p1,p2,p3 ) ;                    /* find cdf */
+   return normal_pq2s( pq ) ;                               /* find z  */
+}
+
+/*--------------------------------------------------------------------------*/
+/*! Given a statistic, compute a half-z-score from it.  That is, the output
+    is z such that cdf(z) of a half-N(0,1) variable is the same as the cdf
+    of the given distribution at val.  A half-N(0,1) variable has density
+    zero for z < 0 and twice the usual N(0,1) density for z > 0.
+----------------------------------------------------------------------------*/
+
+double nifti_stat2hzscore( double val, int code, double p1,double p2,double p3 )
+{
+   pqpair pq ;
+
+   pq = stat2pq( val, code, p1,p2,p3 ) ;                    /* find cdf */
+   pq.q = 0.5*(1.0-pq.p) ; pq.p = 0.5*(1.0+pq.p) ;          /* mangle it */
+   return normal_pq2s( pq ) ;                               /* find z  */
+}
+
+/****************************************************************************/
+/*[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]*/
+/****************************************************************************/
+
+/*--------------------------------------------------------------------------*/
+/* Sample program to test the above functions.  Otherwise unimportant.
+----------------------------------------------------------------------------*/
+
+int main( int argc , char *argv[] )
+{
+   double val , p , q , p1=0.0,p2=0.0,p3=0.0 ;
+   double vbot,vtop,vdel ;
+   int code , iarg=1 , doq=0 , dod=0 , doi=0 , doz=0 , doh=0 ;
+
+   /*-- print some help for the pitiful user --*/
+
+   if( argc < 3 || strstr(argv[1],"help") != NULL ){
+    int ii ;
+    printf("\n") ;
+    printf("Demo program for computing NIfTI statistical functions.\n") ;
+    printf("Usage: nifti_stats [-q|-d|-1|-z] val CODE [p1 p2 p3]\n") ;
+    printf(" val can be a single number or in the form bot:top:step.\n") ;
+    printf(" default ==> output p = Prob(statistic < val).\n") ;
+    printf("  -q     ==> output is 1-p.\n") ;
+    printf("  -d     ==> output is density.\n") ;
+    printf("  -1     ==> output is x such that Prob(statistic < x) = val.\n") ;
+    printf("  -z     ==> output is z such that Normal cdf(z) = p(val).\n") ;
+    printf("  -h     ==> output is z such that 1/2-Normal cdf(z) = p(val).\n");
+    printf(" Allowable CODEs:\n") ;
+    for( ii=NIFTI_FIRST_STATCODE ; ii <= NIFTI_LAST_STATCODE ; ii++ ){
+     printf("  %-10s",inam[ii]); if((ii-NIFTI_FIRST_STATCODE)%6==5)printf("\n");
+    }
+    printf("\n") ;
+    printf(" Following CODE are distributional parameters, as needed.\n");
+    printf("\n") ;
+    printf("Results are written to stdout, 1 number per output line.\n") ;
+    printf("Example (piping output into AFNI program 1dplot):\n") ;
+    printf(" nifti_stats -d 0:4:.001 INVGAUSS 1 3 | 1dplot -dx 0.001 -stdin\n");
+    printf("\n") ;
+    printf("Author - RW Cox - SSCC/NIMH/NIH/DHHS/USA/EARTH - March 2004\n") ;
+    printf("\n") ;
+    exit(0) ;
+   }
+
+   /*-- check first arg to see if it is an output option;
+        if so, set the appropriate output flag to determine what to compute --*/
+
+        if( strcmp(argv[iarg],"-q") == 0 ){ doq = 1 ; iarg++ ; }
+   else if( strcmp(argv[iarg],"-d") == 0 ){ dod = 1 ; iarg++ ; }
+   else if( strcmp(argv[iarg],"-1") == 0 ){ doi = 1 ; iarg++ ; }
+   else if( strcmp(argv[iarg],"-z") == 0 ){ doz = 1 ; iarg++ ; }
+   else if( strcmp(argv[iarg],"-h") == 0 ){ doh = 1 ; iarg++ ; }
+
+   /*-- get the value(s) to process --*/
+
+   vbot=vtop=vdel = 0.0 ;
+   sscanf( argv[iarg++] , "%lf:%lf:%lf" , &vbot,&vtop,&vdel ) ;
+   if( vbot >= vtop ) vdel = 0.0 ;
+   if( vdel <= 0.0  ) vtop = vbot ;
+
+   /*-- decode the CODE into the integer signifying the distribution --*/
+
+   code = nifti_intent_code(argv[iarg++]) ;
+     if( code < 0 ){ fprintf(stderr,"illegal code=%s\n",argv[iarg-1]); exit(1); }
+
+   /*-- get the parameters, if present (defaults are 0) --*/
+
+   if( argc > iarg ) p1 = strtod(argv[iarg++],NULL) ;
+   if( argc > iarg ) p2 = strtod(argv[iarg++],NULL) ;
+   if( argc > iarg ) p3 = strtod(argv[iarg++],NULL) ;
+
+   /*-- loop over input value(s), compute output, write to stdout --*/
+
+   for( val=vbot ; val <= vtop ; val += vdel ){
+     if( doq )                                        /* output = 1-cdf */
+       p = nifti_stat2rcdf( val , code,p1,p2,p3 ) ;
+     else if( dod )                                   /* output = density */
+       p = 1000.0*( nifti_stat2cdf(val+.001,code,p1,p2,p3)
+                   -nifti_stat2cdf(val     ,code,p1,p2,p3)) ;
+     else if( doi )                                   /* output = inverse */
+       p = nifti_cdf2stat( val , code,p1,p2,p3 ) ;
+     else if( doz )                                   /* output = z score */
+       p = nifti_stat2zscore( val , code,p1,p2,p3 ) ;
+     else if( doh )                                   /* output = halfz score */
+       p = nifti_stat2hzscore( val , code,p1,p2,p3 ) ;
+     else                                              /* output = cdf */
+       p = nifti_stat2cdf( val , code,p1,p2,p3 ) ;
+
+     printf("%.9g\n",p) ;
+     if( vdel <= 0.0 ) break ;  /* the case of just 1 value */
+   }
+
+   /*-- terminus est --*/
+
+   exit(0) ;
+}
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/nifti_stats_mex.c b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/nifti_stats_mex.c
new file mode 100644
index 0000000000000000000000000000000000000000..6c617243f9b7f444ffc76f8ab03a4aa649bacef7
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/nifti_stats_mex.c
@@ -0,0 +1,129 @@
+#ifndef lint
+static char svnid[] = "Id: nifti_stats_mex.c 253 2005-10-13 15:31:34Z guillaume ";
+#endif
+/* 
+ * This is a Matlab mex interface for Bob Cox's extensive nifti_stats.c
+ * functionality.  See nifti_stats.m for documentation.
+ */
+
+
+/*
+ * niftilib $Id: nifti_stats_mex.c,v 1.1 2012/03/22 18:36:33 fissell Exp $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include "mex.h"
+
+#include "nifti1.h"
+extern int     nifti_intent_code( char *name );
+extern double     nifti_stat2cdf( double val, int code, double p1,double p2,double p3 );
+extern double    nifti_stat2rcdf( double val, int code, double p1,double p2,double p3 );
+extern double     nifti_stat2cdf( double val, int code, double p1,double p2,double p3 );
+extern double     nifti_cdf2stat( double val, int code, double p1,double p2,double p3 );
+extern double  nifti_stat2zscore( double val, int code, double p1,double p2,double p3 );
+extern double nifti_stat2hzscore( double val, int code, double p1,double p2,double p3 );
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+   double *val, *p, p1=0.0,p2=0.0,p3=0.0 ;
+   int code=5, dop=1, doq=0, dod=0, doi=0, doz=0, doh=0 ;
+   int ndim, i, n;
+   const int *dim;
+
+   if (nlhs>1) mexErrMsgTxt("Too many output arguments.");
+   if (nrhs<1) mexErrMsgTxt("Not enough input arguments.");
+   if (nrhs>4) mexErrMsgTxt("Too many input arguments.");
+
+   /* VAL */
+   if (!mxIsNumeric(prhs[0]) || !mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]))
+      mexErrMsgTxt("Wrong datatype for 1st argument.");
+   ndim = mxGetNumberOfDimensions(prhs[0]);
+   dim  = mxGetDimensions(prhs[0]);
+   n    = 1;
+   for(i=0,n=1; i<ndim; i++)
+      n = n*dim[i];
+   val = mxGetPr(prhs[0]);
+
+   /* CODE */
+   if (nrhs>=2)
+   {
+      if (mxIsChar(prhs[1]))
+      {
+         int buflen;
+         char *buf;
+         buflen = mxGetN(prhs[1])*mxGetM(prhs[1])+1;
+         buf    = (char *)mxCalloc(buflen,sizeof(char));
+         mxGetString(prhs[1],buf,buflen);
+         code   = nifti_intent_code(buf);
+         mxFree(buf);
+      }
+      else if (mxIsNumeric(prhs[1]) && mxIsDouble(prhs[1]) && !mxIsComplex(prhs[1]))
+      {
+         if (mxGetM(prhs[1])*mxGetN(prhs[1]) != 1)
+            mexErrMsgTxt("Wrong sized 2nd argument.");
+         code   = (int)mxGetPr(prhs[1])[0];
+      }
+      else mexErrMsgTxt("Wrong datatype for 2nd argument.");
+      if (code<NIFTI_FIRST_STATCODE || code>NIFTI_LAST_STATCODE)
+          mexErrMsgTxt("Illegal Stat-Code.");
+   }
+
+   /* OPT */
+   if (nrhs>=3)
+   {
+      int buflen;
+      char *buf;
+      dop = 0;
+      if (!mxIsChar(prhs[2]))
+         mexErrMsgTxt("Wrong datatype for3rd argument.");
+      buflen = mxGetN(prhs[2])*mxGetM(prhs[2])+1;
+      buf = (char *)mxCalloc(buflen,sizeof(char));
+      mxGetString(prhs[2],buf,buflen);
+      if      ( strcmp(buf,"-p") == 0 ) dop = 1;
+      else if ( strcmp(buf,"-q") == 0 ) doq = 1;
+      else if ( strcmp(buf,"-d") == 0 ) dod = 1;
+      else if ( strcmp(buf,"-1") == 0 ) doi = 1;
+      else if ( strcmp(buf,"-z") == 0 ) doz = 1;
+      else if ( strcmp(buf,"-h") == 0 ) doh = 1;
+      else { mxFree(buf); mexErrMsgTxt("Unrecognised option."); }
+      mxFree(buf);
+   }
+
+   /* PARAM */
+   if (nrhs>=4)
+   {
+      int np;
+      if (!mxIsNumeric(prhs[3]) || !mxIsDouble(prhs[3]) || mxIsComplex(prhs[3]))
+         mexErrMsgTxt("Wrong datatype for 4th argument.");
+      np = mxGetM(prhs[3])*mxGetN(prhs[3]);
+      if (np>3) mexErrMsgTxt("Wrong sized 4th argument.");
+      if (np>=1) p1 = mxGetPr(prhs[3])[0];
+      if (np>=2) p2 = mxGetPr(prhs[3])[1];
+      if (np>=3) p3 = mxGetPr(prhs[3])[2];
+   }
+
+   /* P */
+   plhs[0] = mxCreateNumericArray(ndim,dim,mxDOUBLE_CLASS,mxREAL);
+   p       = mxGetData(plhs[0]);
+
+   /* Call Bob's code */
+   for(i=0; i<n; i++)
+   {
+      if      ( dop )
+         p[i] = nifti_stat2cdf(val[i], code,p1,p2,p3 ) ;
+      else if ( doq )
+         p[i] = nifti_stat2rcdf(val[i], code,p1,p2,p3 ) ;
+      else if ( dod )
+         p[i] = 1000.0*( nifti_stat2cdf(val[i]+.001,code,p1,p2,p3)
+                        -nifti_stat2cdf(val[i]     ,code,p1,p2,p3)) ;
+      else if ( doi )
+         p[i] = nifti_cdf2stat(val[i], code,p1,p2,p3 ) ;
+      else if ( doz )
+         p[i] = nifti_stat2zscore(val[i], code,p1,p2,p3 ) ;
+      else if ( doh )
+         p[i] = nifti_stat2hzscore(val[i], code,p1,p2,p3 ) ;
+   }
+}
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/write_extras.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/write_extras.m
new file mode 100644
index 0000000000000000000000000000000000000000..49c4cc54591d5f622a6daf54fc0e20381287ccf7
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/write_extras.m
@@ -0,0 +1,41 @@
+function extras = write_extras(fname,extras)
+% Write extra bits of information
+%_______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: write_extras.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: write_extras.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+[pth,nam,ext] = fileparts(fname);
+switch ext
+case {'.hdr','.img','.nii'}
+    mname = fullfile(pth,[nam '.mat']);
+case {'.HDR','.IMG','.NII'}
+    mname = fullfile(pth,[nam '.MAT']);
+otherwise
+    mname = fullfile(pth,[nam '.mat']);
+end
+if isstruct(extras) && ~isempty(fieldnames(extras)),
+    savefields(mname,extras);
+end;
+
+function savefields(fnam,p)
+if length(p)>1, error('Can''t save fields.'); end;
+fn = fieldnames(p);
+for i_=1:length(fn),
+    eval([fn{i_} '= p.' fn{i_} ';']);
+end;
+if str2num(version('-release'))>=14,
+    fn = {'-V6',fn{:}};
+end;
+if numel(fn)>0,
+    save(fnam,fn{:});
+end;
+return;
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/write_hdr_raw.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/write_hdr_raw.m
new file mode 100644
index 0000000000000000000000000000000000000000..01b65e57f1c75fbffa28bb05af390179d0cc3851
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/write_hdr_raw.m
@@ -0,0 +1,82 @@
+function ok = write_hdr_raw(fname,hdr,be)
+% Write a NIFTI-1 .hdr file.
+% FORMAT ok = write_hdr_raw(fname,hdr,be)
+% fname - filename of image
+% hdr   - a structure containing hdr info
+% be    - whether big-endian or not
+% ok    - status (1=good, 0=bad)
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: write_hdr_raw.m 2237 2008-09-29 17:39:53Z guillaume 
+
+%
+% niftilib $Id: write_hdr_raw.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+
+[pth,nam,ext] = fileparts(fname);
+if isempty(pth), pth = pwd; end
+
+if isfield(hdr,'magic')
+    org = niftistruc;
+    switch deblank(hdr.magic)
+    case {'ni1'}
+        hname = fullfile(pth,[nam '.hdr']);
+    case {'n+1'}
+        hname = fullfile(pth,[nam '.nii']);
+    otherwise
+        error('Bad header.');
+    end;
+else
+    org   = mayostruc;
+    hname = fullfile(pth,[nam '.hdr']);
+end;
+
+if nargin >=3
+    if be, mach = 'ieee-be';
+    else   mach = 'ieee-le';
+    end;
+else       mach = 'native';
+end;
+
+ok = true;
+if spm_existfile(hname),
+    fp = fopen(hname,'r+',mach);
+else
+    fp = fopen(hname,'w+',mach);
+end
+if fp == -1,
+    ok = false;
+    return;
+end
+
+for i=1:length(org)
+    if isfield(hdr,org(i).label),
+        dat = hdr.(org(i).label);
+        if length(dat) ~= org(i).len,
+            if length(dat)< org(i).len,
+                dat = [dat(:) ; zeros(org(i).len-length(dat),1)];
+            else
+                dat = dat(1:org(i).len);
+            end;
+        end;
+    else
+        dat = org(i).def;
+    end;
+    % fprintf('%s=\n',org(i).label)
+    % disp(dat)
+    len = fwrite(fp,dat,org(i).dtype.prec);
+    if len ~= org(i).len,
+        ok = false;
+    end;
+end;
+fclose(fp);
+if ~ok,
+     fprintf('There was a problem writing to the header of\n');
+     fprintf('"%s"\n', fname);
+end;
+return;
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/structn.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/structn.m
new file mode 100644
index 0000000000000000000000000000000000000000..074ab049638eb314e1d66218aac044bde82335fd
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/structn.m
@@ -0,0 +1,24 @@
+function t = structn(obj)
+% Convert a NIFTI-1 object into a form of struct
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: structn.m 1143 2008-02-07 19:33:33Z spm 
+
+%
+% niftilib $Id: structn.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+if numel(obj)~=1,
+    error('Too many elements to convert');
+end;
+fn = fieldnames(obj);
+for i=1:length(fn)
+    tmp = subsref(obj,struct('type','.','subs',fn{i}));
+    if ~isempty(tmp)
+        t.(fn{i}) = tmp;
+    end;
+end;
+return;
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/subsasgn.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/subsasgn.m
new file mode 100644
index 0000000000000000000000000000000000000000..5335be170879ac1f762cd66a424934b0f250e46a
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/subsasgn.m
@@ -0,0 +1,404 @@
+function obj = subsasgn(obj,subs,varargin)
+% Subscript assignment
+% See subsref for meaning of fields.
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: subsasgn.m 4136 2010-12-09 22:22:28Z guillaume 
+
+%
+% niftilib $Id: subsasgn.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+switch subs(1).type,
+case {'.'},
+    if numel(obj)~=nargin-2,
+        error('The number of outputs should match the number of inputs.');
+    end;
+    objs = struct(obj);
+    for i=1:length(varargin),
+        val     = varargin{i};
+        obji    = nifti(objs(i));
+        obji    = fun(obji,subs,val);
+        objs(i) = struct(obji);
+    end;
+    obj = nifti(objs);
+
+case {'()'},
+    objs = struct(obj);
+    if length(subs)>1,
+        t    = subsref(objs,subs(1));
+        % A lot of this stuff is a little flakey, and may cause Matlab to bomb.
+        % 
+        %if numel(t) ~= nargin-2,
+        %    error('The number of outputs should match the number of inputs.');
+        %end;
+        for i=1:numel(t),
+            val  = varargin{1};
+            obji = nifti(t(i));
+            obji = subsasgn(obji,subs(2:end),val);
+            t(i) = struct(obji);
+        end;
+        objs = subsasgn(objs,subs(1),t);
+    else
+        if numel(varargin)>1,
+            error('Illegal right hand side in assignment. Too many elements.');
+        end;
+        val = varargin{1};
+        if isa(val,'nifti'),
+            objs = subsasgn(objs,subs,struct(val));
+        elseif isempty(val),
+            objs = subsasgn(objs,subs,[]);
+        else
+            error('Assignment between unlike types is not allowed.');
+        end;
+    end;
+    obj = nifti(objs);
+
+otherwise
+    error('Cell contents reference from a non-cell array object.');
+end;
+return;
+%=======================================================================
+
+%=======================================================================
+function obj = fun(obj,subs,val)
+% Subscript referencing
+
+switch subs(1).type,
+case {'.'},
+    objs = struct(obj);
+    for ii=1:numel(objs)
+        obj = objs(ii);
+
+        if any(strcmpi(subs(1).subs,{'dat'})),
+            if length(subs)>1,
+                val = subsasgn(obj.dat,subs(2:end),val);
+            end;
+            obj      = assigndat(obj,val);
+            objs(ii) = obj;
+            continue;
+        end;
+
+        if isempty(obj.hdr), obj.hdr = empty_hdr; end;
+        if ~isfield(obj.hdr,'magic'), error('Not a NIFTI-1 header'); end;
+
+        if length(subs)>1, % && ~strcmpi(subs(1).subs,{'raw','dat'}),
+            val0 = subsref(nifti(obj),subs(1));
+            val1 = subsasgn(val0,subs(2:end),val);
+        else
+            val1 = val;
+        end;
+
+        switch(subs(1).subs)
+        case {'extras'}
+            if length(subs)>1,
+                obj.extras = subsasgn(obj.extras,subs(2:end),val);
+            else
+                obj.extras = val;
+            end;
+
+        case {'mat0'}
+            if ~isnumeric(val1) || ndims(val1)~=2 || any(size(val1)~=[4 4]) || sum((val1(4,:)-[0 0 0 1]).^2)>1e-8,
+                error('"mat0" should be a 4x4 matrix, with a last row of 0,0,0,1.');
+            end;
+            if obj.hdr.qform_code==0, obj.hdr.qform_code=2; end;
+            s = double(bitand(obj.hdr.xyzt_units,7));
+            if s
+                d = findindict(s,'units');
+                val1 = diag([[1 1 1]/d.rescale 1])*val1;
+            end;
+            obj.hdr = encode_qform0(double(val1), obj.hdr);
+
+        case {'mat0_intent'}
+            if isempty(val1),
+                obj.hdr.qform_code = 0;
+            else
+                if ~ischar(val1) && ~(isnumeric(val1) && numel(val1)==1),
+                    error('"mat0_intent" should be a string or a scalar.');
+                end;
+                d = findindict(val1,'xform');
+                if ~isempty(d)
+                    obj.hdr.qform_code = d.code;
+                end;
+            end;
+
+        case {'mat'}
+            if ~isnumeric(val1) || ndims(val1)~=2 || any(size(val1)~=[4 4]) || sum((val1(4,:)-[0 0 0 1]).^2)>1e-8
+                error('"mat" should be a 4x4 matrix, with a last row of 0,0,0,1.');
+            end;
+            if obj.hdr.sform_code==0, obj.hdr.sform_code=2; end;
+            s = double(bitand(obj.hdr.xyzt_units,7));
+            if s
+                d = findindict(s,'units');
+                val1 = diag([[1 1 1]/d.rescale 1])*val1;
+            end;
+            val1           = val1 * [eye(4,3) [1 1 1 1]'];
+            obj.hdr.srow_x = val1(1,:);
+            obj.hdr.srow_y = val1(2,:);
+            obj.hdr.srow_z = val1(3,:);
+
+        case {'mat_intent'}
+            if isempty(val1),
+                obj.hdr.sform_code = 0;
+            else
+                if ~ischar(val1) && ~(isnumeric(val1) && numel(val1)==1),
+                    error('"mat_intent" should be a string or a scalar.');
+                end;
+                d = findindict(val1,'xform');
+                if ~isempty(d),
+                    obj.hdr.sform_code = d.code;
+                end;
+            end;
+
+        case {'intent'}
+            if ~valid_fields(val1,{'code','param','name'})
+                obj.hdr.intent_code = 0;
+                obj.hdr.intent_p1   = 0;
+                obj.hdr.intent_p2   = 0;
+                obj.hdr.intent_p3   = 0;
+                obj.hdr.intent_name = '';
+            else
+                if ~isfield(val1,'code'),
+                    val1.code = obj.hdr.intent_code;
+                end;
+                d = findindict(val1.code,'intent');
+                if ~isempty(d),
+                    obj.hdr.intent_code = d.code;
+                    if isfield(val1,'param'),
+                        prm = [double(val1.param(:))  ; 0 ; 0; 0];
+                        prm = [prm(1:length(d.param)) ; 0 ; 0; 0];
+                        obj.hdr.intent_p1 = prm(1);
+                        obj.hdr.intent_p2 = prm(2);
+                        obj.hdr.intent_p3 = prm(3);
+                    end;
+                    if isfield(val1,'name'),
+                        obj.hdr.intent_name = val1.name;
+                    end;
+                end;
+            end;
+
+         case {'diminfo'}
+            if ~valid_fields(val1,{'frequency','phase','slice','slice_time'})
+                tmp = obj.hdr.dim_info;
+                for bit=1:6,
+                    tmp = bitset(tmp,bit,0);
+                end;
+                obj.hdr.dim_info       = tmp;
+                obj.hdr.slice_start    = 0;
+                obj.hdr.slice_end      = 0;
+                obj.hdr.slice_duration = 0;
+                obj.hdr.slice_code     = 0;
+            else
+                if isfield(val1,'frequency'),
+                    tmp = val1.frequency;
+                    if ~isnumeric(tmp) || numel(tmp)~=1 || tmp<0 || tmp>3,
+                        error('Invalid frequency direction');
+                    end;
+                    obj.hdr.dim_info = bitset(obj.hdr.dim_info,1,bitget(tmp,1));
+                    obj.hdr.dim_info = bitset(obj.hdr.dim_info,2,bitget(tmp,2));
+                end;
+
+                if isfield(val1,'phase'),
+                    tmp = val1.phase;
+                    if ~isnumeric(tmp) || numel(tmp)~=1 || tmp<0 || tmp>3,
+                        error('Invalid phase direction');
+                    end;
+                    obj.hdr.dim_info = bitset(obj.hdr.dim_info,3,bitget(tmp,1));
+                    obj.hdr.dim_info = bitset(obj.hdr.dim_info,4,bitget(tmp,2));
+                end;
+
+                if isfield(val1,'slice'),
+                    tmp = val1.slice;
+                    if ~isnumeric(tmp) || numel(tmp)~=1 || tmp<0 || tmp>3,
+                        error('Invalid slice direction');
+                    end;
+                    obj.hdr.dim_info = bitset(obj.hdr.dim_info,5,bitget(tmp,1));
+                    obj.hdr.dim_info = bitset(obj.hdr.dim_info,6,bitget(tmp,2));
+                end;
+
+                if isfield(val1,'slice_time')
+                    tim = val1.slice_time;
+                    if ~valid_fields(tim,{'start','end','duration','code'}),
+                        obj.hdr.slice_code     = 0;
+                        obj.hdr.slice_start    = 0;
+                        obj.hdr.end_slice      = 0;
+                        obj.hdr.slice_duration = 0;
+                    else
+                        % sld = double(bitget(obj.hdr.dim_info,5)) + 2*double(bitget(obj.hdr.dim_info,6));
+
+                        if isfield(tim,'start'),
+                            ss = double(tim.start);
+                            if isnumeric(ss) && numel(ss)==1 && ~rem(ss,1), % && ss>=1 && ss<=obj.hdr.dim(sld+1)
+                                obj.hdr.slice_start = ss-1;
+                            else
+                                error('Inappropriate "slice_time.start".');
+                            end;
+                        end;
+
+                        if isfield(tim,'end'),
+                            ss = double(tim.end);
+                            if isnumeric(ss) && numel(ss)==1 && ~rem(ss,1), % && ss>=1 && ss<=obj.hdr.dim(sld+1)
+                                obj.hdr.slice_end = ss-1;
+                            else
+                                error('Inappropriate "slice_time.end".');
+                            end;
+                        end;
+
+                        if isfield(tim,'duration')
+                            sd = double(tim.duration);
+                            if isnumeric(sd) && numel(sd)==1,
+                                s  = double(bitand(obj.hdr.xyzt_units,24));
+                                d  = findindict(s,'units');
+                                if ~isempty(d) && d.rescale, sd = sd/d.rescale; end;
+                                obj.hdr.slice_duration = sd;
+                            else
+                                error('Inappropriate "slice_time.duration".');
+                            end;
+                        end;
+
+                        if isfield(tim,'code'),
+                            d = findindict(tim.code,'sliceorder');
+                            if ~isempty(d),
+                                obj.hdr.slice_code = d.code;
+                            end;
+                        end;
+                    end;
+                end;
+            end;
+
+        case {'timing'}
+            if ~valid_fields(val1,{'toffset','tspace'}),
+                obj.hdr.pixdim(5) = 0;
+                obj.hdr.toffset   = 0;
+            else
+                s  = double(bitand(obj.hdr.xyzt_units,24));
+                d  = findindict(s,'units');
+                if isfield(val1,'toffset'),
+                    if isnumeric(val1.toffset) && numel(val1.toffset)==1,
+                        if d.rescale,
+                            val1.toffset = val1.toffset/d.rescale;
+                        end;
+                        obj.hdr.toffset   = val1.toffset;
+                    else
+                        error('"timing.toffset" needs to be numeric with 1 element');
+                    end;
+                end;
+                if isfield(val1,'tspace'),
+                    if isnumeric(val1.tspace) && numel(val1.tspace)==1,
+                        if d.rescale,
+                            val1.tspace = val1.tspace/d.rescale;
+                        end;
+                        obj.hdr.pixdim(5) = val1.tspace;
+                    else
+                        error('"timing.tspace" needs to be numeric with 1 element');
+                    end;
+                end;
+            end;
+
+        case {'descrip'}
+            if isempty(val1), val1 = char(val1); end;
+            if ischar(val1),
+                obj.hdr.descrip = val1;
+            else
+                error('"descrip" must be a string.');
+            end;
+
+        case {'cal'}
+            if isempty(val1),
+                obj.hdr.cal_min = 0;
+                obj.hdr.cal_max = 0;
+            else
+                if isnumeric(val1) && numel(val1)==2,
+                    obj.hdr.cal_min = val1(1);
+                    obj.hdr.cal_max = val1(2);
+                else
+                    error('"cal" should contain two elements.');
+                end;
+            end;
+
+        case {'aux_file'}
+            if isempty(val1), val1 = char(val1); end;
+            if ischar(val1),
+                obj.hdr.aux_file = val1;
+            else
+                error('"aux_file" must be a string.');
+            end;
+
+        case {'hdr'}
+            error('hdr is a read-only field.');
+            obj.hdr = val1;
+
+        otherwise
+            error(['Reference to non-existent field ''' subs(1).subs '''.']);
+        end;
+
+        objs(ii) = obj;
+    end
+    obj = nifti(objs);
+
+otherwise
+    error('This should not happen.');
+end;
+return;
+%=======================================================================
+
+%=======================================================================
+function obj = assigndat(obj,val)
+if isa(val,'file_array'),
+    sz = size(val);
+    if numel(sz)>7,
+        error('Too many dimensions in data.');
+    end;
+    sz = [sz 1 1 1 1 1 1 1];
+    sz = sz(1:7);
+    sval = struct(val);
+    d    = findindict(sval.dtype,'dtype');
+    if isempty(d)
+        error(['Unknown datatype (' num2str(double(sval.datatype)) ').']);
+    end;
+
+    [pth,nam,suf]    = fileparts(sval.fname);
+    if any(strcmp(suf,{'.img','.IMG'}))
+        val.offset = max(sval.offset,0);
+        obj.hdr.magic = ['ni1' char(0)];
+    elseif any(strcmp(suf,{'.nii','.NII'}))
+        val.offset = max(sval.offset,352);
+        obj.hdr.magic = ['n+1' char(0)];
+    else
+        error(['Unknown filename extension (' suf ').']);
+    end;
+    val.offset        = (ceil(val.offset/16))*16;
+    obj.hdr.vox_offset = val.offset;
+
+    obj.hdr.dim(2:(numel(sz)+1)) = sz;
+    nd = max(find(obj.hdr.dim(2:end)>1));
+    if isempty(nd), nd = 3; end;
+    obj.hdr.dim(1)   = nd;
+    obj.hdr.datatype = sval.dtype;
+    obj.hdr.bitpix   = d.size*8;
+    if ~isempty(sval.scl_slope), obj.hdr.scl_slope = sval.scl_slope; end;
+    if ~isempty(sval.scl_inter), obj.hdr.scl_inter = sval.scl_inter; end;
+    obj.dat          = val;
+else
+    error('"raw" must be of class "file_array"');
+end;
+return;
+
+function ok = valid_fields(val,allowed)
+if isempty(val), ok = false; return; end;
+if ~isstruct(val),
+    error(['Expecting a structure, not a ' class(val) '.']);
+end;
+fn = fieldnames(val);
+for ii=1:length(fn),
+    if ~any(strcmpi(fn{ii},allowed)),
+        fprintf('Allowed fieldnames are:\n');
+        for i=1:length(allowed), fprintf('    %s\n', allowed{i}); end;
+        error(['"' fn{ii} '" is not a valid fieldname.']);
+    end
+end
+ok = true;
+return;
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/subsref.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/subsref.m
new file mode 100644
index 0000000000000000000000000000000000000000..dcedc971af54b9f1fb05813de10d49a90d0f46e6
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/subsref.m
@@ -0,0 +1,245 @@
+function varargout = subsref(opt,subs)
+% Subscript referencing
+%
+% Fields are:
+% dat         - a file-array representing the image data
+% mat0        - a  9-parameter affine transform (from qform0)
+%               Note that the mapping is from voxels (where the first
+%               is considered to be at [1,1,1], to millimetres.  See
+%               mat0_interp for the meaning of the transform.
+% mat         - a 12-parameter affine transform (from sform0)
+%               Note that the mapping is from voxels (where the first
+%               is considered to be at [1,1,1], to millimetres.  See
+%               mat1_interp for the meaning of the transform.
+% mat_intent  - intention of mat.  This field may be missing/empty.
+% mat0_intent - intention of mat0. This field may be missing/empty.
+% intent      - interpretation of image. When present, this structure
+%               contains the fields
+%               code   - name of interpretation
+%               params - parameters needed to interpret the image
+% diminfo     - MR encoding of different dimensions.  This structure may
+%               contain some or all of the following fields
+%               frequency  - a value of 1-3 indicating frequency direction
+%               phase      - a value of 1-3 indicating phase direction
+%               slice      - a value of 1-3 indicating slice direction
+%               slice_time - only present when "slice" field is present.
+%                            Contains the following fields
+%                            code     - ascending/descending etc
+%                            start    - starting slice number
+%                            end      - ending slice number
+%                            duration - duration of each slice acquisition
+%               Setting frequency, phase or slice to 0 will remove it.
+% timing      - timing information.  When present, contains the fields
+%               toffset - acquisition time of first volume (seconds)
+%               tspace  - time between sucessive volumes (seconds)
+% descrip     - a brief description of the image
+% cal         - a two-element vector containing cal_min and cal_max
+% aux_file    - name of an auxiliary file
+% _______________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+%
+% Id: subsref.m 4136 2010-12-09 22:22:28Z guillaume 
+
+%
+% niftilib $Id: subsref.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+
+varargout = rec(opt,subs);
+return;
+
+function c = rec(opt,subs)
+switch subs(1).type,
+case {'.'},
+    c = {};
+    opts = struct(opt);
+    for ii=1:numel(opts)
+        opt = nifti(opts(ii));
+        %if ~isstruct(opt)
+        %    error('Attempt to reference field of non-structure array.');
+        %end;
+
+        h = opt.hdr;
+        if isempty(h),
+            %error('No header.');
+            h = empty_hdr;
+        end;
+
+        % NIFTI-1 FORMAT
+        switch(subs(1).subs)
+        case 'extras',
+            t = opt.extras;
+
+        case 'raw', % A hidden field
+            if isa(opt.dat,'file_array'),
+                tmp         = struct(opt.dat);
+                tmp.scl_slope = [];
+                tmp.scl_inter = [];
+                t           = file_array(tmp);
+            else
+                t = opt.dat;
+            end;
+
+        case 'dat',
+            t = opt.dat;
+
+        case 'mat0',
+            t = decode_qform0(h);
+            s = double(bitand(h.xyzt_units,7));
+            if s
+                d = findindict(s,'units');
+                if ~isempty(d)
+                    t = diag([d.rescale*[1 1 1] 1])*t; 
+                end;
+            end;
+
+        case 'mat0_intent',
+            d = findindict(h.qform_code,'xform');
+            if isempty(d) || d.code==0,
+                t = '';
+            else
+                t = d.label;
+            end;
+
+        case 'mat',
+            if h.sform_code > 0
+                t = double([h.srow_x ; h.srow_y ; h.srow_z ; 0 0 0 1]);
+                t = t * [eye(4,3) [-1 -1 -1 1]'];
+            else
+                t = decode_qform0(h);
+            end
+            s = double(bitand(h.xyzt_units,7));
+            if s
+                d = findindict(s,'units');
+                t = diag([d.rescale*[1 1 1] 1])*t;
+            end;
+
+        case 'mat_intent',
+            if h.sform_code>0,
+                t = h.sform_code;
+            else
+                t = h.qform_code;
+            end;
+            d = findindict(t,'xform');
+            if isempty(d) || d.code==0,
+                t = '';
+            else
+                t = d.label;
+            end;
+
+        case 'intent',
+            d = findindict(h.intent_code,'intent');
+            if isempty(d) || d.code == 0,
+                %t = struct('code','UNKNOWN','param',[]);
+                t = [];
+            else
+                t = struct('code',d.label,'param',...
+                    double([h.intent_p1 h.intent_p2 h.intent_p3]), 'name',deblank(h.intent_name));
+                t.param = t.param(1:length(d.param));
+            end
+
+         case 'diminfo',
+            t   = [];
+            tmp = bitand(         h.dim_info    ,3); if tmp, t.frequency = double(tmp); end;
+            tmp = bitand(bitshift(h.dim_info,-2),3); if tmp, t.phase     = double(tmp); end;
+            tmp = bitand(bitshift(h.dim_info,-4),3); if tmp, t.slice     = double(tmp); end;
+            % t = struct('frequency',bitand(         h.dim_info    ,3),...
+            %               'phase',bitand(bitshift(h.dim_info,-2),3),...
+            %               'slice',bitand(bitshift(h.dim_info,-4),3))
+            if isfield(t,'slice')
+                 sc = double(h.slice_code);
+                 ss = double(h.slice_start)+1;
+                 se = double(h.slice_end)+1;
+                 ss = max(ss,1);
+                 se = min(se,double(h.dim(t.slice+1)));
+
+                 sd = double(h.slice_duration);
+                 s  = double(bitand(h.xyzt_units,24));
+                 d  = findindict(s,'units');
+                 if d.rescale, sd = sd*d.rescale; end;
+
+                 ns       = (se-ss+1);
+                 d = findindict(sc,'sliceorder');
+                 if isempty(d)
+                     label = 'UNKNOWN';
+                 else
+                     label = d.label;
+                 end;
+                 t.slice_time = struct('code',label,'start',ss,'end',se,'duration',sd);
+                 if 0, % Never
+                     t.times  = zeros(1,double(h.dim(t.slice+1)))+NaN;
+                     switch sc,
+                     case 0, % Unknown
+                         t.times(ss:se)        = zeros(1,ns);
+                     case 1, % sequential increasing
+                         t.times(ss:se)        = (0:(ns-1))*sd;
+                     case 2, % sequential decreasing
+                         t.times(ss:se)        = ((ns-1):-1:0)*sd;
+                     case 3, % alternating increasing
+                         t.times(ss:2:se)      = (0:floor((ns+1)/2-1))*sd;
+                         t.times((ss+1):2:se)  = (floor((ns+1)/2):(ns-1))*sd;
+                     case 4, % alternating decreasing
+                         t.times(se:-2:ss)     = (0:floor((ns+1)/2-1))*sd;
+                         t.times(se:-2:(ss+1)) = (floor((ns+1)/2):(ns-1))*sd;
+                     end;
+                 end;
+             end;
+
+        case 'timing',
+            to = double(h.toffset);
+            dt = double(h.pixdim(5));
+            if to==0 && dt==0,
+                t = [];
+            else
+                s  = double(bitand(h.xyzt_units,24));
+                d  = findindict(s,'units');
+                if d.rescale,
+                    to = to*d.rescale;
+                    dt = dt*d.rescale;
+                end;
+                t  = struct('toffset',to,'tspace',dt);
+            end;
+
+        case 'descrip',
+            t   = deblank(h.descrip);
+            msk = find(t==0);
+            if any(msk), t=t(1:(msk(1)-1)); end;
+
+        case 'cal',
+            t = [double(h.cal_min) double(h.cal_max)];
+            if all(t==0), t = []; end;
+
+        case 'aux_file',
+            t = deblank(h.aux_file);
+
+        case 'hdr', % Hidden field
+            t = h;
+
+        otherwise
+            error(['Reference to non-existent field ''' subs(1).subs '''.']);
+        end;
+        if numel(subs)>1,
+            t = subsref(t,subs(2:end));
+        end;
+        c{ii} = t;
+    end;
+case {'{}'},
+    error('Cell contents reference from a non-cell array object.');
+case {'()'},
+    opt  = struct(opt);
+    t    = subsref(opt,subs(1));
+    if length(subs)>1
+        c = {};
+        for i=1:numel(t),
+            ti = nifti(t(i));
+            ti = rec(ti,subs(2:end));
+            c  = {c{:}, ti{:}};
+        end;
+    else
+        c    = {nifti(t)};
+    end;
+
+otherwise
+    error('This should not happen.');
+end;
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/Makefile b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..03e71fcaf915fec9f73da24af95f70b769015784
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/Makefile
@@ -0,0 +1,85 @@
+#!make -f
+#
+# The tardist file for the nifti1 matlab code contains precompiled
+# mex files for the PCWIN, MAC, SOL2, LNX86, GLNXA64 platforms, so
+# you do not need to do this build if you have one of those platforms.
+# Run "uname" at your shell prompt to see your platform code.
+# 
+# 
+# Two files need to be compiled with the MATLAB mex compiler: 
+#	file2mat.c 
+#	mat2file.c
+# These files are in the @file_array/private/src directory.
+# A successful compile will leave two "mex" files in the @file_array/private directory:
+# 	file2mat.mex<platform suffix>  
+#	mat2file.mex<platform suffix>
+#
+# To make the mex files, in this matlab directory type:
+#	make all
+#
+# 
+# Problems ?
+# If you need to make platform specific tweaks to the mex call, you
+# may want to look at the SPM8 (http://www.fil.ion.ucl.ac.uk/spm/)
+# distribution src/Makefile and src/Makefile.var that has more detailed flag settings.
+#
+# For Windows you need the CygWin environment (http://sourceware.org/cygwin/).
+# Install the Default configuration, along with the gcc C compiler, and make
+# from the "Devel" options.
+# You may want to refer to Matthew Brett's web page on mex files for Windows:
+# (http://gnumex.sourceforge.net/)
+#
+
+
+## Defines
+MEX = mex -O
+CC  = cc
+DIR = @file_array/private/src
+
+
+
+## Default targets
+unknown:
+	@ make `uname`
+
+all:
+	@ make `uname`
+
+help:
+	@echo "make all to compile the file2mat and mat2file mex libraries"
+	@echo ""
+
+
+## Platforms
+SunOS:	big_endian
+IRIX:	big_endian
+IRIX64:	big_endian
+HP-UX:	big_endian
+AIX:	big_endian
+OSF1:	big_endian
+
+# for MAC power pc reset to big_endian
+Darwin:	little_endian
+
+Linux:	little_endian
+Linux.A64:	little_endian
+
+CYGWIN_NT-4.0: windows
+CYGWIN_NT-5.0: windows
+CYGWIN_NT-5.1: windows
+
+
+
+## Compiles
+big_endian:
+	(cd $(DIR); $(MEX)  -DBIGENDIAN file2mat.c; mv *mex* ..)
+	(cd $(DIR); $(MEX)  -DBIGENDIAN mat2file.c; mv *mex* ..)
+
+little_endian:
+	(cd $(DIR); $(MEX)  file2mat.c; mv *mex* ..)
+	(cd $(DIR); $(MEX)  mat2file.c; mv *mex* ..)
+
+windows:
+	(cd $(DIR); $(MEX)  -DSPM_WIN32 file2mat.c; mv *.dll ..)
+	(cd $(DIR); $(MEX)  -DSPM_WIN32 mat2file.c; mv *.dll ..)
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/make.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/make.m
new file mode 100644
index 0000000000000000000000000000000000000000..8ffdd4c19ea8f8bcc29efca10db7fdc867385e74
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/make.m
@@ -0,0 +1,41 @@
+%
+% Makefile equivalent for use in MatLab
+% requires availability of MEX
+%
+% calling 'make' from the matlab prompt:
+% 1. compiles the c-sources in @file_array/private/src
+% 2. moves the compiled files to @file_array/private
+%
+% Alle Meije Wink 27/03/2012
+% a.wink@vumc.nl
+%
+
+%
+% niftilib $Id: make.m,v 1.1 2012/03/30 15:25:41 fissell Exp $
+%
+
+% check for existence of MEX compiler
+if (exist('mex') ~=2)
+    error('MEX not installed on your system. Exiting.');
+end
+
+% go to the directory where the c sources are
+cd(['@file_array' filesep 'private' filesep 'src'])
+
+% compile the 2 sources
+if(mex('file2mat.c') | mex('mat2file.c'))
+    error('something went wrong during compilation');
+else
+    % move them to the parent directory
+    if(~movefile('*.mex*','..'))
+        error('compiled files could not be moved')
+    end
+end
+
+% go bake to the directory of make.m
+cd(['..' filesep '..' filesep '..']);
+
+% report the good news
+disp ('files successfully compiled and moved')
+
+
diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/spm_flip_analyze_images.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/spm_flip_analyze_images.m
new file mode 100644
index 0000000000000000000000000000000000000000..1f56afae12c744dff696773b455c1f347c0c7eb6
--- /dev/null
+++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/spm_flip_analyze_images.m
@@ -0,0 +1,19 @@
+function flip = spm_flip_analyze_images
+% Do Analyze format images need to be left-right flipped? The default
+% behaviour is to have the indices of the voxels stored as left-handed and
+% interpret the mm coordinates within a right-handed coordinate system.
+%
+% Note: the behaviour used to be set in spm_defaults.m, but this has now
+% been changed.
+%__________________________________________________________________________
+% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging
+
+% John Ashburner
+% Id: spm_flip_analyze_images.m 1418 2008-04-15 19:15:16Z john 
+
+%
+% niftilib $Id: spm_flip_analyze_images.m,v 1.3 2012/03/22 18:36:33 fissell Exp $
+%
+
+flip = 1;
+
diff --git a/PPMI_NODDI.m b/PPMI_NODDI.m
new file mode 100644
index 0000000000000000000000000000000000000000..4b62d03e54c9b23c4f775a70c2afa3769f4fb349
--- /dev/null
+++ b/PPMI_NODDI.m
@@ -0,0 +1,51 @@
+function PPMI_NODDI(i)
+addpath(genpath('NODDI_toolbox_v1.0.1'));
+importPPMIlist
+PatientNumber=VarName1;
+%for i=1:floor(length(PatientNumber)/3)
+% 
+% [bVal, bGradX, bGradY, bGradZ] = textread(strcat('/data/project/dti/For_William/rotateDWIv2/BMTXT/',int2str(PatientNumber(i)),'.rotatetwo.BVEC.txt'),'%f %f %f %f');
+% lengthB = length(bGradX);
+% 
+% fileID = fopen(strcat('/data/project/dti/For_William/rotateDWIv2/BMTXT/',int2str(PatientNumber(i)),'.rotatetwo.bval'),'w');
+% 
+% formatSpec = '%f ';
+% 
+%         for j=1:lengthB
+%             fprintf(fileID,formatSpec,bVal(j));
+%         end
+%         fclose(fileID);
+% 
+% clear fileID
+% 
+% fileID = fopen(strcat('/data/project/dti/For_William/rotateDWIv2/BMTXT/',int2str(PatientNumber(i)),'.rotatetwo.bvec'),'w');
+% 
+% formatSpec = '%f ';
+% 
+%         for j=1:lengthB
+%             fprintf(fileID,formatSpec,bGradX(j));
+%         end
+%         
+%         fprintf(fileID,'\n');
+%         
+%         for j=1:lengthB
+%             fprintf(fileID,formatSpec,bGradY(j));
+%         end
+%         
+%         fprintf(fileID,'\n');
+%         
+%         for j=1:lengthB
+%             fprintf(fileID,formatSpec,bGradZ(j));
+%         end
+%         fclose(fileID);
+% 
+% clear fileID
+
+CreateROI(strcat('/data/project/dti/For_William/rotateDWIv2/finalrotatedDWIv2/',int2str(PatientNumber(i)),'.DWI.rotat.med.nii'),strcat('/data/project/dti/For_William/rotateDWIv2/brainMasks/',int2str(PatientNumber(i)),'.brainmask.nii'),strcat('/data/project/dti/For_William/rotateDWIv2/FreeWaterResults_WB/',int2str(PatientNumber(i)),'.NODDIroi.mat'));
+%CreateROI('/data/project/dti/For_William/rotateDWIv2/finalrotatedDWIv2/3111.DWI.rotat.med.nii','/data/project/dti/For_William/rotateDWIv2/brainMasks/3111.brainmask.nii','NODDIroi1.mat')
+protocol = FSL2Protocol(strcat('/data/project/dti/For_William/rotateDWIv2/BMTXT/',int2str(PatientNumber(i)),'.rotatetwo.bval'),strcat('/data/project/dti/For_William/rotateDWIv2/BMTXT/',int2str(PatientNumber(i)),'.rotatetwo.bvec'))
+noddi = MakeModel('WatsonSHStickTortIsoV_B0');
+batch_fitting(strcat('/data/project/dti/For_William/rotateDWIv2/FreeWaterResults_WB/',int2str(PatientNumber(i)),'.NODDIroi.mat'),protocol,noddi,strcat('/data/project/dti/For_William/rotateDWIv2/FreeWaterResults_WB/',int2str(PatientNumber(i)),'.FittedParams.mat'),8);
+SaveParamsAsNIfTI(strcat('/data/project/dti/For_William/rotateDWIv2/FreeWaterResults_WB/',int2str(PatientNumber(i)),'.FittedParams.mat'),strcat('/data/project/dti/For_William/rotateDWIv2/FreeWaterResults_WB/',int2str(PatientNumber(i)),'.NODDIroi.mat'),strcat('/data/project/dti/For_William/rotateDWIv2/brainMasks/',int2str(PatientNumber(i)),'.brainmask.nii'),strcat('/data/project/dti/For_William/rotateDWIv2/FreeWaterResults_WB/',int2str(PatientNumber(i)),'.noddi'))
+
+end
diff --git a/importPPMIlist.m b/importPPMIlist.m
new file mode 100644
index 0000000000000000000000000000000000000000..0a381a84f46ce3ef08d987cc482b06249608e593
--- /dev/null
+++ b/importPPMIlist.m
@@ -0,0 +1,45 @@
+%% Import data from text file.
+% Script for importing data from the following text file:
+%
+%    /data/project/dti/For_William/matlab/NODDI_toolbox_v1.0/rotateone.txt
+%
+% To extend the code to different selected data or a different text file,
+% generate a function instead of a script.
+
+% Auto-generated by MATLAB on 2018/05/01 11:40:45
+
+%% Initialize variables.
+filename = 'rotateone.txt';
+delimiter = ',';
+
+%% Format for each line of text:
+%   column1: double (%f)
+%	column2: text (%s)
+% For more information, see the TEXTSCAN documentation.
+formatSpec = '%f%s%[^\n\r]';
+
+%% Open the text file.
+fileID = fopen(filename,'r');
+
+%% Read columns of data according to the format.
+% This call is based on the structure of the file used to generate this
+% code. If an error occurs for a different file, try regenerating the code
+% from the Import Tool.
+dataArray = textscan(fileID, formatSpec, 'Delimiter', delimiter, 'TextType', 'string',  'ReturnOnError', false);
+
+%% Close the text file.
+fclose(fileID);
+
+%% Post processing for unimportable data.
+% No unimportable data rules were applied during the import, so no post
+% processing code is included. To generate code which works for
+% unimportable data, select unimportable cells in a file and regenerate the
+% script.
+
+%% Allocate imported array to column variable names
+VarName1 = dataArray{:, 1};
+rotate000I000R000Aashift4100S500L700P = cellstr(dataArray{:, 2});
+
+
+%% Clear temporary variables
+clearvars filename delimiter formatSpec fileID dataArray ans;
diff --git a/rotateone.txt b/rotateone.txt
new file mode 100644
index 0000000000000000000000000000000000000000..91bd27baf674ec35324aa5fae10fb87c8dc94d10
--- /dev/null
+++ b/rotateone.txt
@@ -0,0 +1,151 @@
+3775, -rotate    0.00I   0.00R   0.00A  -ashift   41.00S   5.00L  -7.00P 
+3325, -rotate    2.00I  -0.14R  -4.00A   -ashift   31.19S   8.35L -14.80P 
+3866, -rotate    3.00I   0.00R   0.00A   -ashift   42.00S  11.98L -11.63P 
+3584, -rotate   10.00I   0.00R   0.00A   -ashift   33.00S   8.24L  -7.72P 
+3816, -rotate   -3.00I   8.00R   0.00A   -ashift   49.27S   3.99L -19.43P 
+3814, -rotate   -4.00I   0.00R   0.00A   -ashift   42.00S   6.40L  -7.57P 
+3181, -rotate  0.00I 12.00R -2.00A  -ashift  8.10S -2.72L 9.00P 
+3151, -rotate  0.00I 16.00R 0.00A  -ashift  4.78S -2.00L 4.67P 
+3852, -rotate  0.00I 16.00R 0.00A  -ashift  6.00S 2.50L 14.00P 
+3355, -rotate  0.00I 27.00R 0.00A  -ashift  5.00S 0.00L 13.00P 
+3157, -rotate  0.00I 28.00R 0.00A  -ashift  5.43S 0.00L 14.36P 
+3390, -rotate  0.00I 8.00R 0.00A  -ashift  6.00S -2.50L 20.00P 
+3788, -rotate  0.00I 8.00R 0.00A  -ashift  11.00S 2.00L 7.00P 
+3830, -rotate  0.17I 12.04R 3.88A  -ashift  9.78S -0.05L -2.92P 
+3350, -rotate  -0.22I 26.07R 4.59A  -ashift  7.14S -2.61L 11.32P 
+3358, -rotate  0.25I 26.04R 2.25A  -ashift  11.59S -0.76L 12.57P 
+3368, -rotate  -0.31I 22.26R 6.69A  -ashift  7.86S -1.99L 8.14P 
+3178, -rotate  0.35I 9.99R -2.03A  -ashift  4S -2L 13P 
+3321, -rotate  0.35I 9.99R -2.03A  -ashift  1.97S 1.00L 12.99P 
+3191, -rotate  -0.42I 7.99R 4.03A  -ashift  4.01S 0.43L 14.00P 
+3800, -rotate  -0.46I 20.07R -1.03A  -ashift  7S -1.74L -5.10P 
+3377, -rotate  0.47I 16.02R 1.79A  -ashift  5.90S -3.24L 15.02P 
+3327, -rotate  0.47I 18.10R 4.68A  -ashift  9.50S 1.00L 13.97P 
+3172, -rotate  -0.55I 30.36R 5.45A  -ashift  4.90S -2.98L 8.31P 
+3316, -rotate  -0.68I 18.00R -0.05A  -ashift  7.58S -2.13L 11.25P 
+4082, -rotate  -0.77I 27.04R 1.23A  -ashift  5.06S 3.45L 12.92P 
+4067, -rotate  -0.81I 14.12R -4.65A  -ashift  8.00S 0.00L 2.00P 
+3789, -rotate  0.81I 25.06R 2.38A  -ashift  4.00S 2.42L 11.92P 
+3770, -rotate  0.82I 5.03R 2.01A  -ashift  7.04S -3.00L 16.44P 
+3352, -rotate  -0.94I 22.07R -4.43A  -ashift  6.10S -1.27L 13.96P 
+3824, -rotate  -0.95I 18.00R -0.32A  -ashift  9.00S -1.96L 2.03P 
+3166, -rotate  0.96I 15.10R 3.87A  -ashift  8S 1.19L 11.98P 
+3307, -rotate  0I 10R 0A  -ashift  9S 0L 20P 
+3161, -rotate  0I 12R 0A  -ashift  12.24S -4L 14.30P 
+3311, -rotate  0I 14R 0A  -ashift  6.65S -4L 10.13P 
+3762, -rotate  0I 16R 0A  -ashift  12S -5L 22P 
+3376, -rotate  0I 18R 0A  -ashift  8.14S -1L 9.53P 
+3107, -rotate  0I 20R 0A  -ashift  5S -4L 10P 
+3373, -rotate  0I 22R 0A  -ashift  6S 0L 9P 
+3807, -rotate  0I 22R 0A  -ashift  5S -2L 0P 
+3105, -rotate  0I 26R 0A  -ashift  1.03S 2L 7.58P 
+3563, -rotate  0I 26R 0A  -ashift  -3S -3L 2P 
+3570, -rotate  0I 26R 0A  -ashift  -3S -3L 2P 
+3855, -rotate  0I 26R 1A  -ashift  0S -0.50L 0P 
+3556, -rotate  0I 27R 0A  -ashift  9.67S -0.56L 6.46P 
+3369, -rotate  0I 28R 0A  -ashift  0S -2L 7P 
+3802, -rotate  0I 28R 0A  -ashift  -1S -2L -4P 
+3767, -rotate  0I 9R 0A  -ashift  12.21S -0.5L 11.77P 
+3309, -rotate  1.00I 14.00R 1.00A  -ashift  6.06S 2.50L 19.95P 
+3108, -rotate  1.03I 14R -0.25A  -ashift  7.58S -1.79L 12.30P 
+3853, -rotate  -1.04I 15.93R 3.29A  -ashift  -4.96S -2.59L -0.03P 
+3826, -rotate  1.08I 22R -0.4A  -ashift  10S -2.48L 1.03P 
+3554, -rotate  1.10I 26R -0.34A  -ashift  11.75S -1.50L 12.36P 
+3808, -rotate  1.11I 23.98R 0.19A  -ashift  9.08S -3.18L 5P 
+3753, -rotate  1.25I 14.09R 3.09A  -ashift  8.04S -1L 16.53P 
+3765, -rotate  -1.25I 17.94R -1.75A  -ashift  4.00S -1.58L 14.01P 
+3758, -rotate  1.27I 19.99R 2.13A  -ashift  12.67S -2L 16.81P 
+3571, -rotate  1.29I 21.17R 4.20A  -ashift  11S -1.5L 11.08P 
+3838, -rotate  -1.76I 23.02R 1.75A  -ashift  7.00S 0.98L -1.02P 
+3190, -rotate  -1.90I 17.99R 1.35A  -ashift  7.92S -3.79L 13.83P 
+3778, -rotate  1.92I 16.13R -3.43A  -ashift  9.07S -1L 1.97P 
+3756, -rotate  10.06I 15.21R 3.06A  -ashift  10S -0.5L 15.03P 
+3332, -rotate  -10.12I 33.87R -2.13A  -ashift  0.06S -2.99L 3.83P 
+3173, -rotate  13.42I 9.38R 8.65A  -ashift  6.93S 2.78L 12.83P 
+3760, -rotate  1I 25R 0A  -ashift  10.98S -3L 8.05P 
+3112, -rotate  2.00I 16.00R 0.00A  -ashift  8.03S 0.00L -0.72P 
+3828, -rotate  -2.00I 5.00R 0.00A  -ashift  9.27S -3.00L 13.30P 
+3850, -rotate  -2.03I 9.99R -1.65A  -ashift  2.05S -1.93L 2.95P 
+3768, -rotate  2.04I 11.99R -0.43A  -ashift  11S -0.58L 11.99P 
+3837, -rotate  -2.07I 24.98R -2.21A  -ashift  8.95S 2.00L 3.94P 
+3759, -rotate  2.08I 15.99R 1.43A  -ashift  9.38S -2.83L 14.33P 
+3832, -rotate  2.14I 21.13R 4.23A  -ashift  9.00S 0.00L 0.00P 
+3806, -rotate  -2.31I 18R 1.05A  -ashift  10S -3L 5P 
+3763, -rotate  2.44I 14.06R -1.63A  -ashift  10.44S -2L 16.23P 
+3831, -rotate  2.45I 27.17R 2.45A  -ashift  10.25S 3.99L 3.85P 
+3310, -rotate  -2.47I 35.97R 1.45A  -ashift  7.36S -3.90L -3.07P 
+3169, -rotate  -2.49I 16.05R 2.51A  -ashift  -0.05S -2.58L 12.03P 
+3823, -rotate  -2.50I 14.94R -0.80A  -ashift  4.76S -4.71L 7.16P 
+3805, -rotate  2.53I 14.03R 1.81A  -ashift  10.00S 0.00L 4.00P 
+3184, -rotate  -2.60I 12.03R -2.83A  -ashift  1.22S -3.27L 16.84P 
+4080, -rotate  2.74I 22.16R 4.39A  -ashift  7.32S 1.00L 9.54P 
+3833, -rotate  2.91I 11.10R -2.56A  -ashift  4.03S -1.00L -0.02P 
+3375, -rotate  2.93I 26.10R 4.79A  -ashift  4.08S -4.50L 13P 
+4004, -rotate  -2.98I 11R -1.19A  -ashift  -2.17S 6.06L 5.65P 
+4083, -rotate  2.98I 23.04R 2.09A  -ashift  5.66S 1.37L 9.12P 
+3320, -rotate  2I 16R 0A  -ashift  8.54S -1.00L 12.64P 
+3308, -rotate  2I 24R 0A  -ashift  13.53S -3.5L 12.59P 
+3354, -rotate  2I 26R 2A  -ashift  9.84S -3.34L 14.09P 
+3392, -rotate  3.00I 16.00R 1.00A  -ashift  6.02S 1.00L 10.00P 
+3769, -rotate  -3.00I 17.00R 0.00A  -ashift  2.70S -1.00L 18.07P 
+3118, -rotate  3.02I 25.98R 4.22A  -ashift  4.22S -2.15L 11.30P 
+3835, -rotate  -3.09I 19.87R 3.19A  -ashift  7.97S 2.00L 0.34P 
+3389, -rotate  3.15I 29.86R -4.04A  -ashift  11.00S -0.69L 12.99P 
+3365, -rotate  3.22I 28.07R 3.52A  -ashift  2.45S -1L 14.13P 
+3558, -rotate  -3.25I 16.01R 1.75A  -ashift  -1.03S -0.88L 6.01P 
+3555, -rotate  -3.28I 23.97R -1.33A  -ashift  7S 0L 18.95P 
+3559, -rotate  -3.36I 20R 1.06A  -ashift  0.72S -4L 8.03P 
+3551, -rotate  3.37I 26.69R 0.47A  -ashift  -2.01S -0.14L -3.99P 
+3366, -rotate  3.46I 29.85R 1.74A  -ashift  2.14S 1.99L 10.83P 
+3779, -rotate  3.56I 10.98R -0.62A  -ashift  9.60S -0.6L 23.10P 
+3776, -rotate  3.73I 15.00R 1.04A  -ashift  10.95S -2.50L 5.99P 
+3587, -rotate  3.79I 23.88R -1.74A  -ashift  0.00S 2.00L 12.03P 
+3168, -rotate  -3.84I 3R -3A  -ashift  5.47S -2L 12.20P 
+3165, -rotate  3I 14.10R 4.12A  -ashift  1S 0L 12P 
+3125, -rotate  3I 18R 0A  -ashift  7.44S 2L 16.27P 
+3361, -rotate  3I 19R 0A  -ashift  5.42S 0L 13.82P 
+3593, -rotate  4.00I 22.00R 1.00A  -ashift  5.82S -1.60L 8.14P 
+3174, -rotate  4.15I 13.16R 3.41A  -ashift  7.05S -0.54L 18.32P 
+3305, -rotate  4.19I 12.01R -0.81A  -ashift  6.58S 0.80L 11.32P 
+3757, -rotate  4.19I 24.05R 1.11A  -ashift  6.39S -1.36L 8.36P 
+3834, -rotate  4.24I 27.07R 5.42A  -ashift  8.09S -0.07L 4.87P 
+3817, -rotate  4.36I 11.98R 3.07A  -ashift  11.03S 0.50L 4.01P 
+3811, -rotate  -4.41I 24.93R -2.14A  -ashift  4.14S -1.99L 3.86P 
+3592, -rotate  4.43I 22.07R 1.98A  -ashift  4.71S -0.78L 17.08P 
+3119, -rotate  -4.45I 24R 1.09A  -ashift  13S -0.5L 4P 
+3818, -rotate  -4.57I 15.99R 2.08A  -ashift  1.93S -3L 1.98P 
+3104, -rotate  4.66I 27.17R 1.47A  -ashift  -0.33S 0.22L 8.45P 
+3764, -rotate  4.72I 22R 1.75A  -ashift  11S -1.33L 10.02P 
+4010, -rotate  4.74I 8.06R 1.74A  -ashift  2.29S 6.61L 3.43P 
+3825, -rotate  4.86I 16.19R -3.12A  -ashift  10.93S -2L 3.21P 
+3809, -rotate  -4I 10R 0A  -ashift  3.75S -2L 7.14P 
+3120, -rotate  -4I 14R 0A  -ashift  5.16S 1L 24.09P 
+3829, -rotate  4I 18R 0A  -ashift  12.85S 0L 4.42P 
+3812, -rotate  4I 22R 0A  -ashift  4S -1.5L 0.14P 
+3815, -rotate  5.00I 24.00R 0.00A  -ashift  2.99S -2.50L 4.03P 
+3557, -rotate  5.02I 14.38R 3.86A  -ashift  5S 0.71L 11.99P 
+3175, -rotate  5.26I 6.96R 6.04A  -ashift  3.16S 0L 8.93P 
+3777, -rotate  5.41I 23.07R 3.90A  -ashift  6.00S 0.00L 18.00P 
+4024, -rotate  -5.43I 15.99R -2.08A  -ashift  -1.38S -9.94L 13.09P 
+3771, -rotate  5.53I 22.05R 1.35A  -ashift  6.50S 0.52L 15.99P 
+3102, -rotate  5.64I 31.98R 3.25A  -ashift  2.96S 3.45L 11.72P 
+3575, -rotate  5I 34R 0A  -ashift  -2.88S -5L 2.03P 
+3591, -rotate  6.08I 15.99R -0.57A  -ashift  3.00S -1.27L 21.02P 
+3380, -rotate  6.33I 23.18R 6.27A  -ashift  4.86S -2.17L 9P 
+3154, -rotate  6.41I 16.73R 5.20A  -ashift  2.47S -3.99L 15.30P 
+3116, -rotate  6.55I 18.05R -1.45A  -ashift  2.93S 2.58L 12.04P 
+3367, -rotate  6.59I 24.18R 6.59A  -ashift  8.56S -4.60L 12.28P 
+3171, -rotate  6.5I 19R 0A  -ashift  7.79S -3.5L 12.14P 
+3353, -rotate  -6.62I 17.93R 5.26A  -ashift  5.29S -4.00L 11.41P 
+3819, -rotate  -6.65I 17.99R 2.10A  -ashift  7.29S -2L 6.28P 
+3318, -rotate  -6.67I 20.08R -3.53A  -ashift  11.70S -3.38L 11.1P 
+3574, -rotate  6I 12R 0A  -ashift  2S 4L 7P 
+4029, -rotate  -6I 19R 0A  -ashift  2.69S -7L 18.05P 
+3787, -rotate  7.03I 14.00R -0.25A  -ashift  4.00S -0.95L 3.00P 
+3123, -rotate  -7.19I 27.40R -9.36A  -ashift  0.64S -3.58L 8.34P 
+3780, -rotate  7.25I 16.01R -0.75A  -ashift  13.97S 1.70L 17.02P 
+3372, -rotate  7.27I 25.04R 1.27A  -ashift  4S 0.28L 8P 
+3111, -rotate  8.06I 20.28R 5.07A  -ashift  13.89S -3.98L 20.58P 
+3552, -rotate  8.15I 18.11R 5.66A  -ashift  7.00S 0.52L 15.99P 
+3359, -rotate  9.44I 25.09R 5.01A  -ashift  8.89S -3.10L 17.15P 
+3585, -rotate  9.78I 17.99R 0.40A  -ashift  5.86S 6.02L 15.94P