Print

Print


Commit in java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl on MAIN
GblData.java+289added 919
GblPoint.java+581-13918 -> 919
GblTrajectory.java+1292-5918 -> 919
HpsGblFitter.java+307-326918 -> 919
matrix/BorderedBandMatrix.java+360added 919
      /EigenvalueDecomposition.java+959added 919
      /LUDecomposition.java+310added 919
      /Matrix.java+1553added 919
      /QRDecomposition.java+218added 919
      /SymMatrix.java+66added 919
      /VMatrix.java+201added 919
      /VSymMatrix.java+303added 919
      /VVector.java+129added 919
      /Vector.java+337added 919
+6905-344
11 added + 3 modified, total 14 files
First pass at the java port of GBL.
Work in progress.

java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl
GblData.java added at 919
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/GblData.java	                        (rev 0)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/GblData.java	2014-08-28 15:31:06 UTC (rev 919)
@@ -0,0 +1,289 @@
+package org.hps.recon.tracking.gbl;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.hps.recon.tracking.gbl.matrix.VVector;
+
+
+/**
+ *
+ * @author Norman A Graf
+ *
+ * @version $Id:
+ */
+public class GblData
+{
+
+    int theLabel; ///< Label (of measurements point)
+    double theValue; ///< Value (residual)
+    double thePrecision; ///< Precision (1/sigma**2)
+    double theDownWeight; ///< Down-weighting factor (0-1)
+    double thePrediction; ///< Prediction from fit
+    List<Integer> theParameters = new ArrayList<Integer>(); ///< List of fit parameters (with non zero derivatives)
+    List<Double> theDerivatives = new ArrayList<Double>(); ///< List of derivatives for fit
+    List<Integer> globalLabels = new ArrayList<Integer>(); ///< Labels for global derivatives
+    List<Double> globalDerivatives = new ArrayList<Double>(); ///< Global derivatives
+
+/// Create data block.
+    /**
+     * \param [in] aLabel Label of corresponding point \param [in] aValue Value
+     * of (scalar) measurement \param [in] aPrec Precision of (scalar)
+     * measurement
+     */
+    GblData(int aLabel, double aValue, double aPrec)
+    {
+
+        theLabel = aLabel;
+        theValue = aValue;
+        thePrecision = aPrec;
+        theDownWeight = 1.;
+        thePrediction = 0.;
+    }
+
+///// Add derivatives from measurement.
+///**
+// * Add (non-zero) derivatives to data block. Fill list of labels of used fit parameters.
+// * \param [in] iRow Row index (0-4) in up to 5D measurement
+// * \param [in] labDer Labels for derivatives
+// * \param [in] matDer Derivatives (matrix) 'measurement vs track fit parameters'
+// * \param [in] iOff Offset for row index for additional parameters
+// * \param [in] derLocal Derivatives (matrix) for additional local parameters
+// * \param [in] labGlobal Labels for additional global (MP-II) parameters
+// * \param [in] derGlobal Derivatives (matrix) for additional global (MP-II) parameters
+// * \param [in] extOff Offset for external parameters
+// * \param [in] extDer Derivatives for external Parameters
+// */
+//void addDerivatives(unsigned int iRow,
+//		const std::vector<unsigned int> &labDer, const SMatrix55 &matDer,
+//		unsigned int iOff, const TMatrixD &derLocal,
+//		const std::vector<int> &labGlobal, const TMatrixD &derGlobal,
+//		unsigned int extOff, const TMatrixD &extDer) {
+//
+//	unsigned int nParMax = 5 + derLocal.GetNcols() + extDer.GetNcols();
+//	theParameters.reserve(nParMax); // have to be sorted
+//	theDerivatives.reserve(nParMax);
+//
+//	for (int i = 0; i < derLocal.GetNcols(); ++i) // local derivatives
+//			{
+//		if (derLocal(iRow - iOff, i)) {
+//			theParameters.push_back(i + 1);
+//			theDerivatives.push_back(derLocal(iRow - iOff, i));
+//		}
+//	}
+//
+//	for (int i = 0; i < extDer.GetNcols(); ++i) // external derivatives
+//			{
+//		if (extDer(iRow - iOff, i)) {
+//			theParameters.push_back(extOff + i + 1);
+//			theDerivatives.push_back(extDer(iRow - iOff, i));
+//		}
+//	}
+//
+//	for (unsigned int i = 0; i < 5; ++i) // curvature, offset derivatives
+//			{
+//		if (labDer[i] && matDer(iRow, i)) {
+//			theParameters.push_back(labDer[i]);
+//			theDerivatives.push_back(matDer(iRow, i));
+//		}
+//	}
+//
+//	globalLabels = labGlobal;
+//	for (int i = 0; i < derGlobal.GetNcols(); ++i) // global derivatives
+//		globalDerivatives.push_back(derGlobal(iRow - iOff, i));
+//}
+//
+///// Add derivatives from kink.
+///**
+// * Add (non-zero) derivatives to data block. Fill list of labels of used fit parameters.
+// * \param [in] iRow Row index (0-1) in 2D kink
+// * \param [in] labDer Labels for derivatives
+// * \param [in] matDer Derivatives (matrix) 'kink vs track fit parameters'
+// * \param [in] extOff Offset for external parameters
+// * \param [in] extDer Derivatives for external Parameters
+// */
+//void addDerivatives(unsigned int iRow,
+//		const std::vector<unsigned int> &labDer, const SMatrix27 &matDer,
+//		unsigned int extOff, const TMatrixD &extDer) {
+//
+//	unsigned int nParMax = 7 + extDer.GetNcols();
+//	theParameters.reserve(nParMax); // have to be sorted
+//	theDerivatives.reserve(nParMax);
+//
+//	for (int i = 0; i < extDer.GetNcols(); ++i) // external derivatives
+//			{
+//		if (extDer(iRow, i)) {
+//			theParameters.push_back(extOff + i + 1);
+//			theDerivatives.push_back(extDer(iRow, i));
+//		}
+//	}
+//
+//	for (unsigned int i = 0; i < 7; ++i) // curvature, offset derivatives
+//			{
+//		if (labDer[i] && matDer(iRow, i)) {
+//			theParameters.push_back(labDer[i]);
+//			theDerivatives.push_back(matDer(iRow, i));
+//		}
+//	}
+//}
+//
+///// Add derivatives from external seed.
+///**
+// * Add (non-zero) derivatives to data block. Fill list of labels of used fit parameters.
+// * \param [in] index Labels for derivatives
+// * \param [in] derivatives Derivatives (vector)
+// */
+//void addDerivatives(const std::vector<unsigned int> &index,
+//		const std::vector<double> &derivatives) {
+//	for (unsigned int i = 0; i < derivatives.size(); ++i) // any derivatives
+//			{
+//		if (derivatives[i]) {
+//			theParameters.push_back(index[i]);
+//			theDerivatives.push_back(derivatives[i]);
+//		}
+//	}
+//}
+/// Calculate prediction for data from fit (by GblTrajectory::fit).
+    void setPrediction(VVector aVector)
+    {
+
+        thePrediction = 0.;
+        for (int i = 0; i < theDerivatives.size(); ++i) {
+            thePrediction += theDerivatives.get(i) * aVector.get(theParameters.get(i) - 1);
+        }
+    }
+
+///// Outlier down weighting with M-estimators (by GblTrajectory::fit).
+///**
+// * \param [in] aMethod M-estimator (1: Tukey, 2:Huber, 3:Cauchy)
+// */
+//double setDownWeighting(unsigned int aMethod) {
+//
+//	double aWeight = 1.;
+//	double scaledResidual = fabs(theValue - thePrediction) * sqrt(thePrecision);
+//	if (aMethod == 1) // Tukey
+//			{
+//		if (scaledResidual < 4.6851) {
+//			aWeight = (1.0 - 0.045558 * scaledResidual * scaledResidual);
+//			aWeight *= aWeight;
+//		} else {
+//			aWeight = 0.;
+//		}
+//	} else if (aMethod == 2) //Huber
+//			{
+//		if (scaledResidual >= 1.345) {
+//			aWeight = 1.345 / scaledResidual;
+//		}
+//	} else if (aMethod == 3) //Cauchy
+//			{
+//		aWeight = 1.0 / (1.0 + (scaledResidual * scaledResidual / 5.6877));
+//	}
+//	theDownWeight = aWeight;
+//	return aWeight;
+//}
+//
+/// Calculate Chi2 contribution.
+    /**
+     * \return (down-weighted) Chi2
+     */
+    double getChi2()
+    {
+        double aDiff = theValue - thePrediction;
+        return aDiff * aDiff * thePrecision * theDownWeight;
+    }
+
+///// Print data block.
+//void printData() const {
+//
+//	std::cout << " measurement at label " << theLabel << ": " << theValue
+//			<< ", " << thePrecision << std::endl;
+//	std::cout << "  param " << theParameters.size() << ":";
+//	for (unsigned int i = 0; i < theParameters.size(); ++i)
+//		std::cout << " " << theParameters[i];
+//	}
+//	std::cout << std::endl;
+//	std::cout << "  deriv " << theDerivatives.size() << ":";
+//	for (unsigned int i = 0; i < theDerivatives.size(); ++i) {
+//		std::cout << " " << theDerivatives[i];
+//	}
+//	std::cout << std::endl;
+//}
+//
+    public String toString()
+    {
+        StringBuffer sb = new StringBuffer(" measurement at label " + theLabel + ": " + theValue + ", " + thePrecision + "\n");
+        sb.append("  param " + theParameters.size() + ":");
+        for (int i = 0; i < theParameters.size(); ++i) {
+            sb.append(" " + theParameters.get(i));
+        }
+        sb.append("\n");
+        return sb.toString();
+    }
+
+/// Get Data for local fit.
+    /**
+     * \param [out] aValue Value \param [out] aWeight Weight \param [out]
+     * indLocal List of labels of used (local) fit parameters \param [out]
+     * derLocal List of derivatives for used (local) fit parameters
+     */
+    void getLocalData(double[] retVal, List<Integer> indLocal, List<Double> derLocal)
+    {
+
+        retVal[0] = theValue;
+        retVal[1] = thePrecision * theDownWeight;
+        indLocal = theParameters;
+        derLocal = theDerivatives;
+    }
+
+    void getLocalData(double[] retVal, int[] indLocal, double[] derLocal)
+    {
+
+        retVal[0] = theValue;
+        retVal[1] = thePrecision * theDownWeight;
+        indLocal = new int[theParameters.size()];
+        derLocal = new double[theParameters.size()];
+        for (int i = 0; i < theParameters.size(); ++i) {
+            indLocal[i] = theParameters.get(i);
+            derLocal[i] = theDerivatives.get(i);
+        }
+
+    }
+
+//
+///// Get all Data for MP-II binary record.
+///**
+// * \param [out] fValue Value
+// * \param [out] fErr Error
+// * \param [out] indLocal List of labels of local parameters
+// * \param [out] derLocal List of derivatives for local parameters
+// * \param [out] labGlobal List of labels of global parameters
+// * \param [out] derGlobal List of derivatives for global parameters
+// */
+//void getAllData(float &fValue, float &fErr,
+//		std::vector<unsigned int>* &indLocal, std::vector<double>* &derLocal,
+//		std::vector<int>* &labGlobal, std::vector<double>* &derGlobal) {
+//	fValue = theValue;
+//	fErr = 1.0 / sqrt(thePrecision);
+//	indLocal = &theParameters;
+//	derLocal = &theDerivatives;
+//	labGlobal = &globalLabels;
+//	derGlobal = &globalDerivatives;
+//}
+//
+///// Get data for residual (and errors).
+///**
+// * \param [out] aResidual Measurement-Prediction
+// * \param [out] aVariance Variance (of measurement)
+// * \param [out] aDownWeight Down-weighting factor
+// * \param [out] indLocal List of labels of used (local) fit parameters
+// * \param [out] derLocal List of derivatives for used (local) fit parameters
+// */
+//void getResidual(double &aResidual, double &aVariance,
+//		double &aDownWeight, std::vector<unsigned int>* &indLocal,
+//		std::vector<double>* &derLocal) {
+//	aResidual = theValue - thePrediction;
+//	aVariance = 1.0 / thePrecision;
+//	aDownWeight = theDownWeight;
+//	indLocal = &theParameters;
+//	derLocal = &theDerivatives;
+//}
+}

java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl
GblPoint.java 918 -> 919
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/GblPoint.java	2014-08-28 08:14:53 UTC (rev 918)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/GblPoint.java	2014-08-28 15:31:06 UTC (rev 919)
@@ -1,22 +1,590 @@
 package org.hps.recon.tracking.gbl;
 
-import hep.physics.matrix.BasicMatrix;
-import hep.physics.matrix.Matrix;
+import java.util.ArrayList;
+import java.util.List;
+import org.hps.recon.tracking.gbl.matrix.EigenvalueDecomposition;
+import org.hps.recon.tracking.gbl.matrix.Matrix;
+import org.hps.recon.tracking.gbl.matrix.SymMatrix;
+import org.hps.recon.tracking.gbl.matrix.Vector;
 
+/**
+ *
+ * @author phansson
+ * @author Norman A Graf
+ *
+ * @version $Id:
+ */
 public class GblPoint {
 
-	public GblPoint(BasicMatrix jacPointToPoint) {
-		// TODO Auto-generated constructor stub
-	}
+    public GblPoint(hep.physics.matrix.BasicMatrix jacPointToPoint) {
+        theLabel = 0;
+        theOffset = 0;
+        measDim = 0;
+        transFlag = false;
+        //measTransformation() 
+        scatFlag = false;
+        //localDerivatives()
+        //globalLabels()
+        //globalDerivatives()
 
-	public void addMeasurement(Matrix proL2m, BasicMatrix meas, BasicMatrix measPrec) {
-		// TODO Auto-generated method stub
-		
-	}
+        for (int i = 0; i < 5; ++i) {
+            for (int j = 0; j < 5; ++j) {
+                p2pJacobian.set(i, j, jacPointToPoint.e(i, j));
+            }
+        }
+    }
 
-	public void addScatterer(BasicMatrix scat, BasicMatrix scatPrec) {
-		// TODO Auto-generated method stub
-		
-	}
+    public void addMeasurement(hep.physics.matrix.Matrix proL2m, hep.physics.matrix.BasicMatrix meas, hep.physics.matrix.BasicMatrix measPrec) {
 
+        int ncols = proL2m.getNColumns();
+        int nrows = proL2m.getNRows();
+        System.out.println("proL2m has "+nrows+" rows and "+ ncols+ "columns");
+        Matrix a = new Matrix(nrows, ncols);
+        for(int i=0; i<nrows; ++i)
+        {
+            for(int j=0; j<ncols; ++j)
+            {
+                a.set(i,j,proL2m.e(i, j));
+            }
+        }
+        System.out.println("GblPoint add matrix: ");
+        a.print(10, 6);
+        
+        
+        
+        int measnrows = meas.getNRows();
+        int measncols = meas.getNColumns();
+        System.out.println("meas has "+measnrows+" rows and "+measncols+" columns");
+        
+        Vector measvec = new Vector(measncols);
+        for(int i=0; i<measnrows; ++i)
+        {
+            measvec.set(i, meas.e(0, i));
+        }
+        System.out.println("GblPoint add meas: ");
+        measvec.print(10, 6);
+        
+        
+        int measPrecnrows = measPrec.getNRows();
+        int measPrecncols = measPrec.getNColumns();
+        
+        System.out.println("measPrec has "+measPrecnrows+" rows and "+measPrecncols+" columns");
+        Vector measPrecvec = new Vector(measPrecncols);
+        for(int i=0; i<measPrecnrows; ++i)
+        {
+            measPrecvec.set(i, measPrec.e(0, i));
+        }
+        System.out.println("GblPoint add measPrec: ");
+        measPrecvec.print(10, 6); 
+        
+        addMeasurement(a, measvec, measPrecvec, 0.);
+    }
+
+    public void addScatterer(hep.physics.matrix.BasicMatrix scat, hep.physics.matrix.BasicMatrix scatPrec) {
+        // TODO Auto-generated method stub
+
+    }
+
+    private int theLabel; ///< Label identifying point
+    private int theOffset; ///< Offset number at point if not negative (else interpolation needed)
+    private Matrix p2pJacobian = new SymMatrix(5); ///< Point-to-point jacobian from previous point
+    private Matrix prevJacobian = new SymMatrix(5); ///< Jacobian to previous scatterer (or first measurement)
+    private Matrix nextJacobian = new SymMatrix(5); ///< Jacobian to next scatterer (or last measurement)
+    private int measDim; ///< Dimension of measurement (1-5), 0 indicates absence of measurement
+    private SymMatrix measProjection = new SymMatrix(5); ///< Projection from measurement to local system
+    private Vector measResiduals = new Vector(5); ///< Measurement residuals
+    private Vector measPrecision = new Vector(5); ///< Measurement precision (diagonal of inverse covariance matrix)
+    private boolean transFlag; ///< Transformation exists?
+    private Matrix measTransformation; ///< Transformation of diagonalization (of meas. precision matrix)
+    private boolean scatFlag; ///< Scatterer present?
+    private SymMatrix scatTransformation = new SymMatrix(2); ///< Transformation of diagonalization (of scat. precision matrix)
+    private Vector scatResiduals = new Vector(2); ///< Scattering residuals (initial kinks if iterating)
+    private Vector scatPrecision = new Vector(2); ///< Scattering precision (diagonal of inverse covariance matrix)
+    private Matrix localDerivatives = new Matrix(0, 0); ///< Derivatives of measurement vs additional local (fit) parameters
+    private List<Integer> globalLabels = new ArrayList<Integer>(); ///< Labels of global (MP-II) derivatives
+    private Matrix globalDerivatives = new Matrix(0, 0); ///< Derivatives of measurement vs additional global (MP-II) parameters
+
+/// Create a point.
+    /**
+     * Create point on (initial) trajectory. Needs transformation jacobian from
+     * previous point. \param [in] aJacobian Transformation jacobian from
+     * previous point
+     */
+    public GblPoint(Matrix aJacobian) {
+
+        theLabel = 0;
+        theOffset = 0;
+        measDim = 0;
+        transFlag = false;
+        //measTransformation() 
+        scatFlag = false;
+        //localDerivatives()
+        //globalLabels()
+        //globalDerivatives()
+
+        for (int i = 0; i < 5; ++i) {
+            for (int j = 0; j < 5; ++j) {
+                p2pJacobian.set(i, j, aJacobian.get(i, j));
+            }
+        }
+    }
+
+    public GblPoint(SymMatrix aJacobian) {
+        theLabel = 0;
+        theOffset = 0;
+        p2pJacobian = new SymMatrix(aJacobian);
+        measDim = 0;
+        transFlag = false;
+        //measTransformation() 
+        scatFlag = false;
+        //localDerivatives() 
+        //globalLabels() 
+        //globalDerivatives()
+
+    }
+
+/// Add a measurement to a point.
+    /**
+     * Add measurement (in meas. system) with diagonal precision (inverse
+     * covariance) matrix. ((up to) 2D: position, 4D: slope+position, 5D:
+     * curvature+slope+position) \param [in] aProjection Projection from local
+     * to measurement system \param [in] aResiduals Measurement residuals \param
+     * [in] aPrecision Measurement precision (diagonal) \param [in] minPrecision
+     * Minimal precision to accept measurement
+     */
+    public void addMeasurement(Matrix aProjection,
+            Vector aResiduals, Vector aPrecision,
+            double minPrecision) {
+        measDim = aResiduals.getRowDimension();
+        int iOff = 5 - measDim;
+        for (int i = 0; i < measDim; ++i) {
+            measResiduals.set(iOff + i, aResiduals.get(i));
+            measPrecision.set(iOff + i, (aPrecision.get(i) >= minPrecision ? aPrecision.get(i) : 0.));
+            for (int j = 0; j < measDim; ++j) {
+                measProjection.set(iOff + i, iOff + j, aProjection.get(i, j));
+            }
+        }
+    }
+/// Add a measurement to a point.
+
+    /**
+     * Add measurement (in meas. system) with arbitrary precision (inverse
+     * covariance) matrix. Will be diagonalized. ((up to) 2D: position, 4D:
+     * slope+position, 5D: curvature+slope+position) \param [in] aProjection
+     * Projection from local to measurement system \param [in] aResiduals
+     * Measurement residuals \param [in] aPrecision Measurement precision
+     * (matrix) \param [in] minPrecision Minimal precision to accept measurement
+     */
+    public void addMeasurement(Matrix aProjection,
+            Vector aResiduals, SymMatrix aPrecision,
+            double minPrecision) {
+        measDim = aResiduals.getRowDimension();
+        EigenvalueDecomposition measEigen = new EigenvalueDecomposition(aPrecision);
+        measTransformation.ResizeTo(measDim, measDim);
+        measTransformation = measEigen.getV();
+        measTransformation.transposeInPlace();
+        transFlag = true;
+        Vector transResiduals = measTransformation.times(aResiduals);
+        Vector transPrecision = new Vector(measEigen.getRealEigenvalues());
+        Matrix transProjection = measTransformation.times(aProjection);
+        int iOff = 5 - measDim;
+        for (int i = 0; i < measDim; ++i) {
+            measResiduals.set(iOff + i, transResiduals.get(i));
+            measPrecision.set(iOff + i, (transPrecision.get(i) >= minPrecision ? transPrecision.get(i) : 0.));
+            for (int j = 0; j < measDim; ++j) {
+                measProjection.set(iOff + i, iOff + j, transProjection.get(i, j));
+            }
+        }
+    }
+
+/// Add a measurement to a point.
+    /**
+     * Add measurement in local system with diagonal precision (inverse
+     * covariance) matrix. ((up to) 2D: position, 4D: slope+position, 5D:
+     * curvature+slope+position) \param [in] aResiduals Measurement residuals
+     * \param [in] aPrecision Measurement precision (diagonal) \param [in]
+     * minPrecision Minimal precision to accept measurement
+     */
+    public void addMeasurement(Vector aResiduals,
+            Vector aPrecision, double minPrecision) {
+        measDim = aResiduals.getRowDimension();
+        int iOff = 5 - measDim;
+        for (int i = 0; i < measDim; ++i) {
+            measResiduals.set(iOff + i, aResiduals.get(i));
+            measPrecision.set(iOff + i,
+                    aPrecision.get(i) >= minPrecision ? aPrecision.get(i) : 0.);
+        }
+        measProjection.setToIdentity();
+    }
+
+/// Add a measurement to a point.
+    /**
+     * Add measurement in local system with arbitrary precision (inverse
+     * covariance) matrix. Will be diagonalized. ((up to) 2D: position, 4D:
+     * slope+position, 5D: curvature+slope+position) \param [in] aResiduals
+     * Measurement residuals \param [in] aPrecision Measurement precision
+     * (matrix) \param [in] minPrecision Minimal precision to accept measurement
+     */
+    public void addMeasurement(Vector aResiduals,
+            SymMatrix aPrecision, double minPrecision) {
+        measDim = aResiduals.getRowDimension();
+        EigenvalueDecomposition measEigen = new EigenvalueDecomposition(aPrecision);
+        measTransformation.ResizeTo(measDim, measDim);
+        measTransformation = measEigen.getV();
+        measTransformation.transposeInPlace();
+        transFlag = true;
+        Vector transResiduals = measTransformation.times(aResiduals);
+        Vector transPrecision = new Vector(measEigen.getRealEigenvalues());
+        int iOff = 5 - measDim;
+        for (int i = 0; i < measDim; ++i) {
+            measResiduals.set(iOff + i, transResiduals.get(i));
+            measPrecision.set(iOff + i, (transPrecision.get(i)) >= minPrecision ? transPrecision.get(i) : 0.);
+            for (int j = 0; j < measDim; ++j) {
+                measProjection.set(iOff + i, iOff + j, measTransformation.get(i, j));
+            }
+        }
+    }
+
+/// Check for measurement at a point.
+    /**
+     * Get dimension of measurement (0 = none). \return measurement dimension
+     */
+    int hasMeasurement() {
+        return measDim;
+    }
+
+/// Retrieve measurement of a point.
+    /**
+     * \param [out] aProjection Projection from (diagonalized) measurement to
+     * local system \param [out] aResiduals Measurement residuals \param [out]
+     * aPrecision Measurement precision (diagonal)
+     */
+    public void getMeasurement(SymMatrix aProjection, Vector aResiduals,
+            Vector aPrecision) {
+        aProjection = measProjection;
+        aResiduals = measResiduals;
+        aPrecision = measPrecision;
+    }
+
+/// Get measurement transformation (from diagonalization).
+    /**
+     * \param [out] aTransformation Transformation matrix
+     */
+    public void getMeasTransformation(Matrix aTransformation) {
+        aTransformation.ResizeTo(measDim, measDim);
+        if (transFlag) {
+            aTransformation = measTransformation;
+        } else {
+            aTransformation.UnitMatrix();
+        }
+    }
+
+/// Add a (thin) scatterer to a point.
+    /**
+     * Add scatterer with diagonal precision (inverse covariance) matrix.
+     * Changes local track direction.
+     *
+     * \param [in] aResiduals Scatterer residuals \param [in] aPrecision
+     * Scatterer precision (diagonal of inverse covariance matrix)
+     */
+    public void addScatterer(Vector aResiduals,
+            Vector aPrecision) {
+        scatFlag = true;
+        scatResiduals.set(0, aResiduals.get(0));
+        scatResiduals.set(1, aResiduals.get(1));
+        scatPrecision.set(0, aPrecision.get(0));
+        scatPrecision.set(1, aPrecision.get(1));
+        scatTransformation.setToIdentity();
+    }
+
+/// Add a (thin) scatterer to a point.
+    /**
+     * Add scatterer with arbitrary precision (inverse covariance) matrix. Will
+     * be diagonalized. Changes local track direction.
+     *
+     * The precision matrix for the local slopes is defined by the angular
+     * scattering error theta_0 and the scalar products c_1, c_2 of the offset
+     * directions in the local frame with the track direction:
+     *
+     * (1 - c_1*c_1 - c_2*c_2) | 1 - c_1*c_1 - c_1*c_2 | P =
+     * ~~~~~~~~~~~~~~~~~~~~~~~ * | | theta_0*theta_0 | - c_1*c_2 1 - c_2*c_2 |
+     *
+     * \param [in] aResiduals Scatterer residuals \param [in] aPrecision
+     * Scatterer precision (matrix)
+     */
+    public void addScatterer(Vector aResiduals,
+            SymMatrix aPrecision) {
+        scatFlag = true;
+        EigenvalueDecomposition scatEigen = new EigenvalueDecomposition(aPrecision);
+        Matrix aTransformation = scatEigen.getEigenVectors();
+        aTransformation.transposeInPlace();
+        Vector transResiduals = aTransformation.times(aResiduals);
+        Vector transPrecision = new Vector(scatEigen.getRealEigenvalues());
+        for (int i = 0; i < 2; ++i) {
+            scatResiduals.set(i, transResiduals.get(i));
+            scatPrecision.set(i, transPrecision.get(i));
+            for (int j = 0; j < 2; ++j) {
+                scatTransformation.set(i, j, aTransformation.get(i, j));
+            }
+        }
+    }
+
+/// Check for scatterer at a point.
+    boolean hasScatterer() {
+        return scatFlag;
+    }
+
+/// Retrieve scatterer of a point.
+    /**
+     * \param [out] aTransformation Scatterer transformation from
+     * diagonalization \param [out] aResiduals Scatterer residuals \param [out]
+     * aPrecision Scatterer precision (diagonal)
+     */
+    public void getScatterer(SymMatrix aTransformation, Vector aResiduals,
+            Vector aPrecision) {
+        aTransformation = scatTransformation;
+        aResiduals = scatResiduals;
+        aPrecision = scatPrecision;
+    }
+
+/// Get scatterer transformation (from diagonalization).
+    /**
+     * \param [out] aTransformation Transformation matrix
+     */
+    public void getScatTransformation(Matrix aTransformation) {
+        aTransformation.ResizeTo(2, 2);
+        if (scatFlag) {
+            for (int i = 0; i < 2; ++i) {
+                for (int j = 0; j < 2; ++j) {
+                    aTransformation.set(i, j, scatTransformation.get(i, j));
+                }
+            }
+        } else {
+            aTransformation.UnitMatrix();
+        }
+    }
+
+/// Add local derivatives to a point.
+    /**
+     * Point needs to have a measurement. \param [in] aDerivatives Local
+     * derivatives (matrix)
+     */
+    public void addLocals(Matrix aDerivatives) {
+        if (measDim != 0) {
+            localDerivatives.ResizeTo(aDerivatives.getRowDimension(), aDerivatives.getColumnDimension());
+            if (transFlag) {
+                localDerivatives = measTransformation.times(aDerivatives);
+            } else {
+                localDerivatives = aDerivatives;
+            }
+        }
+    }
+
+/// Retrieve number of local derivatives from a point.
+    int getNumLocals() {
+        return localDerivatives.getColumnDimension();
+    }
+
+/// Retrieve local derivatives from a point.
+    Matrix getLocalDerivatives() {
+        return localDerivatives;
+    }
+
+/// Add global derivatives to a point.
+    /**
+     * Point needs to have a measurement. \param [in] aLabels Global derivatives
+     * labels \param [in] aDerivatives Global derivatives (matrix)
+     */
+    public void addGlobals(List<Integer> aLabels,
+            Matrix aDerivatives) {
+        if (measDim != 0) {
+            globalLabels = aLabels;
+            globalDerivatives.ResizeTo(aDerivatives.getRowDimension(), aDerivatives.getColumnDimension());
+            if (transFlag) {
+                globalDerivatives = measTransformation.times(aDerivatives);
+            } else {
+                globalDerivatives = aDerivatives;
+            }
+
+        }
+    }
+
+/// Retrieve number of global derivatives from a point.
+    int getNumGlobals() {
+        return globalDerivatives.getColumnDimension();
+    }
+
+/// Retrieve global derivatives labels from a point.
+    List<Integer> getGlobalLabels() {
+        return globalLabels;
+    }
+
+/// Retrieve global derivatives from a point.
+    Matrix getGlobalDerivatives() {
+        return globalDerivatives;
+    }
+
+/// Define label of point (by GBLTrajectory constructor)
+    /**
+     * \param [in] aLabel Label identifying point
+     */
+    public void setLabel(int aLabel) {
+        theLabel = aLabel;
+    }
+
+/// Retrieve label of point
+    int getLabel() {
+        return theLabel;
+    }
+
+/// Define offset for point (by GBLTrajectory constructor)
+    /**
+     * \param [in] anOffset Offset number
+     */
+    public void setOffset(int anOffset) {
+        theOffset = anOffset;
+    }
+
+/// Retrieve offset for point
+    int getOffset() {
+        return theOffset;
+    }
+
+/// Retrieve point-to-(previous)point jacobian
+    Matrix getP2pJacobian() {
+        return p2pJacobian;
+    }
+
+/// Define jacobian to previous scatterer (by GBLTrajectory constructor)
+    /**
+     * \param [in] aJac Jacobian
+     */
+    public void addPrevJacobian(Matrix aJac) {
+        int ifail = 0;
+// to optimize: need only two last rows of inverse
+//	prevJacobian = aJac.InverseFast(ifail);
+//  block matrix algebra
+        Matrix CA = aJac.sub(2, 3, 3, 0).times(aJac.sub(3, 0, 0).inverse()); // C*A^-1
+        Matrix DCAB = aJac.sub(2, 3, 3).minus(CA.times(aJac.sub(3, 2, 0, 3))); // D - C*A^-1 *B
+        DCAB = DCAB.inverse();
+        prevJacobian.placeAt(DCAB, 3, 3);
+        prevJacobian.placeAt(DCAB.times(CA).uminus(), 3, 0);
+    }
+//
+/// Define jacobian to next scatterer (by GBLTrajectory constructor)
+
+    /**
+     * \param [in] aJac Jacobian
+     */
+    public void addNextJacobian(Matrix aJac) {
+        nextJacobian = aJac;
+    }
+
+/// Retrieve derivatives of local track model
+    /**
+     * Linearized track model: F_u(q/p,u',u) = J*u + S*u' + d*q/p, W is inverse
+     * of S, negated for backward propagation. \param [in] aDirection
+     * Propagation direction (>0 forward, else backward) \param [out] matW W
+     * \param [out] matWJ W*J \param [out] vecWd W*d \exception
+     * std::overflow_error : matrix S is singular.
+     */
+    public void getDerivatives(int aDirection, Matrix matW, Matrix matWJ,
+            Vector vecWd) {
+
+        Matrix matJ;
+        Vector vecd;
+        if (aDirection < 1) {
+            matJ = prevJacobian.sub(2, 3, 3);
+            matW = prevJacobian.sub(2, 3, 1).uminus();
+            vecd = prevJacobian.subCol(2, 0, 3);
+        } else {
+            matJ = nextJacobian.sub(2, 3, 3);
+            matW = nextJacobian.sub(2, 3, 1);
+            vecd = nextJacobian.subCol(2, 0, 3);
+        }
+
+        matW = matW.inverse();
+//	if (!matW.InvertFast()) {
+//		std::cout << " getDerivatives failed to invert matrix: "
+//				<< matW << "\n";
+//		std::cout
+//				<< " Possible reason for singular matrix: multiple GblPoints at same arc-length"
+//				<< "\n";
+//		throw std::overflow_error("Singular matrix inversion exception");
+//	}
+        matWJ = matW.times(matJ);
+        vecWd = matW.times(vecd);
+
+    }
+//
+/// Print GblPoint
+
+    /**
+     * \param [in] level print level (0: minimum, >0: more)
+     */
+    public void printPoint(int level) {
+        StringBuffer sb = new StringBuffer("GblPoint");
+        if (theLabel != 0) {
+            sb.append(", label " + theLabel);
+            if (theOffset >= 0) {
+                sb.append(", offset " + theOffset);
+            }
+        }
+        if (measDim != 0) {
+            sb.append(", " + measDim + " measurements");
+        }
+        if (scatFlag) {
+            sb.append(", scatterer");
+        }
+        if (transFlag) {
+            sb.append(", diagonalized");
+        }
+        if (localDerivatives != null) {
+            sb.append(", " + localDerivatives.getColumnDimension()
+                    + " local derivatives");
+        }
+        if (globalDerivatives != null) {
+            sb.append(", " + globalDerivatives.getColumnDimension()
+                    + " global derivatives");
+        }
+        sb.append("\n");
+        if (level > 0) {
+            if (measDim != 0) {
+                sb.append("  Measurement" + "\n");
+                sb.append("   Projection: " + "\n" + measProjection
+                        + "\n");
+                sb.append("   Residuals: " + measResiduals + "\n");
+                sb.append("   Precision: " + measPrecision + "\n");
+            }
+            if (scatFlag) {
+                sb.append("  Scatterer" + "\n");
+                sb.append("   Residuals: " + scatResiduals + "\n");
+                sb.append("   Precision: " + scatPrecision + "\n");
+            }
+            if (localDerivatives.getColumnDimension() != 0) {
+                sb.append("  Local Derivatives:" + "\n");
+                localDerivatives.print(4, 6);
+            }
+            if (globalDerivatives.getColumnDimension() != 0) {
+                sb.append("  Global Labels:");
+                for (int i = 0; i < globalLabels.size(); ++i) {
+                    sb.append(" " + globalLabels.get(i));
+                }
+                sb.append("\n");
+                sb.append("  Global Derivatives:" + "\n");
+                globalDerivatives.print(4, 6);
+            }
+            sb.append("  Jacobian " + "\n");
+            sb.append("   Point-to-point " + "\n" + p2pJacobian
+                    + "\n");
+            if (theLabel != 0) {
+                sb.append("   To previous offset " + "\n" + prevJacobian
+                        + "\n");
+                sb.append("   To next offset " + "\n" + nextJacobian
+                        + "\n");
+            }
+        }
+        System.out.println(sb.toString());
+    }
+
 }

java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl
GblTrajectory.java 918 -> 919
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/GblTrajectory.java	2014-08-28 08:14:53 UTC (rev 918)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/GblTrajectory.java	2014-08-28 15:31:06 UTC (rev 919)
@@ -5,20 +5,28 @@
  * 
  * @author Per Hansson Adrian <[log in to unmask]>
  *
+ * @author Norman A Graf
+ *
+ * @version $Id:
+ * 
  */
 
+import static java.lang.Math.max;
+import java.util.ArrayList;
 import java.util.List;
+import org.hps.recon.tracking.gbl.matrix.BorderedBandMatrix;
+import org.hps.recon.tracking.gbl.matrix.Matrix;
+import org.hps.recon.tracking.gbl.matrix.SymMatrix;
+import org.hps.recon.tracking.gbl.matrix.VVector;
+import org.hps.recon.tracking.gbl.matrix.Vector;
 
+
 public class GblTrajectory {
 
 	public GblTrajectory(List<GblPoint> listOfPoints) {
-		// TODO Auto-generated constructor stub
+		this(listOfPoints, 0, new SymMatrix(0), false, false, false);
 	}
 
-	public boolean isValid() {
-		// TODO Auto-generated method stub
-		return false;
-	}
 
 	public void fit(double m_chi2, int m_ndf, int m_lost_weight) {
 		// TODO Auto-generated method stub
@@ -30,4 +38,1283 @@
 		
 	}
 
+    /**
+     * \mainpage General information
+     *
+     * \section intro_sec Introduction
+     *
+     * For a track with an initial trajectory from a prefit of the measurements
+     * (internal seed) or an external prediction (external seed) the description
+     * of multiple scattering is added by offsets in a local system. Along the
+     * initial trajectory points are defined with can describe a measurement or
+     * a (thin) scatterer or both. Measurements are arbitrary functions of the
+     * local track parameters at a point (e.g. 2D: position, 4D:
+     * direction+position). The refit provides corrections to the local track
+     * parameters (in the local system) and the corresponding covariance matrix
+     * at any of those points. Non-diagonal covariance matrices will be
+     * diagonalized internally. Outliers can be down-weighted by use of
+     * M-estimators.
+     *
+     * The broken lines trajectory is defined by (2D) offsets at the first and
+     * last point and all points with a scatterer. The prediction for a
+     * measurement is obtained by interpolation of the enclosing offsets and for
+     * triplets of adjacent offsets kink angles are determined. This requires
+     * for all points the jacobians for propagation to the previous and next
+     * offset. These are calculated from the point-to-point jacobians along the
+     * initial trajectory. The sequence of points has to be strictly monotonic
+     * in arc-length.
+     *
+     * Additional local or global parameters can be added and the trajectories
+     * can be written to special binary files for calibration and alignment with
+     * Millepede-II. (V. Blobel, NIM A, 566 (2006), pp. 5-13).
+     *
+     * Besides simple trajectories describing the path of a single particle
+     * composed trajectories are supported. These are constructed from the
+     * trajectories of multiple particles and some external parameters (like
+     * those describing a decay) and transformations at the first points from
+     * the external to the local track parameters.
+     *
+     * The conventions for the coordinate systems follow: Derivation of
+     * Jacobians for the propagation of covariance matrices of track parameters
+     * in homogeneous magnetic fields A. Strandlie, W. Wittek, NIM A, 566 (2006)
+     * 687-698.
+     *
+     * \section call_sec Calling sequence
+     *
+     * -# Create list of points on initial trajectory:\n
+     * <tt>List<GblPoint> list</tt>
+     * -# For all points on initial trajectory: - Create points and add
+     * appropriate attributes:\n - <tt>point = gbl::GblPoint(..)</tt>
+     * - <tt>point.addMeasurement(..)</tt>
+     * - Add additional local or global parameters to measurement:\n -
+     * <tt>point.addLocals(..)</tt>
+     * - <tt>point.addGlobals(..)</tt>
+     * - <tt>point.addScatterer(..)</tt>
+     * - Add point (ordered by arc length) to list:\n
+     * <tt>list.add(point)</tt>
+     * -# Create (simple) trajectory from list of points:\n
+     * <tt>traj = gbl::GblTrajectory (list)</tt>
+     * -# Optionally with external seed:\n
+     * <tt>traj = gbl::GblTrajectory (list,seed)</tt>
+     * -# Optionally check validity of trajectory:\n
+     * <tt>if (not traj.isValid()) .. //abort</tt>
+     * -# Fit trajectory, return error code, get Chi2, Ndf (and weight lost by
+     * M-estimators):\n
+     * <tt>ierr = traj.fit(..)</tt>
+     * -# For any point on initial trajectory: - Get corrections and covariance
+     * matrix for track parameters:\n
+     * <tt>[..] = traj.getResults(label)</tt>
+     * -# Optionally write trajectory to MP binary file:\n
+     * <tt>traj.milleOut(..)</tt>
+     *
+     * \section loc_sec Local system and local parameters At each point on the
+     * trajectory a local coordinate system with local track parameters has to
+     * be defined. The first of the five parameters describes the bending, the
+     * next two the direction and the last two the position (offsets). The
+     * curvilinear system (T,U,V) with parameters (q/p, lambda, phi, x_t, y_t)
+     * is well suited.
+     *
+     * \section impl_sec Implementation
+     *
+     * Matrices are implemented with ROOT (root.cern.ch). User input or output
+     * is in the form of TMatrices. Internally SMatrices are used for fixes
+     * sized and simple matrices based on List<> for variable sized matrices.
+     *
+     * \section ref_sec References - V. Blobel, C. Kleinwort, F. Meier, Fast
+     * alignment of a complex tracking detector using advanced track models,
+     * Computer Phys. Communications (2011), doi:10.1016/j.cpc.2011.03.017 - C.
+     * Kleinwort, General Broken Lines as advanced track fitting method, NIM A,
+     * 673 (2012), 107-110, doi:10.1016/j.nima.2012.01.024
+     */
+    int numAllPoints; ///< Number of all points on trajectory
+    List< Integer> numPoints = new ArrayList<Integer>(); ///< Number of points on (sub)trajectory
+    int numTrajectories; ///< Number of trajectories (in composed trajectory)
+    int numOffsets; ///< Number of (points with) offsets on trajectory
+    int numInnerTrans; ///< Number of inner transformations to external parameters
+    int numCurvature; ///< Number of curvature parameters (0 or 1) or external parameters
+    int numParameters; ///< Number of fit parameters
+    int numLocals; ///< Total number of (additional) local parameters
+    int numMeasurements; ///< Total number of measurements
+    int externalPoint; ///< Label of external point (or 0)
+    boolean constructOK; ///< Trajectory has been successfully constructed (ready for fit/output)
+    boolean fitOK; ///< Trajectory has been successfully fitted (results are valid)
+    List< Integer> theDimension = new ArrayList<Integer>(); ///< List of active dimensions (0=u1, 1=u2) in fit
+    List<List<GblPoint>> thePoints = new ArrayList<List<GblPoint>>(); ///< (list of) List of points on trajectory
+    List<GblData> theData = new ArrayList<GblData>(); ///< List of data blocks
+    List<Integer> measDataIndex = new ArrayList<Integer>(); ///< mapping points to data blocks from measurements
+    List<Integer> scatDataIndex; ///< mapping points to data blocks from scatterers
+    List<Integer> externalIndex; ///< List of fit parameters used by external seed
+    SymMatrix externalSeed; ///< Precision (inverse covariance matrix) of external seed
+    List<Matrix> innerTransformations; ///< Transformations at innermost points of
+    // composed trajectory (from common external parameters)
+    Matrix externalDerivatives; // Derivatives for external measurements of composed trajectory
+    Vector externalMeasurements; // Residuals for external measurements of composed trajectory
+    Vector externalPrecisions; // Precisions for external measurements of composed trajectory
+    VVector theVector; ///< Vector of linear equation system
+    BorderedBandMatrix theMatrix = new BorderedBandMatrix(); ///< (Bordered band) matrix of linear equation system
+
+///// Create new (simple) trajectory from list of points.
+//    /**
+//     * Curved trajectory in space (default) or without curvature (q/p) or in one
+//     * plane (u-direction) only. \param [in] aPointList List of points \param
+//     * [in] flagCurv Use q/p \param [in] flagU1dir Use in u1 direction \param
+//     * [in] flagU2dir Use in u2 direction
+//     */
+//    GblTrajectory(List<GblPoint> aPointList,
+//            boolean flagCurv, boolean flagU1dir, boolean flagU2dir)
+//    {
+//        numAllPoints = aPointList.size();
+//        //numPoints()
+//        numOffsets = 0;
+//        numInnerTrans = 0;
+//        numCurvature = (flagCurv ? 1 : 0);
+//        numParameters = 0;
+//        numLocals = 0;
+//        numMeasurements = 0;
+//        externalPoint = 0;
+//                //externalSeed()
+//        //innerTransformations()
+//        //externalDerivatives()
+//        //externalMeasurements()
+//        // externalPrecisions() 
+//
+//        if (flagU1dir)
+//        {
+//            theDimension.add(0);
+//        }
+//        if (flagU2dir)
+//        {
+//            theDimension.add(1);
+//        }
+//        // simple (single) trajectory
+//        thePoints.add(aPointList);
+//        numPoints.add(numAllPoints);
+////	construct(); // construct trajectory
+//    }
+/// Create new (simple) trajectory from list of points with external seed.
+    /**
+     * Curved trajectory in space (default) or without curvature (q/p) or in one
+     * plane (u-direction) only. \param [in] aPointList List of points \param
+     * [in] aLabel (Signed) label of point for external seed (<0: in front, >0:
+     * after point, slope changes at scatterer!) \param [in] aSeed Precision
+     * matrix of external seed \param [in] flagCurv Use q/p \param [in]
+     * flagU1dir Use in u1 direction \param [in] flagU2dir Use in u2 direction
+     */
+    GblTrajectory(List<GblPoint> aPointList,
+            int aLabel, SymMatrix aSeed, boolean flagCurv,
+            boolean flagU1dir, boolean flagU2dir)
+    {
+        numAllPoints = aPointList.size();
+        //numPoints(), 
+        numOffsets = 0;
+        numInnerTrans = 0;
+        numCurvature = (flagCurv ? 1 : 0);
+        numParameters = 0;
+        numLocals = 0;
+        numMeasurements = 0;
+        //externalPoint(aLabel) 
+        //theDimension(),
+        //thePoints(), 
+        //theData(), 
+        //measDataIndex(), 
+        //scatDataIndex(), 
+        //externalIndex(), 
+        //externalSeed(aSeed), 
+        //innerTransformations(), 
+        //externalDerivatives(), 
+        //externalMeasurements(), 
+        //externalPrecisions() {
+
+        if (flagU1dir)
+        {
+            theDimension.add(0);
+        }
+        if (flagU2dir)
+        {
+            theDimension.add(1);
+        }
+        // simple (single) trajectory
+        thePoints.add(aPointList);
+        numPoints.add(numAllPoints);
+        construct(); // construct trajectory
+    }
+
+///// Create new composed trajectory from list of points and transformations.
+///**
+// * Composed of curved trajectory in space.
+// * \param [in] aPointsAndTransList List containing pairs with list of points and transformation (at inner (first) point)
+// */
+//GblTrajectory(
+//		const List<std::pair<List<GblPoint>, TMatrixD> > &aPointsAndTransList) :
+//		numAllPoints(), numPoints(), numOffsets(0), numInnerTrans(
+//				aPointsAndTransList.size()), numParameters(0), numLocals(0), numMeasurements(
+//				0), externalPoint(0), theDimension(0), thePoints(), theData(), measDataIndex(), scatDataIndex(), externalIndex(), externalSeed(), innerTransformations(), externalDerivatives(), externalMeasurements(), externalPrecisions() {
+//
+//	for ( int iTraj = 0; iTraj < aPointsAndTransList.size(); ++iTraj) {
+//		thePoints.add(aPointsAndTransList[iTraj].first);
+//		numPoints.add(thePoints.back().size());
+//		numAllPoints += numPoints.back();
+//		innerTransformations.add(aPointsAndTransList[iTraj].second);
+//	}
+//	theDimension.add(0);
+//	theDimension.add(1);
+//	numCurvature = innerTransformations[0].GetNcols();
+//	construct(); // construct (composed) trajectory
+//}
+//
+///// Create new composed trajectory from list of points and transformations with (independent) external measurements.
+///**
+// * Composed of curved trajectory in space.
+// * \param [in] aPointsAndTransList List containing pairs with list of points and transformation (at inner (first) point)
+// * \param [in] extDerivatives Derivatives of external measurements vs external parameters
+// * \param [in] extMeasurements External measurements (residuals)
+// * \param [in] extPrecisions Precision of external measurements
+// */
+//GblTrajectory(
+//		const List<std::pair<List<GblPoint>, TMatrixD> > &aPointsAndTransList,
+//		const TMatrixD &extDerivatives, const TVectorD &extMeasurements,
+//		const TVectorD &extPrecisions) :
+//		numAllPoints(), numPoints(), numOffsets(0), numInnerTrans(
+//				aPointsAndTransList.size()), numParameters(0), numLocals(0), numMeasurements(
+//				0), externalPoint(0), theDimension(0), thePoints(), theData(), measDataIndex(), scatDataIndex(), externalIndex(), externalSeed(), innerTransformations(), externalDerivatives(
+//				extDerivatives), externalMeasurements(extMeasurements), externalPrecisions(
+//				extPrecisions) {
+//
+//	for ( int iTraj = 0; iTraj < aPointsAndTransList.size(); ++iTraj) {
+//		thePoints.add(aPointsAndTransList[iTraj].first);
+//		numPoints.add(thePoints.back().size());
+//		numAllPoints += numPoints.back();
+//		innerTransformations.add(aPointsAndTransList[iTraj].second);
+//	}
+//	theDimension.add(0);
+//	theDimension.add(1);
+//	numCurvature = innerTransformations[0].GetNcols();
+//	construct(); // construct (composed) trajectory
+//}
+//
+//~GblTrajectory() {
+//}
+//
+/// Retrieve validity of trajectory
+    boolean isValid()
+    {
+        return constructOK;
+    }
+
+/// Retrieve number of point from trajectory
+    int getNumPoints()
+    {
+        return numAllPoints;
+    }
+
+/// Construct trajectory from list of points.
+    /**
+     * Trajectory is prepared for fit or output to binary file, may consists of
+     * sub-trajectories.
+     */
+    void construct()
+    {
+
+        constructOK = false;
+        fitOK = false;
+        int aLabel = 0;
+        // loop over trajectories
+        numTrajectories = thePoints.size();
+        //std::cout << " numTrajectories: " << numTrajectories << ", "<< innerTransformations.size()  << std::endl;
+//	for ( int iTraj = 0; iTraj < numTrajectories; ++iTraj) {
+//		List<GblPoint>::iterator itPoint;
+//		for (itPoint = thePoints[iTraj].begin();
+//				itPoint < thePoints[iTraj].end(); ++itPoint) {
+//			numLocals = std::max(numLocals, itPoint->getNumLocals());
+//			numMeasurements += itPoint->hasMeasurement();
+//			itPoint->setLabel(++aLabel);
+//		}
+//	}
+        for (List<GblPoint> list : thePoints)
+        {
+            for (GblPoint p : list)
+            {
+                numLocals = max(numLocals, p.getNumLocals());
+                numMeasurements += p.hasMeasurement();
+                p.setLabel(++aLabel);
+            }
+        }
+        defineOffsets();
+        calcJacobians();
+//	try {
+		prepare();
+//	} catch (std::overflow_error &e) {
+//		std::cout << " GblTrajectory construction failed: " << e.what()
+//				<< std::endl;
+//		return;
+//	}
+        constructOK = true;
+        // number of fit parameters
+        numParameters = (numOffsets - 2 * numInnerTrans) * theDimension.size()
+                + numCurvature + numLocals;
+    }
+//
+/// Define offsets from list of points.
+
+    /**
+     * Define offsets at points with scatterers and first and last point. All
+     * other points need interpolation from adjacent points with offsets.
+     */
+    void defineOffsets()
+    {
+
+        // loop over trajectories
+        for (int iTraj = 0; iTraj < numTrajectories; ++iTraj)
+        {
+            List<GblPoint> list = thePoints.get(iTraj);
+            int size = list.size();
+            // first point is offset
+//		thePoints[iTraj].front().setOffset(numOffsets++);
+            list.get(0).setOffset(numOffsets++);		// intermediate scatterers are offsets
+//		List<GblPoint>::iterator itPoint;
+//		for (itPoint = thePoints[iTraj].begin() + 1;
+//				itPoint < thePoints[iTraj].end() - 1; ++itPoint) {
+//			if (itPoint->hasScatterer()) {
+//				itPoint->setOffset(numOffsets++);
+//			} else {
+//				itPoint->setOffset(-numOffsets);
+//			}
+//		}
+            for (int i = 1; i < size - 1; ++i)
+            {
+                GblPoint p = list.get(i);
+                if (p.hasScatterer())
+                {
+                    p.setOffset(numOffsets++);
+                } else
+                {
+                    p.setOffset(-numOffsets);
+                }
+
+            }
+            // last point is offset
+//		thePoints[iTraj].back().setOffset(numOffsets++);
+            list.get(size - 1).setOffset(numOffsets++);
+        }
+    }
+
+/// Calculate Jacobians to previous/next scatterer from point to point ones.
+    void calcJacobians()
+    {
+
+        Matrix scatJacobian = new Matrix(5, 5);
+        // loop over trajectories
+        for (int iTraj = 0; iTraj < numTrajectories; ++iTraj)
+        {
+            List<GblPoint> list = thePoints.get(iTraj);
+            int size = list.size();
+            // forward propagation (all)
+            GblPoint previousPoint = list.get(0);
+            int numStep = 0;
+            for (int i = 1; i < size; ++i)
+            {
+                GblPoint p = list.get(i);
+                if (numStep == 0)
+                {
+                    scatJacobian = p.getP2pJacobian();
+                } else
+                {
+                    scatJacobian = p.getP2pJacobian().times(scatJacobian);
+                }
+                numStep++;
+                p.addPrevJacobian(scatJacobian);// iPoint -> previous scatterer
+                if (p.getOffset() >= 0)
+                {
+                    previousPoint.addNextJacobian(scatJacobian); // lastPoint -> next scatterer
+                    numStep = 0;
+                    previousPoint = p;
+                }
+            }
+//            List<GblPoint>::iterator itPoint;
+//            for (itPoint = thePoints[iTraj].begin() + 1;
+//                    itPoint < thePoints[iTraj].end(); ++itPoint)
+//            {
+//                if (numStep == 0)
+//                {
+//                    scatJacobian = itPoint -> getP2pJacobian();
+//                } else
+//                {
+//                    scatJacobian = itPoint -> getP2pJacobian() * scatJacobian;
+//                }
+//                numStep++;
+//                itPoint -> addPrevJacobian(scatJacobian); // iPoint -> previous scatterer
+//                if (itPoint -> getOffset() >= 0)
+//                {
+//                    previousPoint -> addNextJacobian(scatJacobian); // lastPoint -> next scatterer
+//                    numStep = 0;
+//                    previousPoint =  & ( * itPoint);
+//                }
+//            }
+//            // backward propagation (without scatterers)
+//            for (itPoint = thePoints[iTraj].end() - 1;
+//                    itPoint > thePoints[iTraj].begin(); --itPoint)
+//            {
+//                if (itPoint -> getOffset() >= 0)
+//                {
+//                    scatJacobian = itPoint -> getP2pJacobian();
+//                    continue; // skip offsets
+//                }
+//                itPoint -> addNextJacobian(scatJacobian); // iPoint -> next scatterer
+//                scatJacobian = scatJacobian * itPoint -> getP2pJacobian();
+//            }
+            // backward propagation (without scatterers)            
+            for (int i = size - 1; i > 0; --i)
+            {
+                GblPoint p = list.get(i);
+                if (p.getOffset() >= 0)
+                {
+                    scatJacobian = p.getP2pJacobian();
+                    continue; // skip offsets
+                }
+                p.addNextJacobian(scatJacobian); // iPoint -> next scatterer
+                scatJacobian = scatJacobian.times(p.getP2pJacobian());
+            }
+        }
+    }
+//
+///// Get jacobian for transformation from fit to track parameters at point.
+///**
+// * Jacobian broken lines (q/p,..,u_i,u_i+1..) to track (q/p,u',u) parameters
+// * including additional local parameters.
+// * \param [in] aSignedLabel (Signed) label of point for external seed
+// * (<0: in front, >0: after point, slope changes at scatterer!)
+// * \return List of fit parameters with non zero derivatives and
+// * corresponding transformation matrix
+// */
+//std::pair<List< int>, TMatrixD> getJacobian(
+//		int aSignedLabel) const {
+//
+//	 int nDim = theDimension.size();
+//	 int nCurv = numCurvature;
+//	 int nLocals = numLocals;
+//	 int nBorder = nCurv + nLocals;
+//	 int nParBRL = nBorder + 2 * nDim;
+//	 int nParLoc = nLocals + 5;
+//	List< int> anIndex;
+//	anIndex.reserve(nParBRL);
+//	TMatrixD aJacobian(nParLoc, nParBRL);
+//	aJacobian.Zero();
+//
+//	 int aLabel = abs(aSignedLabel);
+//	 int firstLabel = 1;
+//	 int lastLabel = 0;
+//	 int aTrajectory = 0;
+//	// loop over trajectories
+//	for ( int iTraj = 0; iTraj < numTrajectories; ++iTraj) {
+//		aTrajectory = iTraj;
+//		lastLabel += numPoints[iTraj];
+//		if (aLabel <= lastLabel)
+//			break;
+//		if (iTraj < numTrajectories - 1)
+//			firstLabel += numPoints[iTraj];
+//	}
+//	int nJacobian; // 0: prev, 1: next
+//	// check consistency of (index, direction)
+//	if (aSignedLabel > 0) {
+//		nJacobian = 1;
+//		if (aLabel >= lastLabel) {
+//			aLabel = lastLabel;
+//			nJacobian = 0;
+//		}
+//	} else {
+//		nJacobian = 0;
+//		if (aLabel <= firstLabel) {
+//			aLabel = firstLabel;
+//			nJacobian = 1;
+//		}
+//	}
+//	const GblPoint aPoint = thePoints[aTrajectory][aLabel - firstLabel];
+//	List< int> labDer(5);
+//	SMatrix55 matDer;
+//	getFitToLocalJacobian(labDer, matDer, aPoint, 5, nJacobian);
+//
+//	// from local parameters
+//	for ( int i = 0; i < nLocals; ++i) {
+//		aJacobian(i + 5, i) = 1.0;
+//		anIndex.add(i + 1);
+//	}
+//	// from trajectory parameters
+//	 int iCol = nLocals;
+//	for ( int i = 0; i < 5; ++i) {
+//		if (labDer[i] > 0) {
+//			anIndex.add(labDer[i]);
+//			for ( int j = 0; j < 5; ++j) {
+//				aJacobian(j, iCol) = matDer(j, i);
+//			}
+//			++iCol;
+//		}
+//	}
+//	return std::make_pair(anIndex, aJacobian);
+//}
+
+/// Get (part of) jacobian for transformation from (trajectory) fit to track parameters at point.
+    /**
+     * Jacobian broken lines (q/p,..,u_i,u_i+1..) to local (q/p,u',u)
+     * parameters. \param [out] anIndex List of fit parameters with non zero
+     * derivatives \param [out] aJacobian Corresponding transformation matrix
+     * \param [in] aPoint Point to use \param [in] measDim Dimension of
+     * 'measurement' (<=2: calculate only offset part, >2: complete matrix)
+     * \param [in] nJacobian Direction (0: to previous offset, 1: to next
+     * offset)
+     */
+    void getFitToLocalJacobian(List<Integer> anIndex,
+            Matrix aJacobian, GblPoint aPoint, int measDim,
+            int nJacobian)
+    {
+
+        int nDim = theDimension.size();
+        int nCurv = numCurvature;
+        int nLocals = numLocals;
+
+        int nOffset = aPoint.getOffset();
+
+        if (nOffset < 0) // need interpolation
+        {
+            Matrix prevW = new Matrix(2, 2);
+            Matrix prevWJ = new Matrix(2, 2);
+            Matrix nextW = new Matrix(2, 2);
+            Matrix nextWJ = new Matrix(2, 2);
+            Matrix matN = new Matrix(2, 2);
+            Vector prevWd = new Vector(2);
+            Vector nextWd = new Vector(2);
+            int ierr;
+            aPoint.getDerivatives(0, prevW, prevWJ, prevWd); // W-, W- * J-, W- * d-
+            aPoint.getDerivatives(1, nextW, nextWJ, nextWd); // W-, W- * J-, W- * d-
+            Matrix sumWJ = prevWJ.plus(nextWJ);
+//?		matN = sumWJ.inverse(ierr); // N = (W- * J- + W+ * J+)^-1
+            // derivatives for u_int
+            Matrix prevNW = matN.times(prevW); // N * W-
+            Matrix nextNW = matN.times(nextW); // N * W+
+            Vector prevNd = matN.times(prevWd); // N * W- * d-
+            Vector nextNd = matN.times(nextWd); // N * W+ * d+
+
+            int iOff = nDim * (-nOffset - 1) + nLocals + nCurv + 1; // first offset ('i' in u_i)
+
+            // local offset
+            if (nCurv > 0)
+            {
+                Vector negDiff = prevNd.minus(nextNd).uminus();
+                aJacobian.placeInCol(negDiff, 3, 0); // from curvature
+                anIndex.set(0, nLocals + 1);
+            }
+            aJacobian.placeAt(prevNW, 3, 1); // from 1st Offset
+            aJacobian.placeAt(nextNW, 3, 3); // from 2nd Offset
+            for (int i = 0; i < nDim; ++i)
+            {
+                anIndex.set(1 + theDimension.get(i), iOff + i);
+                anIndex.set(3 + theDimension.get(i), iOff + nDim + i);
+            }
+//
+////		// local slope and curvature
+////		if (measDim > 2) {
+////			// derivatives for u'_int
+////			const SMatrix22 prevWPN(nextWJ * prevNW); // W+ * J+ * N * W-
+////			const SMatrix22 nextWPN(prevWJ * nextNW); // W- * J- * N * W+
+////			const SVector2 prevWNd(nextWJ * prevNd); // W+ * J+ * N * W- * d-
+////			const SVector2 nextWNd(prevWJ * nextNd); // W- * J- * N * W+ * d+
+////			if (nCurv > 0) {
+////				aJacobian(0, 0) = 1.0;
+////				aJacobian.Place_in_col(prevWNd - nextWNd, 1, 0); // from curvature
+////			}
+////			aJacobian.Place_at(-prevWPN, 1, 1); // from 1st Offset
+////			aJacobian.Place_at(nextWPN, 1, 3); // from 2nd Offset
+////		}
+//	} else { // at point
+            // anIndex must be sorted
+            // forward : iOff2 = iOff1 + nDim, index1 = 1, index2 = 3
+            // backward: iOff2 = iOff1 - nDim, index1 = 3, index2 = 1
+            int iOff1 = nDim * nOffset + nCurv + nLocals + 1; // first offset ('i' in u_i)
+            int index1 = 3 - 2 * nJacobian; // index of first offset
+            int iOff2 = iOff1 + nDim * (nJacobian * 2 - 1); // second offset ('i' in u_i)
+            int index2 = 1 + 2 * nJacobian; // index of second offset
+            // local offset
+            aJacobian.set(3, index1, 1.0); // from 1st Offset
+            aJacobian.set(4, index1 + 1, 1.0);
+            for (int i = 0; i < nDim; ++i)
+            {
+                anIndex.set(index1 + theDimension.get(i), iOff1 + i);
+            }
+
+            // local slope and curvature
+            if (measDim > 2)
+            {
+                Matrix matW = new Matrix(2, 2);
+                Matrix matWJ = new Matrix(2, 2);
+                Vector vecWd = new Vector(2);
+                aPoint.getDerivatives(nJacobian, matW, matWJ, vecWd); // W, W * J, W * d
+                double sign = (nJacobian > 0) ? 1. : -1.;
+                if (nCurv > 0)
+                {
+                    aJacobian.set(0, 0, 1.0);
+                    aJacobian.placeInCol(vecWd.timesScalar(-sign), 1, 0); // from curvature
+                    anIndex.set(0, nLocals + 1);
+                }
+                aJacobian.placeAt(matWJ.times(-sign), 1, index1); // from 1st Offset
+                aJacobian.placeAt(matW.times(sign), 1, index2); // from 2nd Offset
+                for (int i = 0; i < nDim; ++i)
+                {
+                    anIndex.set(index2 + theDimension.get(i), iOff2 + i);
+                }
+            }
+        }
+    }
+
+/// Get jacobian for transformation from (trajectory) fit to kink parameters at point.
+    /**
+     * Jacobian broken lines (q/p,..,u_i-1,u_i,u_i+1..) to kink (du')
+     * parameters. \param [out] anIndex List of fit parameters with non zero
+     * derivatives \param [out] aJacobian Corresponding transformation matrix
+     * \param [in] aPoint Point to use
+     */
+    void getFitToKinkJacobian(List< Integer> anIndex,
+            Matrix aJacobian, GblPoint aPoint)
+    {
+
+        //nb aJacobian has dimension 2,7
+        int nDim = theDimension.size();
+        int nCurv = numCurvature;
+        int nLocals = numLocals;
+
+        int nOffset = aPoint.getOffset();
+
+        Matrix prevW = new Matrix(2, 2);
+        Matrix prevWJ = new Matrix(2, 2);
+        Matrix nextW = new Matrix(2, 2);
+        Matrix nextWJ = new Matrix(2, 2);
+        Vector prevWd = new Vector(2);
+        Vector nextWd = new Vector(2);
+        aPoint.getDerivatives(0, prevW, prevWJ, prevWd); // W-, W- * J-, W- * d-
+        aPoint.getDerivatives(1, nextW, nextWJ, nextWd); // W-, W- * J-, W- * d-
+        Matrix sumWJ = prevWJ.plus(nextWJ); // W- * J- + W+ * J+
+        Vector sumWd = prevWd.plus(nextWd); // W+ * d+ + W- * d-
+
+        int iOff = (nOffset - 1) * nDim + nCurv + nLocals + 1; // first offset ('i' in u_i)
+
+        // local offset
+        if (nCurv > 0)
+        {
+            aJacobian.placeInCol(sumWd.uminus(), 0, 0); // from curvature
+            anIndex.set(0, nLocals + 1);
+        }
+        aJacobian.placeAt(prevW, 0, 1); // from 1st Offset
+        aJacobian.placeAt(sumWJ.uminus(), 0, 3); // from 2nd Offset
+        aJacobian.placeAt(nextW, 0, 5); // from 1st Offset
+        for (int i = 0; i < nDim; ++i)
+        {
+            anIndex.set(1 + theDimension.get(i), iOff + i);
+            anIndex.set(3 + theDimension.get(i), iOff + nDim + i);
+            anIndex.set(5 + theDimension.get(i), iOff + nDim * 2 + i);
+        }
+    }
+
+///// Get fit results at point.
+///**
+// * Get corrections and covariance matrix for local track and additional parameters
+// * in forward or backward direction.
+// * \param [in] aSignedLabel (Signed) label of point on trajectory
+// * (<0: in front, >0: after point, slope changes at scatterer!)
+// * \param [out] localPar Corrections for local parameters
+// * \param [out] localCov Covariance for local parameters
+// * \return error code (non-zero if trajectory not fitted successfully)
+// */
+// int getResults(int aSignedLabel, TVectorD &localPar,
+//		SymMatrix &localCov) const {
+//	if (! fitOK)
+//		return 1;
+//	std::pair<List< int>, TMatrixD> indexAndJacobian =
+//			getJacobian(aSignedLabel);
+//	 int nParBrl = indexAndJacobian.first.size();
+//	TVectorD aVec(nParBrl); // compressed vector
+//	for ( int i = 0; i < nParBrl; ++i) {
+//		aVec[i] = theVector(indexAndJacobian.first[i] - 1);
+//	}
+//	SymMatrix aMat = theMatrix.getBlockMatrix(indexAndJacobian.first); // compressed matrix
+//	localPar = indexAndJacobian.second * aVec;
+//	localCov = aMat.Similarity(indexAndJacobian.second);
+//	return 0;
+//}
+//
+///// Get residuals at point from measurement.
+///**
+// * Get (diagonalized) residual, error of measurement and residual and down-weighting
+// * factor for measurement at point
+// *
+// * \param [in]  aLabel Label of point on trajectory
+// * \param [out] numData Number of data blocks from measurement at point
+// * \param [out] aResiduals Measurements-Predictions
+// * \param [out] aMeasErrors Errors of Measurements
+// * \param [out] aResErrors Errors of Residuals (including correlations from track fit)
+// * \param [out] aDownWeights Down-Weighting factors
+// * \return error code (non-zero if trajectory not fitted successfully)
+// */
+// int getMeasResults( int aLabel,
+//		 int &numData, TVectorD &aResiduals, TVectorD &aMeasErrors,
+//		TVectorD &aResErrors, TVectorD &aDownWeights) {
+//	numData = 0;
+//	if (! fitOK)
+//		return 1;
+//
+//	 int firstData = measDataIndex[aLabel - 1]; // first data block with measurement
+//	numData = measDataIndex[aLabel] - firstData; // number of data blocks
+//	for ( int i = 0; i < numData; ++i) {
+//		getResAndErr(firstData + i, aResiduals[i], aMeasErrors[i],
+//				aResErrors[i], aDownWeights[i]);
+//	}
+//	return 0;
+//}
+//
+///// Get (kink) residuals at point from scatterer.
+///**
+// * Get (diagonalized) residual, error of measurement and residual and down-weighting
+// * factor for scatterering kinks at point
+// *
+// * \param [in]  aLabel Label of point on trajectory
+// * \param [out] numData Number of data blocks from scatterer at point
+// * \param [out] aResiduals (kink)Measurements-(kink)Predictions
+// * \param [out] aMeasErrors Errors of (kink)Measurements
+// * \param [out] aResErrors Errors of Residuals (including correlations from track fit)
+// * \param [out] aDownWeights Down-Weighting factors
+// * \return error code (non-zero if trajectory not fitted successfully)
+// */
+// int getScatResults( int aLabel,
+//		 int &numData, TVectorD &aResiduals, TVectorD &aMeasErrors,
+//		TVectorD &aResErrors, TVectorD &aDownWeights) {
+//	numData = 0;
+//	if (! fitOK)
+//		return 1;
+//
+//	 int firstData = scatDataIndex[aLabel - 1]; // first data block with scatterer
+//	numData = scatDataIndex[aLabel] - firstData; // number of data blocks
+//	for ( int i = 0; i < numData; ++i) {
+//		getResAndErr(firstData + i, aResiduals[i], aMeasErrors[i],
+//				aResErrors[i], aDownWeights[i]);
+//	}
+//	return 0;
+//}
+//
+///// Get (list of) labels of points on (simple) trajectory
+///**
+// * \param [out] aLabelList List of labels (aLabelList[i] = i+1)
+// */
+//void getLabels(List< int> &aLabelList) {
+//	 int aLabel = 0;
+//	 int nPoint = thePoints[0].size();
+//	aLabelList.resize(nPoint);
+//	for ( i = 0; i < nPoint; ++i) {
+//		aLabelList[i] = ++aLabel;
+//	}
+//}
+//
+///// Get (list of lists of) labels of points on (composed) trajectory
+///**
+// * \param [out] aLabelList List of of lists of labels
+// */
+//void getLabels(
+//		List<List< int> > &aLabelList) {
+//	 int aLabel = 0;
+//	aLabelList.resize(numTrajectories);
+//	for ( int iTraj = 0; iTraj < numTrajectories; ++iTraj) {
+//		 int nPoint = thePoints[iTraj].size();
+//		aLabelList[iTraj].resize(nPoint);
+//		for ( i = 0; i < nPoint; ++i) {
+//			aLabelList[iTraj][i] = ++aLabel;
+//		}
+//	}
+//}
+//
+///// Get residual and errors from data block.
+///**
+// * Get residual, error of measurement and residual and down-weighting
+// * factor for (single) data block
+// * \param [in]  aData Label of data block
+// * \param [out] aResidual Measurement-Prediction
+// * \param [out] aMeasError Error of Measurement
+// * \param [out] aResError Error of Residual (including correlations from track fit)
+// * \param [out] aDownWeight Down-Weighting factor
+// */
+//void getResAndErr( int aData, double &aResidual,
+//		double &aMeasError, double &aResError, double &aDownWeight) {
+//
+//	double aMeasVar;
+//	List< int>* indLocal;
+//	List<double>* derLocal;
+//	theData[aData].getResidual(aResidual, aMeasVar, aDownWeight, indLocal,
+//			derLocal);
+//	 int nParBrl = (*indLocal).size();
+//	TVectorD aVec(nParBrl); // compressed vector of derivatives
+//	for ( int j = 0; j < nParBrl; ++j) {
+//		aVec[j] = (*derLocal)[j];
+//	}
+//	SymMatrix aMat = theMatrix.getBlockMatrix(*indLocal); // compressed (covariance) matrix
+//	double aFitVar = aMat.Similarity(aVec); // variance from track fit
+//	aMeasError = sqrt(aMeasVar); // error of measurement
+//	aResError = (aFitVar < aMeasVar ? sqrt(aMeasVar - aFitVar) : 0.); // error of residual
+//}
+/// Build linear equation system from data (blocks).
+    void buildLinearEquationSystem()
+    {
+        int nBorder = numCurvature + numLocals;
+//	theVector. resize(numParameters);
+        theMatrix.resize(numParameters, nBorder, 5);
+        double[] retVals = new double[2];
+        double aValue, aWeight;
+        int[] indLocal = null;
+        double[] derLocal = null;
+        for (GblData d : theData)
+        {
+            d.getLocalData(retVals, indLocal, derLocal);
+            aValue = retVals[0];
+            aWeight = retVals[1];
+            for (int j = 0; j < indLocal.length; ++j)
+            {
+                theVector.addTo(indLocal[j] - 1, derLocal[j] * aWeight * aValue);
+            }
+            theMatrix.addBlockMatrix(aWeight, indLocal, derLocal);
+        }
+    }
+//}
+
+/// Prepare fit for simple or composed trajectory
+/**
+ * Generate data (blocks) from measurements, kinks, external seed and measurements.
+ */
+void prepare() {
+	 int nDim = theDimension.size();
+	// upper limit
+	 int maxData = numMeasurements + nDim * (numOffsets - 2);
+//cng			+ externalSeed.getRowDimension();
+//	theData.reserve(maxData);
+//	measDataIndex.resize(numAllPoints + 3); // include external seed and measurements
+         //cng
+         for(int i = 0; i<numAllPoints + 3; ++i) measDataIndex.add(i,0);
+         //cng
+//	scatDataIndex.resize(numAllPoints + 1);
+	 int nData = 0;
+	List<Matrix> innerTransDer = new ArrayList<Matrix>();
+	List<List<Integer> > innerTransLab = new ArrayList<List<Integer>>();
+//	// composed trajectory ?
+//	if (numInnerTrans > 0) {
+//		//std::cout << "composed trajectory" << std::endl;
+//		for ( int iTraj = 0; iTraj < numTrajectories; ++iTraj) {
+//			// innermost point
+//			GblPoint* innerPoint = &thePoints[iTraj].front();
+//			// transformation fit to local track parameters
+//			List< int> firstLabels(5);
+//			SMatrix55 matFitToLocal, matLocalToFit;
+//			getFitToLocalJacobian(firstLabels, matFitToLocal, *innerPoint, 5);
+//			// transformation local track to fit parameters
+//			int ierr;
+//			matLocalToFit = matFitToLocal.Inverse(ierr);
+//			TMatrixD localToFit(5, 5);
+//			for ( int i = 0; i < 5; ++i) {
+//				for ( int j = 0; j < 5; ++j) {
+//					localToFit(i, j) = matLocalToFit(i, j);
+//				}
+//			}
+//			// transformation external to fit parameters at inner (first) point
+//			innerTransDer.add(localToFit * innerTransformations[iTraj]);
+//			innerTransLab.add(firstLabels);
+//		}
+//	}
+	// measurements
+	Matrix matP = new Matrix(5,5);
+//	// loop over trajectories
+//	List<GblPoint>::iterator itPoint;
+//	for ( int iTraj = 0; iTraj < numTrajectories; ++iTraj) {
+//		for (itPoint = thePoints[iTraj].begin();
+//				itPoint < thePoints[iTraj].end(); ++itPoint) {
+//			SVector5 aMeas, aPrec;
+//			 int nLabel = itPoint->getLabel();
+//			 int measDim = itPoint->hasMeasurement();
+//			if (measDim) {
+//				const TMatrixD localDer = itPoint->getLocalDerivatives();
+//				const List<int> globalLab = itPoint->getGlobalLabels();
+//				const TMatrixD globalDer = itPoint->getGlobalDerivatives();
+//				TMatrixD transDer;
+//				itPoint->getMeasurement(matP, aMeas, aPrec);
+//				 int iOff = 5 - measDim; // first active component
+//				List< int> labDer(5);
+//				SMatrix55 matDer, matPDer;
+//				 int nJacobian =
+//						(itPoint < thePoints[iTraj].end() - 1) ? 1 : 0; // last point needs backward propagation
+//				getFitToLocalJacobian(labDer, matDer, *itPoint, measDim,
+//						nJacobian);
+//				if (measDim > 2) {
+//					matPDer = matP * matDer;
+//				} else { // 'shortcut' for position measurements
+//					matPDer.Place_at(
+//							matP.Sub<SMatrix22>(3, 3)
+//									* matDer.Sub<SMatrix25>(3, 0), 3, 0);
+//				}
+//
+////				if (numInnerTrans > 0) {
+////					// transform for external parameters
+////					TMatrixD proDer(measDim, 5);
+////					// match parameters
+////					 int ifirst = 0;
+////					 int ilabel = 0;
+////					while (ilabel < 5) {
+////						if (labDer[ilabel] > 0) {
+////							while (innerTransLab[iTraj][ifirst]
+////									!= labDer[ilabel] && ifirst < 5) {
+////								++ifirst;
+////							}
+////							if (ifirst >= 5) {
+////								labDer[ilabel] -= 2 * nDim * (iTraj + 1); // adjust label
+////							} else {
+////								// match
+////								labDer[ilabel] = 0; // mark as related to external parameters
+////								for ( int k = iOff; k < 5; ++k) {
+////									proDer(k - iOff, ifirst) = matPDer(k,
+////											ilabel);
+////								}
+////							}
+////						}
+////						++ilabel;
+////					}
+////					transDer.ResizeTo(measDim, numCurvature);
+////					transDer = proDer * innerTransDer[iTraj];
+////				}
+//				for ( int i = iOff; i < 5; ++i) {
+//					if (aPrec(i) > 0.) {
+//						GblData aData(nLabel, aMeas(i), aPrec(i));
+//						aData.addDerivatives(i, labDer, matPDer, iOff, localDer,
+//								globalLab, globalDer, numLocals, transDer);
+//						theData.add(aData);
+//						nData++;
+//					}
+//				}
+//
+//			}
+//			measDataIndex[nLabel] = nData;
+//		}
+//	} // end loop over trajectories
+
+//	// pseudo measurements from kinks
+//	SMatrix22 matT;
+//	scatDataIndex[0] = nData;
[truncated at 1000 lines; 320 more skipped]

java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl
HpsGblFitter.java 918 -> 919
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/HpsGblFitter.java	2014-08-28 08:14:53 UTC (rev 918)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/HpsGblFitter.java	2014-08-28 15:31:06 UTC (rev 919)
@@ -35,249 +35,245 @@
 import org.lcsim.recon.tracking.seedtracker.SeedCandidate;
 import org.lcsim.recon.tracking.seedtracker.SeedTrack;
 
-
 /**
  * Class to running GBL on HPS track.
- * 
+ *
  * @author phansson
+ * 
+ * @version $Id:
  *
  */
 public class HpsGblFitter {
 
-	
-	private boolean _debug = false;
-	private double _B = 0.;
-	private double _bfac = 0.;
-	private boolean isMC = false;
-	TrackerHitUtils _trackHitUtils = null;
-	MultipleScattering _scattering = null;
-	private double m_chi2 = -1.;
-	private int m_ndf = -1;
-	private int m_lost_weight = -1;
-	GblTrajectory _traj = null;
-	MilleBinary _mille = null;
-	
+    private boolean _debug = true;
+    private double _B = 0.;
+    private double _bfac = 0.;
+    private boolean isMC = false;
+    TrackerHitUtils _trackHitUtils = null;
+    MultipleScattering _scattering = null;
+    private double m_chi2 = -1.;
+    private int m_ndf = -1;
+    private int m_lost_weight = -1;
+    GblTrajectory _traj = null;
+    MilleBinary _mille = null;
 
-	
-	public HpsGblFitter(double Bz, MultipleScattering scattering, boolean isMCFlag) {
-		isMC = isMCFlag;
-		_B = Bz;
-		_bfac = Bz * Constants.fieldConversion;
-		_trackHitUtils = new TrackerHitUtils();
-		_scattering = scattering;
-	}
-	
-	public void setMilleBinary(MilleBinary mille) {
-		_mille = mille;
-	}
-	
-	public void clear() {
-		m_chi2 = -1.;
-		m_ndf = -1;
-		m_lost_weight = -1;
-		_traj = null;
-	}
+    public HpsGblFitter() {
+        _B = -0.5;
+        _bfac = _B * Constants.fieldConversion;
+        _trackHitUtils = new TrackerHitUtils();
+        _scattering = new MultipleScattering(new MaterialSupervisor());
+        System.out.println("Default constructor");
+    }
 
-	public int Fit(Track track) {
-		
+    public HpsGblFitter(double Bz, MultipleScattering scattering, boolean isMCFlag) {
+        isMC = isMCFlag;
+        _B = Bz;
+        _bfac = Bz * Constants.fieldConversion;
+        _trackHitUtils = new TrackerHitUtils();
+        _scattering = scattering;
+        System.out.println("Constructor");
+    }
 
-		// Check that things are setup
-		if(_B == 0.) {
-			System.out.printf("%s: B-field not set!\n", this.getClass().getSimpleName());
-			return -1;
-		}
-		if(_scattering == null) {
-			System.out.printf("%s: Multiple scattering calculator not set!\n", this.getClass().getSimpleName());
-			return -2;
-		}
-		
-		// Time the fits
-		//clock_t startTime = clock();
+    public void setMilleBinary(MilleBinary mille) {
+        _mille = mille;
+    }
 
-		
-		
-		// path length along trajectory
-		double s = 0.;
-		// jacobian to transport errors between points along the path
-		BasicMatrix jacPointToPoint = GblUtils.getInstance().unitMatrix(5, 5);
-		// Option to use uncorrelated  MS errors
-		// This is similar to what is done in lcsim seedtracker
-		// The msCov below holds the MS errors
-		// This is for testing purposes only.
-		boolean useUncorrMS = false;
-		BasicMatrix msCov = GblUtils.getInstance().zeroMatrix(5, 5);
-		
-		// Vector of the strip clusters used for the GBL fit
-		List<GblPoint> listOfPoints = new ArrayList<GblPoint>();
-		
-		// Store the projection from local to measurement frame for each strip cluster
-		// need to use pointer for TMatrix here?
-		Map<Integer, Matrix> proL2m_list = new HashMap<Integer, Matrix>(); 
-		// Save the association between strip cluster and label	
-		Map<HelicalTrackStrip, Integer> stripLabelMap = new HashMap<HelicalTrackStrip, Integer>();
-		  
-		//start trajectory at refence point (s=0) - this point has no measurement
-		GblPoint ref_point = new GblPoint(jacPointToPoint);
-		listOfPoints.add(ref_point);
-		
-		//Create a list of all the strip clusters making up the track 
-		List<HelicalTrackStrip> stripClusters = new ArrayList<HelicalTrackStrip>();
-		SeedCandidate seed = ((SeedTrack) track).getSeedCandidate();
-		HelicalTrackFit htf = seed.getHelix();
-		List<HelicalTrackHit> stereoHits = seed.getHits();
-		for(int ihit = 0; ihit < stereoHits.size(); ++ihit) {
-			HelicalTrackCross cross = (HelicalTrackCross) stereoHits.get(ihit);
-			stripClusters.add(cross.getStrips().get(0));
-			stripClusters.add(cross.getStrips().get(1));
-		}
-		
-		// sort the clusters along path
-		// TODO use actual path length and not layer id!
-		//Collections.sort(stripClusters, new HelicalTrackStripComparer());
-		Collections.sort(stripClusters, new Comparator<HelicalTrackStrip>() {
-			public int compare(HelicalTrackStrip o1, HelicalTrackStrip o2) {
-				return o1.layer() < o2.layer() ? -1 : o1.layer() > o2.layer() ? 1 : 0;
-			}
-		});
+    public void clear() {
+        m_chi2 = -1.;
+        m_ndf = -1;
+        m_lost_weight = -1;
+        _traj = null;
+    }
 
-		if(_debug ) {
-			System.out.printf("%s: %d strip clusters:\n", stripClusters.size());
-			for(int istrip=0;istrip<stripClusters.size();++istrip) {
-				System.out.printf("%s: layer %d origin %s\n", stripClusters.get(istrip).layer(),stripClusters.get(istrip).origin().toString());
-			}
-		}
+    public int Fit(Track track) {
 
-		
-		// Find scatter points along the path of the track
+        // Check that things are setup
+        if (_B == 0.) {
+            System.out.printf("%s: B-field not set!\n", this.getClass().getSimpleName());
+            return -1;
+        }
+        if (_scattering == null) {
+            System.out.printf("%s: Multiple scattering calculator not set!\n", this.getClass().getSimpleName());
+            return -2;
+        }
+
+        // Time the fits
+        //clock_t startTime = clock();
+        // path length along trajectory
+        double s = 0.;
+        // jacobian to transport errors between points along the path
+        BasicMatrix jacPointToPoint = GblUtils.getInstance().unitMatrix(5, 5);
+        // Option to use uncorrelated  MS errors
+        // This is similar to what is done in lcsim seedtracker
+        // The msCov below holds the MS errors
+        // This is for testing purposes only.
+        boolean useUncorrMS = false;
+        BasicMatrix msCov = GblUtils.getInstance().zeroMatrix(5, 5);
+
+        // Vector of the strip clusters used for the GBL fit
+        List<GblPoint> listOfPoints = new ArrayList<GblPoint>();
+
+        // Store the projection from local to measurement frame for each strip cluster
+        // need to use pointer for TMatrix here?
+        Map<Integer, Matrix> proL2m_list = new HashMap<Integer, Matrix>();
+        // Save the association between strip cluster and label	
+        Map<HelicalTrackStrip, Integer> stripLabelMap = new HashMap<HelicalTrackStrip, Integer>();
+
+        //start trajectory at refence point (s=0) - this point has no measurement
+        GblPoint ref_point = new GblPoint(jacPointToPoint);
+        listOfPoints.add(ref_point);
+
+        //Create a list of all the strip clusters making up the track 
+        List<HelicalTrackStrip> stripClusters = new ArrayList<HelicalTrackStrip>();
+        SeedCandidate seed = ((SeedTrack) track).getSeedCandidate();
+        HelicalTrackFit htf = seed.getHelix();
+        List<HelicalTrackHit> stereoHits = seed.getHits();
+        for (int ihit = 0; ihit < stereoHits.size(); ++ihit) {
+            HelicalTrackCross cross = (HelicalTrackCross) stereoHits.get(ihit);
+            stripClusters.add(cross.getStrips().get(0));
+            stripClusters.add(cross.getStrips().get(1));
+        }
+
+        // sort the clusters along path
+        // TODO use actual path length and not layer id!
+        //Collections.sort(stripClusters, new HelicalTrackStripComparer());
+        Collections.sort(stripClusters, new Comparator<HelicalTrackStrip>() {
+            public int compare(HelicalTrackStrip o1, HelicalTrackStrip o2) {
+                return o1.layer() < o2.layer() ? -1 : o1.layer() > o2.layer() ? 1 : 0;
+            }
+        });
+
+        if (_debug) {
+            System.out.printf(" %d strip clusters:\n", stripClusters.size());
+            for (int istrip = 0; istrip < stripClusters.size(); ++istrip) {
+                System.out.printf("layer %d origin %s\n", stripClusters.get(istrip).layer(), stripClusters.get(istrip).origin().toString());
+            }
+        }
+
+        // Find scatter points along the path of the track
         ScatterPoints scatters = _scattering.FindHPSScatterPoints(htf);
-		
-		
-		if(_debug ) {
-			System.out.printf("%s: Process %d strip clusters\n", stripClusters.size());
-		}
-		for(int istrip=0;istrip<stripClusters.size();++istrip) {
-			
-			HelicalTrackStrip strip = stripClusters.get(istrip);
-			
-			if(_debug) {
-				System.out.printf("%s: layer %d origin %s\n", strip.layer(),strip.origin().toString());
-			}
-			
-			 //Find intercept point with sensor in tracking frame
+
+        if (_debug) {
+            System.out.printf(" Process %d strip clusters\n", stripClusters.size());
+        }
+        for (int istrip = 0; istrip < stripClusters.size(); ++istrip) {
+
+            HelicalTrackStrip strip = stripClusters.get(istrip);
+
+            if (_debug) {
+                System.out.printf(" layer %d origin %s\n", strip.layer(), strip.origin().toString());
+            }
+
+            //Find intercept point with sensor in tracking frame
             Hep3Vector trkpos = TrackUtils.getHelixPlaneIntercept(htf, strip, Math.abs(_B));
-            if(_debug) {
-            	System.out.printf("trkpos at intercept [%.10f %.10f %.10f]\n",trkpos.x(),trkpos.y(),trkpos.z());
+            if (_debug) {
+                System.out.printf("trkpos at intercept [%.10f %.10f %.10f]\n", trkpos.x(), trkpos.y(), trkpos.z());
             }
-            
-          //path length to intercept
-            double path = HelixUtils.PathToXPlane(htf,trkpos.x(),0,0).get(0); 
+
+            //path length to intercept
+            double path = HelixUtils.PathToXPlane(htf, trkpos.x(), 0, 0).get(0);
             double path3D = path / Math.cos(Math.atan(htf.slope()));
-            
-		    
-		    // Path length step for this cluster
-		    double step = path3D - s;
-		    
-		    if( _debug ) {
-		      System.out.printf("%s: Path length step %f from %f to %f\n",this.getClass().getSimpleName(),step, s, path3D);
-		    }
-		    
-		    // Measurement direction (perpendicular and parallel to strip direction)
-		    BasicMatrix mDir = new BasicMatrix(2,3);
-		    mDir.setElement(0, 0, strip.u().x());
-		    mDir.setElement(0, 1, strip.u().y());
-		    mDir.setElement(0, 2, strip.u().z());
-		    mDir.setElement(1, 0, strip.v().x());
-		    mDir.setElement(1, 1, strip.v().y());
-		    mDir.setElement(1, 2, strip.v().z());
-		    
-		    Matrix mDirT = MatrixOp.transposed(mDir); //new BasicMatrix(MatrixOp.transposed(mDir));
-		    if(_debug) {
-		    	System.out.printf("%s: mDir \n%s\n",this.getClass().getSimpleName(),mDir.toString());
-		    	System.out.printf("%s: mDirT \n%s\n",this.getClass().getSimpleName(),mDirT.toString());
-		    }
-		    
 
-		    // Track direction 
-		    double sinLambda = Math.sin(Math.atan(htf.slope())); 
-		    double cosLambda = Math.sqrt(1.0 - sinLambda*sinLambda);
-		    double sinPhi = Math.sin(htf.phi0());
-		    double cosPhi = Math.sqrt(1.0 - sinPhi*sinPhi);
-		    
-		    // Track direction in curvilinear frame (U,V,T)
-		    // U = Z x T / |Z x T|, V = T x U
-		    BasicMatrix uvDir = new BasicMatrix(2,3);
-		    uvDir.setElement(0, 0, -sinPhi);
-		    uvDir.setElement(0, 1, cosPhi);
-		    uvDir.setElement(0, 2, 0.);
-		    uvDir.setElement(1, 0, -sinLambda * cosPhi);
-		    uvDir.setElement(1, 1, -sinLambda * sinPhi);
-		    uvDir.setElement(1, 2, cosLambda);
-		    
-		    if(_debug) {
-		    	System.out.printf("%s: uvDir \n%s\n",this.getClass().getSimpleName(),uvDir.toString());
-		    }
+            // Path length step for this cluster
+            double step = path3D - s;
 
-		    // projection from  measurement to local (curvilinear uv) directions (duv/dm)
-		    Matrix proM2l = MatrixOp.mult(uvDir, mDirT); //uvDir * mDirT;
-		    
-		    //projection from local (curvilinear uv) to measurement directions (dm/duv)
-		    Matrix proL2m = MatrixOp.inverse(proM2l);
-		    
-		    //proL2m_list[strip->GetId()] = new TMatrixD(proL2m);
+            if (_debug) {
+                System.out.printf("%s Path length step %f from %f to %f\n", this.getClass().getSimpleName(), step, s, path3D);
+            }
 
-			if(_debug) {
-				System.out.printf("%s: proM2l \n%s\n",this.getClass().getSimpleName(),proM2l.toString());
-				System.out.printf("%s: proL2m \n%s\n",this.getClass().getSimpleName(),proL2m.toString());
-			}
-			
-			// measurement/residual in the measurement system
-		    
+            // Measurement direction (perpendicular and parallel to strip direction)
+            BasicMatrix mDir = new BasicMatrix(2, 3);
+            mDir.setElement(0, 0, strip.u().x());
+            mDir.setElement(0, 1, strip.u().y());
+            mDir.setElement(0, 2, strip.u().z());
+            mDir.setElement(1, 0, strip.v().x());
+            mDir.setElement(1, 1, strip.v().y());
+            mDir.setElement(1, 2, strip.v().z());
+
+            Matrix mDirT = MatrixOp.transposed(mDir); //new BasicMatrix(MatrixOp.transposed(mDir));
+            if (_debug) {
+                System.out.printf(" mDir \n%s\n", this.getClass().getSimpleName(), mDir.toString());
+                System.out.printf(" mDirT \n%s\n", this.getClass().getSimpleName(), mDirT.toString());
+            }
+
+            // Track direction 
+            double sinLambda = Math.sin(Math.atan(htf.slope()));
+            double cosLambda = Math.sqrt(1.0 - sinLambda * sinLambda);
+            double sinPhi = Math.sin(htf.phi0());
+            double cosPhi = Math.sqrt(1.0 - sinPhi * sinPhi);
+
+            // Track direction in curvilinear frame (U,V,T)
+            // U = Z x T / |Z x T|, V = T x U
+            BasicMatrix uvDir = new BasicMatrix(2, 3);
+            uvDir.setElement(0, 0, -sinPhi);
+            uvDir.setElement(0, 1, cosPhi);
+            uvDir.setElement(0, 2, 0.);
+            uvDir.setElement(1, 0, -sinLambda * cosPhi);
+            uvDir.setElement(1, 1, -sinLambda * sinPhi);
+            uvDir.setElement(1, 2, cosLambda);
+
+            if (_debug) {
+                System.out.printf(" uvDir \n%s\n", this.getClass().getSimpleName(), uvDir.toString());
+            }
+
+            // projection from  measurement to local (curvilinear uv) directions (duv/dm)
+            Matrix proM2l = MatrixOp.mult(uvDir, mDirT); //uvDir * mDirT;
+
+            //projection from local (curvilinear uv) to measurement directions (dm/duv)
+            Matrix proL2m = MatrixOp.inverse(proM2l);
+
+            //proL2m_list[strip->GetId()] = new TMatrixD(proL2m);
+            if (_debug) {
+                System.out.printf(" proM2l \n%s\n", this.getClass().getSimpleName(), proM2l.toString());
+                System.out.printf(" proL2m \n%s\n", this.getClass().getSimpleName(), proL2m.toString());
+            }
+
+            // measurement/residual in the measurement system
             // start by find the distance vector between the center and the track position
             Hep3Vector vdiffTrk = VecOp.sub(trkpos, strip.origin());
-            
+
             // then find the rotation from tracking to measurement frame
             Hep3Matrix trkToStripRot = _trackHitUtils.getTrackToStripRotation(strip);
-            
+
             // then rotate that vector into the measurement frame to get the predicted measurement position
             Hep3Vector trkpos_meas = VecOp.mult(trkToStripRot, vdiffTrk);
-                            
+
             // hit measurement and uncertainty in measurement frame
-            Hep3Vector m_meas = new BasicHep3Vector(strip.umeas(),0.,0.);
-            
+            Hep3Vector m_meas = new BasicHep3Vector(strip.umeas(), 0., 0.);
+
             // finally the residual
             Hep3Vector res_meas = VecOp.sub(m_meas, trkpos_meas);
-            Hep3Vector res_err_meas = new BasicHep3Vector(strip.du(),(strip.vmax() - strip.vmin()) / Math.sqrt(12),10.0/Math.sqrt(12));
+            Hep3Vector res_err_meas = new BasicHep3Vector(strip.du(), (strip.vmax() - strip.vmin()) / Math.sqrt(12), 10.0 / Math.sqrt(12));
 
             // Move to matrix objects instead of 3D vectors
             // TODO use only one type
-            
-			// only 1D measurement in u-direction, set strip measurement direction to zero
-		    BasicMatrix meas = new BasicMatrix(0,2);
-		    meas.setElement(0, 0, res_meas.x());
-		    meas.setElement(0, 1, 0.);
+            // only 1D measurement in u-direction, set strip measurement direction to zero
+            BasicMatrix meas = new BasicMatrix(1, 2);
+            meas.setElement(0, 0, res_meas.x());
+            meas.setElement(0, 1, 0.);
 //			    //meas[0][0] += deltaU[iLayer] # misalignment
 
-		    BasicMatrix measErr = new BasicMatrix(0,2);
-		    measErr.setElement(0, 0, res_err_meas.x());
-		    measErr.setElement(0, 1, 0.);
+            BasicMatrix measErr = new BasicMatrix(1, 2);
+            measErr.setElement(0, 0, res_err_meas.x());
+            measErr.setElement(0, 1, 0.);
 
-		    BasicMatrix measPrec = new BasicMatrix(0,2);
-		    measPrec.setElement(0, 0, 1.0/( measErr.e(0, 0) * measErr.e(0, 0)));
-		    measPrec.setElement(0, 1, 0.);
-		    if (_debug) {
-		    	System.out.printf("%s: meas \n%s\n",this.getClass().getSimpleName(),meas.toString());
-		    	System.out.printf("%s: measErr \n%s\n",this.getClass().getSimpleName(),measErr.toString());
-		    	System.out.printf("%s: measPrec \n%s\n",this.getClass().getSimpleName(),measPrec.toString());
+            BasicMatrix measPrec = new BasicMatrix(1, 2);
+            measPrec.setElement(0, 0, 1.0 / (measErr.e(0, 0) * measErr.e(0, 0)));
+            measPrec.setElement(0, 1, 0.);
+            if (_debug) {
+                System.out.printf("%s: meas \n%s\n", this.getClass().getSimpleName(), meas.toString());
+                System.out.printf("%s: measErr \n%s\n", this.getClass().getSimpleName(), measErr.toString());
+                System.out.printf("%s: measPrec \n%s\n", this.getClass().getSimpleName(), measPrec.toString());
             }
 
             //Find the Jacobian to be able to propagate the covariance matrix to this strip position
             jacPointToPoint = GblUtils.getInstance().gblSimpleJacobianLambdaPhi(step, cosLambda, Math.abs(_bfac));
-            
-            if(_debug) {
-				System.out.printf("%s: jacPointToPoint \n%s\n",this.getClass().getSimpleName(),jacPointToPoint.toString());
+
+            if (_debug) {
+                System.out.printf("%s: jacPointToPoint \n%s\n", this.getClass().getSimpleName(), jacPointToPoint.toString());
             }
-            
-          //propagate MS covariance matrix (in the curvilinear frame) to this strip position
+
+            //propagate MS covariance matrix (in the curvilinear frame) to this strip position
             //msCov = np.dot(jacPointToPoint, np.dot(msCov, jacPointToPoint.T))
             //measMsCov = np.dot(proL2m, np.dot(msCov[3:, 3:], proL2m.T))
 //                if (m_debug) {
@@ -286,187 +282,172 @@
 //                  //cout << "HpsGblFitter: " << "measMsCov at this point:" << endl;
 //                  //measMsCov.Print();
 //                }
-            
             //Option to blow up measurement error according to multiple scattering
             //if useUncorrMS:
             //measPrec[0] = 1.0 / (measErr[0] ** 2 + measMsCov[0, 0])
             //  if debug:
             //print 'Adding measMsCov ', measMsCov[0,0]
-                
             // point with independent measurement
             GblPoint point = new GblPoint(jacPointToPoint);
 
             //Add measurement to the point
-            point.addMeasurement(proL2m,meas,measPrec);
+            point.addMeasurement(proL2m, meas, measPrec);
 
-            
             //Add scatterer in curvilinear frame to the point
             // no direction in this frame as it moves along the track
-            BasicMatrix scat = GblUtils.getInstance().zeroMatrix(0,2);
+            BasicMatrix scat = GblUtils.getInstance().zeroMatrix(0, 2);
 
             // find scattering angle
-            ScatterPoint scatter = scatters.getScatterPoint(((RawTrackerHit)strip.rawhits().get(0)).getDetectorElement());
+            ScatterPoint scatter = scatters.getScatterPoint(((RawTrackerHit) strip.rawhits().get(0)).getDetectorElement());
             double scatAngle;
-         
-            if(scatter != null) {
-            	scatAngle = scatter.getScatterAngle().Angle();
-            }	
-            else {
-                System.out.printf("%s: WARNING cannot find scatter for detector %s with strip cluster at %s\n",this.getClass(),((RawTrackerHit)strip.rawhits().get(0)).getDetectorElement().getName(),strip.origin().toString());
+
+            if (scatter != null) {
+                scatAngle = scatter.getScatterAngle().Angle();
+            } else {
+                System.out.printf("%s: WARNING cannot find scatter for detector %s with strip cluster at %s\n", this.getClass(), ((RawTrackerHit) strip.rawhits().get(0)).getDetectorElement().getName(), strip.origin().toString());
                 //can be edge case where helix is outside, but close to sensor, so use hack with the sensor origin closest to hit
                 //TODO check if this really makes sense to do
                 DetectorPlane closest = null;
                 double dx = 999999.9;
-                if(MaterialSupervisor.class.isInstance(_scattering.getMaterialManager())) {
-                    MaterialSupervisor matSup = (MaterialSupervisor)_scattering.getMaterialManager();
-                    for(ScatteringDetectorVolume vol : matSup.getMaterialVolumes()) {
-                        DetectorPlane plane = (DetectorPlane)vol;
+                if (MaterialSupervisor.class.isInstance(_scattering.getMaterialManager())) {
+                    MaterialSupervisor matSup = (MaterialSupervisor) _scattering.getMaterialManager();
+                    for (ScatteringDetectorVolume vol : matSup.getMaterialVolumes()) {
+                        DetectorPlane plane = (DetectorPlane) vol;
                         double dx_loop = Math.abs(strip.origin().x() - plane.origin().x());
-                        if(dx_loop<dx) {
+                        if (dx_loop < dx) {
                             dx = dx_loop;
                             closest = plane;
                         }
                     }
-                    if(closest==null) {
+                    if (closest == null) {
                         throw new RuntimeException("cannot find any plane that is close to strip!");
                     } else {
                         // find scatterlength
-                        double s_closest = HelixUtils.PathToXPlane(htf,closest.origin().x(), 0., 0).get(0);
+                        double s_closest = HelixUtils.PathToXPlane(htf, closest.origin().x(), 0., 0).get(0);
                         double X0 = closest.getMaterialTraversedInRL(HelixUtils.Direction(htf, s_closest));
-                        ScatterAngle scatterAngle = new ScatterAngle(s_closest, _scattering.msangle(htf.p(Math.abs(_B)),X0));
+                        ScatterAngle scatterAngle = new ScatterAngle(s_closest, _scattering.msangle(htf.p(Math.abs(_B)), X0));
                         scatAngle = scatterAngle.Angle();
                     }
-                } 
-                else {
+                } else {
                     throw new UnsupportedOperationException("Should not happen. This problem is only solved with the MaterialSupervisor.");
                 }
             }
-            
-            
+
             // Scattering angle in the curvilinear frame
             //Note the cosLambda to correct for the projection in the phi direction
-            BasicMatrix scatErr = new BasicMatrix(0,2);
+            BasicMatrix scatErr = new BasicMatrix(1, 2);
             scatErr.setElement(0, 0, scatAngle);
             scatErr.setElement(0, 1, scatAngle / cosLambda);
-            BasicMatrix scatPrec = new BasicMatrix(0,2);
+            BasicMatrix scatPrec = new BasicMatrix(1, 2);
             scatPrec.setElement(0, 0, 1.0 / (scatErr.e(0, 0) * scatErr.e(0, 0)));
             scatPrec.setElement(0, 1, 1.0 / (scatErr.e(0, 1) * scatErr.e(0, 1)));
-            
+
             // add scatterer if not using the uncorrelated MS covariances for testing
-            if (! useUncorrMS) {
-              point.addScatterer(scat, scatPrec);
-              if (_debug) {
-            	  System.out.printf("%s: scatError to this point \n%s\n",this.getClass().getSimpleName(),scatErr.toString());
-              }
+            if (!useUncorrMS) {
+                point.addScatterer(scat, scatPrec);
+                if (_debug) {
+                    System.out.printf("%s: scatError to this point \n%s\n", this.getClass().getSimpleName(), scatErr.toString());
+                }
             }
-			
+
             // Add this GBL point to list that will be used in fit
             listOfPoints.add(point);
             int iLabel = listOfPoints.size();
-            
+
             // Update MS covariance matrix 
-            msCov.setElement(1, 1, msCov.e(1, 1) + scatErr.e(0, 0)*scatErr.e(0, 0));
-            msCov.setElement(2, 2, msCov.e(2, 2) + scatErr.e(0, 1)*scatErr.e(0, 1));
-            
-            
-            
+            msCov.setElement(1, 1, msCov.e(1, 1) + scatErr.e(0, 0) * scatErr.e(0, 0));
+            msCov.setElement(2, 2, msCov.e(2, 2) + scatErr.e(0, 1) * scatErr.e(0, 1));
+
             /*
 
-            ##### 
-            ## Calculate global derivatives for this point
-            # track direction in tracking/global frame
-            tDirGlobal = np.array( [ [cosPhi * cosLambda, sinPhi * cosLambda, sinLambda] ] )        
-            # Cross-check that the input is consistent
-            if( np.linalg.norm( tDirGlobal - strip.tDir) > 0.00001):
-              print 'ERROR: tDirs are not consistent!'
-              sys.exit(1)
-            # rotate track direction to measurement frame          
-            tDirMeas = np.dot( tDirGlobal, np.array([strip.u, strip.v, strip.w]) )
-            #tDirMeas = utils.rotateGlToMeas(strip,tDirGlobal)
-            normalMeas = np.dot( strip.w , np.array([strip.u, strip.v, strip.w]) ) 
-            #normalMeas = utils.rotateGlToMeas(strip,strip.w) 
-            # non-measured directions 
-            vmeas = 0.
-            wmeas = 0.
-            # calculate and add derivatives to point
-            glDers = utils.globalDers(strip.layer,strip.meas,vmeas,wmeas,tDirMeas,normalMeas)
-            ders = glDers.getDers(track.isTop())
-            labGlobal = ders['labels']
-            addDer = ders['ders']
-            if debug:
-              print 'global derivatives:'
-              print labGlobal
-              print addDer
-            point.addGlobals(labGlobal, addDer)
-            ##### 
+             ##### 
+             ## Calculate global derivatives for this point
+             # track direction in tracking/global frame
+             tDirGlobal = np.array( [ [cosPhi * cosLambda, sinPhi * cosLambda, sinLambda] ] )        
+             # Cross-check that the input is consistent
+             if( np.linalg.norm( tDirGlobal - strip.tDir) > 0.00001):
+             print 'ERROR: tDirs are not consistent!'
+             sys.exit(1)
+             # rotate track direction to measurement frame          
+             tDirMeas = np.dot( tDirGlobal, np.array([strip.u, strip.v, strip.w]) )
+             #tDirMeas = utils.rotateGlToMeas(strip,tDirGlobal)
+             normalMeas = np.dot( strip.w , np.array([strip.u, strip.v, strip.w]) ) 
+             #normalMeas = utils.rotateGlToMeas(strip,strip.w) 
+             # non-measured directions 
+             vmeas = 0.
+             wmeas = 0.
+             # calculate and add derivatives to point
+             glDers = utils.globalDers(strip.layer,strip.meas,vmeas,wmeas,tDirMeas,normalMeas)
+             ders = glDers.getDers(track.isTop())
+             labGlobal = ders['labels']
+             addDer = ders['ders']
+             if debug:
+             print 'global derivatives:'
+             print labGlobal
+             print addDer
+             point.addGlobals(labGlobal, addDer)
+             ##### 
 
              */
-            
-        
-
             //move on to next point
             s += step;
-        
+
             // save strip and label map
             //stripLabelMap[strip] = iLabel;
+        }
+
+        //create the trajectory
+        _traj = new GblTrajectory(listOfPoints); //,seedLabel, clSeed);
+
+        if (!_traj.isValid()) {
+            System.out.printf("%s:  Invalid GblTrajectory -> skip \n", this.getClass().getSimpleName());
+            return -3;
+        }
+
+        // fit trajectory
+        _traj.fit(m_chi2, m_ndf, m_lost_weight);
         
-        
-          
+        //cng
+//        System.out.println("fitting the traectory...");
+//        double[] retDVals = new double[2];
+//        int[] retIVals = new int[1];
+//        int success = _traj.fit(retDVals, retIVals, "");
+        //cng
 
-            
-            
-            
-		}
-	
+        if (_debug) {
+            System.out.printf("%s:  Chi2  Fit: %f , %d , %d\n", this.getClass().getSimpleName(), m_chi2, m_ndf, m_lost_weight);
+        }
 
-		//create the trajectory
-		_traj = new GblTrajectory(listOfPoints); //,seedLabel, clSeed);
-			  
-		if (! _traj.isValid()) {
-			System.out.printf("%s:  Invalid GblTrajectory -> skip \n",this.getClass().getSimpleName());
-			return -3;
-		}
-		
-		// fit trajectory
-		_traj.fit(m_chi2, m_ndf, m_lost_weight);
-		
-		if( _debug ) {
-			System.out.printf("%s:  Chi2  Fit: %f , %d , %d\n",this.getClass().getSimpleName(), m_chi2, m_ndf,m_lost_weight);
-		}
-		
-		// write to MP binary file
-		if(_mille != null) {
-			_traj.milleOut(_mille);
-		}
-		
-		//stop the clock
-		//clock_t endTime = clock();
-		//double diff = endTime - startTime;
-		//double cps = CLOCKS_PER_SEC;
-		//if( m_debug ) {
-		//	std::cout << "HpsGblFitter: " << " Time elapsed " << diff / cps << " s" << std::endl;
-		//}
+        // write to MP binary file
+        if (_mille != null) {
+            _traj.milleOut(_mille);
+        }
 
-		if(_debug) {
-			System.out.printf("%s:  Fit() done successfully.\n",this.getClass().getSimpleName());
-		}
-		
-		return 0;
-	}
-	
+        //stop the clock
+        //clock_t endTime = clock();
+        //double diff = endTime - startTime;
+        //double cps = CLOCKS_PER_SEC;
+        //if( m_debug ) {
+        //	std::cout << "HpsGblFitter: " << " Time elapsed " << diff / cps << " s" << std::endl;
+        //}
+        if (_debug) {
+            System.out.printf("%s:  Fit() done successfully.\n", this.getClass().getSimpleName());
+        }
 
-	public static class HelicalTrackStripComparer implements Comparator<HelicalTrackStrip> {
-		public int compare(HelicalTrackStrip o1, HelicalTrackStrip o2) {
-			// TODO Change this to path length!?
-			return compare(o1.layer(),o2.layer());
-		}
-	
-		private static int compare(int s1, int s2) {
-			return s1 < s2 ? -1 : s2 > s1 ? 1 : 0;
-		}
-	
-	
-	}
+        return 0;
+    }
 
+    public static class HelicalTrackStripComparer implements Comparator<HelicalTrackStrip> {
 
+        public int compare(HelicalTrackStrip o1, HelicalTrackStrip o2) {
+            // TODO Change this to path length!?
+            return compare(o1.layer(), o2.layer());
+        }
+
+        private static int compare(int s1, int s2) {
+            return s1 < s2 ? -1 : s2 > s1 ? 1 : 0;
+        }
+
+    }
+
 }

java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix
BorderedBandMatrix.java added at 919
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/BorderedBandMatrix.java	                        (rev 0)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/BorderedBandMatrix.java	2014-08-28 15:31:06 UTC (rev 919)
@@ -0,0 +1,360 @@
+package org.hps.recon.tracking.gbl.matrix;
+
+import static java.lang.Math.abs;
+import static java.lang.Math.min;
+import static java.lang.Math.max;
+
+/**
+ *
+ * @author Norman A. Graf
+ *
+ * @version $Id$
+ */
+/// (Symmetric) Bordered Band Matrix.
+/**
+ * Separate storage of border, mixed and band parts (as vector<double>).
+ *
+ * \verbatim Example for matrix size=8 with border size and band width of two
+ *
+ * +- -+ | B11 B12 M13 M14 M15 M16 M17 M18 | | B12 B22 M23 M24 M25 M26 M27 M28 |
+ * | M13 M23 C33 C34 C35 0. 0. 0. | | M14 M24 C34 C44 C45 C46 0. 0. | | M15 M25
+ * C35 C45 C55 C56 C57 0. | | M16 M26 0. C46 C56 C66 C67 C68 | | M17 M27 0. 0.
+ * C57 C67 C77 C78 | | M18 M28 0. 0. 0. C68 C78 C88 | +- -+
+ *
+ * Is stored as::
+ *
+ * +- -+ +- -+ | B11 B12 | | M13 M14 M15 M16 M17 M18 | | B12 B22 | | M23 M24 M25
+ * M26 M27 M28 | +- -+ +- -+
+ *
+ * +- -+ | C33 C44 C55 C66 C77 C88 | | C34 C45 C56 C67 C78 0. | | C35 C46 C57
+ * C68 0. 0. | +- -+ \endverbatim
+ */
+public class BorderedBandMatrix
+{
+
+    private int numSize; ///< Matrix size
+    private int numBorder; ///< Border size
+    private int numBand; ///< Band width
+    private int numCol; ///< Band matrix size
+    private VSymMatrix theBorder = new VSymMatrix(0); ///< Border part
+    private VMatrix theMixed = new VMatrix(0,0); ///< Mixed part
+    private VMatrix theBand = new VMatrix(0,0); ///< Band part
+
+/// Resize bordered band matrix.
+    /**
+     * \param nSize [in] Size of matrix \param nBorder [in] Size of border (=1
+     * for q/p + additional local parameters) \param nBand [in] Band width
+     * (usually = 5, for simplified jacobians = 4)
+     */
+    public void resize(int nSize, int nBorder, int nBand)
+    {
+        numSize = nSize;
+        numBorder = nBorder;
+        numCol = nSize - nBorder;
+        numBand = 0;
+        theBorder.resize(numBorder);
+        theMixed.resize(numBorder, numCol);
+        theBand.resize((nBand + 1), numCol);
+    }
+
+/// Add symmetric block matrix.
+    /**
+     * Add (extended) block matrix defined by 'aVector * aWeight * aVector.T' to
+     * bordered band matrix: BBmatrix(anIndex(i),anIndex(j)) += aVector(i) *
+     * aWeight * aVector(j). \param aWeight [in] Weight \param anIndex [in] List
+     * of rows/colums to be used \param aVector [in] Vector
+     */
+    public void addBlockMatrix(double aWeight,
+            int[] anIndex,
+            double[] aVector)
+    {
+        int nBorder = numBorder;
+        for (int i = 0; i < anIndex.length; ++i)
+        {
+            int iIndex = (anIndex)[i] - 1; // anIndex has to be sorted
+            for (int j = 0; j <= i; ++j)
+            {
+                int jIndex = (anIndex)[j] - 1;
+                if (iIndex < nBorder)
+                {
+                    theBorder.addTo(iIndex, jIndex, aVector[i] * aWeight
+                            * aVector[j]);
+                } else if (jIndex < nBorder)
+                {
+                    theMixed.addTo(jIndex, iIndex - nBorder, aVector[i] * aWeight
+                            * aVector[j]);
+                } else
+                {
+                    int nBand = iIndex - jIndex;
+                    theBand.addTo(nBand, jIndex - nBorder, aVector[i] * aWeight
+                            * aVector[j]);
+                    numBand = max(numBand, nBand); // update band width
+                }
+            }
+        }
+    }
+
+///// Retrieve symmetric block matrix.
+///**
+// * Get (compressed) block from bordered band matrix: aMatrix(i,j) = BBmatrix(anIndex(i),anIndex(j)).
+// * \param anIndex [in] List of rows/colums to be used
+// */
+//TMatrixDSym BorderedBandMatrix::getBlockMatrix(
+//		const std::vector<unsigned int> anIndex) const {
+//
+//	TMatrixDSym aMatrix(anIndex.size());
+//	int nBorder = numBorder;
+//	for (unsigned int i = 0; i < anIndex.size(); ++i) {
+//		int iIndex = anIndex[i] - 1; // anIndex has to be sorted
+//		for (unsigned int j = 0; j <= i; ++j) {
+//			int jIndex = anIndex[j] - 1;
+//			if (iIndex < nBorder) {
+//				aMatrix(i, j) = theBorder(iIndex, jIndex); // border part of inverse
+//			} else if (jIndex < nBorder) {
+//				aMatrix(i, j) = -theMixed(jIndex, iIndex - nBorder); // mixed part of inverse
+//			} else {
+//				unsigned int nBand = iIndex - jIndex;
+//				aMatrix(i, j) = theBand(nBand, jIndex - nBorder); // band part of inverse
+//			}
+//			aMatrix(j, i) = aMatrix(i, j);
+//		}
+//	}
+//	return aMatrix;
+//}    
+/// Solve linear equation system, partially calculate inverse.
+    /**
+     * Solve linear equation A*x=b system with bordered band matrix A, calculate
+     * bordered band part of inverse of A. Use decomposition in border and band
+     * part for block matrix algebra:
+     *
+     * | A Ct | | x1 | | b1 | , A is the border part | | * | | = | | , Ct is the
+     * mixed part | C D | | x2 | | b2 | , D is the band part
+     *
+     * Explicit inversion of D is avoided by using solution X of D*X=C
+     * (X=D^-1*C, obtained from Cholesky decomposition and forward/backward
+     * substitution)
+     *
+     * | x1 | | E*b1 - E*Xt*b2 | , E^-1 = A-Ct*D^-1*C = A-Ct*X | | = | | | x2 |
+     * | x - X*x1 | , x is solution of D*x=b2 (x=D^-1*b2)
+     *
+     * Inverse matrix is:
+     *
+     * | E -E*Xt | | | , only band part of (D^-1 + X*E*Xt) | -X*E D^-1 + X*E*Xt
+     * | is calculated
+     *
+     *
+     * \param [in] aRightHandSide Right hand side (vector) 'b' of A*x=b \param
+     * [out] aSolution Solution (vector) x of A*x=b
+     */
+public void  solveAndInvertBorderedBand(
+		  VVector aRightHandSide, VVector aSolution) {
+
+	// decompose band
+	decomposeBand();
+	// invert band
+	VMatrix inverseBand = invertBand();
+	if (numBorder > 0) { // need to use block matrix decomposition to solve
+		// solve for mixed part
+		 VMatrix auxMat = solveBand(theMixed); // = Xt
+		 VMatrix auxMatT = auxMat.transpose(); // = X
+		// solve for border part
+		 VVector auxVec = aRightHandSide.getVec(numBorder,0).minus(
+				auxMat.times( aRightHandSide.getVec(numCol, numBorder) ) ); // = b1 - Xt*b2
+		VSymMatrix inverseBorder = theBorder.minus(theMixed.times(auxMatT) );
+		inverseBorder.invert(); // = E
+		 VVector borderSolution = inverseBorder.times(auxVec); // = x1
+		// solve for band part
+		 VVector bandSolution = solveBand(
+				aRightHandSide.getVec(numCol, numBorder)); // = x
+		aSolution.putVec(borderSolution,0);
+		aSolution.putVec(bandSolution.minus(auxMatT.times(borderSolution)), numBorder); // = x2
+		// parts of inverse
+		theBorder = inverseBorder; // E
+		theMixed = inverseBorder.times(auxMat); // E*Xt (-mixed part of inverse) !!!
+		theBand = inverseBand.plus(bandOfAVAT(auxMatT, inverseBorder)); // band(D^-1 + X*E*Xt)
+	} else {
+		aSolution.putVec(solveBand(aRightHandSide),0);
+		theBand = inverseBand;
+	}
+}
+/// Print bordered band matrix.
+    public void printMatrix()
+    {
+        System.out.println("Border part ");
+        theBorder.print();
+        System.out.println("Mixed  part ");
+        theMixed.print();
+        System.out.println("Band   part ");
+        theBand.print();
+    }
+
+    /*============================================================================
+     from Dbandmatrix.F (MillePede-II by V. Blobel, Univ. Hamburg)
+     ============================================================================*/
+/// (root free) Cholesky decomposition of band part: C=LDL^T
+    /**
+     * Decompose band matrix into diagonal matrix D and lower triangular band
+     * matrix L (diagonal=1). Overwrite band matrix with D and off-diagonal part
+     * of L. \exception 2 : matrix is singular. \exception 3 : matrix is not
+     * positive definite.
+     */
+    private void decomposeBand()
+    {
+
+        int nRow = numBand + 1;
+        int nCol = numCol;
+        VVector auxVec = new VVector(nCol);
+        for (int i = 0; i < nCol; ++i)
+        {
+            auxVec.set(i, theBand.get(0, i) * 16.0); // save diagonal elements
+        }
+        for (int i = 0; i < nCol; ++i)
+        {
+            if ((theBand.get(0, i) + auxVec.get(i)) != theBand.get(0, i))
+            {
+                theBand.set(0, i, 1.0 / theBand.get(0, i));
+                if (theBand.get(0, i) < 0.)
+                {
+                    throw new RuntimeException("BorderedBandMatrix decomposeBand not positive definite");
+                }
+            } else
+            {
+                theBand.set(0, i, 0.0);
+                throw new RuntimeException("BorderedBandMatrix decomposeBand singular");
+            }
+            for (int j = 1; j < min(nRow, nCol - i); ++j)
+            {
+                double rxw = theBand.get(j, i) * theBand.get(0, i);
+                for (int k = 0; k < min(nRow, nCol - i) - j; ++k)
+                {
+                    theBand.subFrom(k, i + j, theBand.get(k + j, i) * rxw);
+                }
+                theBand.set(j, i, rxw);
+            }
+        }
+    }
+
+/// Invert band part.
+    /**
+     * \return Inverted band
+     */
+    private VMatrix invertBand()
+    {
+
+        int nRow = numBand + 1;
+        int nCol = numCol;
+        VMatrix inverseBand = new VMatrix(nRow, nCol);
+
+        for (int i = nCol - 1; i >= 0; i--)
+        {
+            double rxw = theBand.get(0, i);
+            for (int j = i; j >= max(0, i - nRow + 1); j--)
+            {
+                for (int k = j + 1; k < min(nCol, j + nRow); ++k)
+                {
+                    rxw -= inverseBand.get(abs(i - k), min(i, k))
+                            * theBand.get(k - j, j);
+                }
+                inverseBand.set(i - j, j, rxw);
+                rxw = 0.;
+            }
+        }
+        return inverseBand;
+    }
+
+/// Solve for band part.
+    /**
+     * Solve C*x=b for band part using decomposition C=LDL^T and forward (L*z=b)
+     * and backward substitution (L^T*x=D^-1*z). \param [in] aRightHandSide
+     * Right hand side (vector) 'b' of C*x=b \return Solution (vector) 'x' of
+     * C*x=b
+     */
+    private VVector solveBand(VVector aRightHandSide)
+    {
+
+        int nRow = theBand.getNumRows();
+        int nCol = theBand.getNumCols();
+        VVector aSolution = new VVector(aRightHandSide);
+        for (int i = 0; i < nCol; ++i) // forward substitution
+        {
+            for (int j = 1; j < min(nRow, nCol - i); ++j)
+            {
+                aSolution.subFrom(j + i, theBand.get(j, i) * aSolution.get(i));
+            }
+        }
+        for (int i = nCol - 1; i >= 0; i--) // backward substitution
+        {
+            double rxw = theBand.get(0, i) * aSolution.get(i);
+            for (int j = 1; j < min(nRow, nCol - i); ++j)
+            {
+                rxw -= theBand.get(j, i) * aSolution.get(j + i);
+            }
+            aSolution.set(i, rxw);
+        }
+        return aSolution;
+    }
+
+/// solve band part for mixed part (border rows).
+    /**
+     * Solve C*X=B for mixed part using decomposition C=LDL^T and forward and
+     * backward substitution. \param [in] aRightHandSide Right hand side
+     * (matrix) 'B' of C*X=B \return Solution (matrix) 'X' of C*X=B
+     */
+    private VMatrix solveBand(VMatrix aRightHandSide)
+    {
+
+        int nRow = theBand.getNumRows();
+        int nCol = theBand.getNumCols();
+        VMatrix aSolution = new VMatrix(aRightHandSide);
+        for (int iBorder = 0; iBorder < numBorder; iBorder++)
+        {
+            for (int i = 0; i < nCol; ++i) // forward substitution
+            {
+                for (int j = 1; j < min(nRow, nCol - i); ++j)
+                {
+                    aSolution.subFrom(iBorder, j + i, theBand.get(j, i)
+                            * aSolution.get(iBorder, i));
+                }
+            }
+            for (int i = nCol - 1; i >= 0; i--) // backward substitution
+            {
+                double rxw = theBand.get(0, i) * aSolution.get(iBorder, i);
+                for (int j = 1; j < min(nRow, nCol - i); ++j)
+                {
+                    rxw -= theBand.get(j, i) * aSolution.get(iBorder, j + i);
+                }
+                aSolution.set(iBorder, i, rxw);
+            }
+        }
+        return aSolution;
+    }
+
+
+    /// Calculate band part of: 'anArray * aSymArray * anArray.T'.
+/**
+ * \return Band part of product
+ */
+private VMatrix bandOfAVAT( VMatrix anArray,
+		 VSymMatrix aSymArray)  {
+	int nBand = numBand;
+	int nCol = numCol;
+	int nBorder = numBorder;
+	double sum;
+	VMatrix aBand = new VMatrix((nBand + 1), nCol);
+	for (int i = 0; i < nCol; ++i) {
+		for (int j = max(0, i - nBand); j <= i; ++j) {
+			sum = 0.;
+			for (int l = 0; l < nBorder; ++l) { // diagonal
+				sum += anArray.get(i, l) * aSymArray.get(l, l) * anArray.get(j, l);
+				for (int k = 0; k < l; ++k) { // off diagonal
+					sum += anArray.get(i, l) * aSymArray.get(l, k) * anArray.get(j, k)
+							+ anArray.get(i, k) * aSymArray.get(l, k) * anArray.get(j, l);
+				}
+			}
+			aBand.set(i - j, j, sum);
+		}
+	}
+	return aBand;
+}
+    
+}

java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix
EigenvalueDecomposition.java added at 919
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/EigenvalueDecomposition.java	                        (rev 0)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/EigenvalueDecomposition.java	2014-08-28 15:31:06 UTC (rev 919)
@@ -0,0 +1,959 @@
+package org.hps.recon.tracking.gbl.matrix;
+
+/** Eigenvalues and eigenvectors of a real matrix. 
+<P>
+    If A is symmetric, then A = V*D*V' where the eigenvalue matrix D is
+    diagonal and the eigenvector matrix V is orthogonal.
+    I.e. A = V.times(D.times(V.transpose())) and 
+    V.times(V.transpose()) equals the identity matrix.
+<P>
+    If A is not symmetric, then the eigenvalue matrix D is block diagonal
+    with the real eigenvalues in 1-by-1 blocks and any complex eigenvalues,
+    lambda + i*mu, in 2-by-2 blocks, [lambda, mu; -mu, lambda].  The
+    columns of V represent the eigenvectors in the sense that A*V = V*D,
+    i.e. A.times(V) equals V.times(D).  The matrix V may be badly
+    conditioned, or even singular, so the validity of the equation
+    A = V*D*inverse(V) depends upon V.cond().
+    @version $Id: EigenvalueDecomposition.java,v 1.1.1.1 2010/11/30 21:31:59 jeremy Exp $
+*/
+
+public class EigenvalueDecomposition implements java.io.Serializable {
+
+/* ------------------------
+   Class variables
+ * ------------------------ */
+
+   /** Row and column dimension (square matrix).
+   @serial matrix dimension.
+   */
+   private int n;
+
+   /** Symmetry flag.
+   @serial internal symmetry flag.
+   */
+   private boolean issymmetric;
+
+   /** Arrays for internal storage of eigenvalues.
+   @serial internal storage of eigenvalues.
+   */
+   private double[] d, e;
+
+   /** Array for internal storage of eigenvectors.
+   @serial internal storage of eigenvectors.
+   */
+   private double[][] V;
+
+   /** Array for internal storage of nonsymmetric Hessenberg form.
+   @serial internal storage of nonsymmetric Hessenberg form.
+   */
+   private double[][] H;
+
+   /** Working storage for nonsymmetric algorithm.
+   @serial working storage for nonsymmetric algorithm.
+   */
+   private double[] ort;
+
+/* ------------------------
+   Private Methods
+ * ------------------------ */
+
+   // Symmetric Householder reduction to tridiagonal form.
+
+   private void tred2 () {
+
+   //  This is derived from the Algol procedures tred2 by
+   //  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
+   //  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
+   //  Fortran subroutine in EISPACK.
+
+      for (int j = 0; j < n; j++) {
+         d[j] = V[n-1][j];
+      }
+
+      // Householder reduction to tridiagonal form.
+   
+      for (int i = n-1; i > 0; i--) {
+   
+         // Scale to avoid under/overflow.
+   
+         double scale = 0.0;
+         double h = 0.0;
+         for (int k = 0; k < i; k++) {
+            scale = scale + Math.abs(d[k]);
+         }
+         if (scale == 0.0) {
+            e[i] = d[i-1];
+            for (int j = 0; j < i; j++) {
+               d[j] = V[i-1][j];
+               V[i][j] = 0.0;
+               V[j][i] = 0.0;
+            }
+         } else {
+   
+            // Generate Householder vector.
+   
+            for (int k = 0; k < i; k++) {
+               d[k] /= scale;
+               h += d[k] * d[k];
+            }
+            double f = d[i-1];
+            double g = Math.sqrt(h);
+            if (f > 0) {
+               g = -g;
+            }
+            e[i] = scale * g;
+            h = h - f * g;
+            d[i-1] = f - g;
+            for (int j = 0; j < i; j++) {
+               e[j] = 0.0;
+            }
+   
+            // Apply similarity transformation to remaining columns.
+   
+            for (int j = 0; j < i; j++) {
+               f = d[j];
+               V[j][i] = f;
+               g = e[j] + V[j][j] * f;
+               for (int k = j+1; k <= i-1; k++) {
+                  g += V[k][j] * d[k];
+                  e[k] += V[k][j] * f;
+               }
+               e[j] = g;
+            }
+            f = 0.0;
+            for (int j = 0; j < i; j++) {
+               e[j] /= h;
+               f += e[j] * d[j];
+            }
+            double hh = f / (h + h);
+            for (int j = 0; j < i; j++) {
+               e[j] -= hh * d[j];
+            }
+            for (int j = 0; j < i; j++) {
+               f = d[j];
+               g = e[j];
+               for (int k = j; k <= i-1; k++) {
+                  V[k][j] -= (f * e[k] + g * d[k]);
+               }
+               d[j] = V[i-1][j];
+               V[i][j] = 0.0;
+            }
+         }
+         d[i] = h;
+      }
+   
+      // Accumulate transformations.
+   
+      for (int i = 0; i < n-1; i++) {
+         V[n-1][i] = V[i][i];
+         V[i][i] = 1.0;
+         double h = d[i+1];
+         if (h != 0.0) {
+            for (int k = 0; k <= i; k++) {
+               d[k] = V[k][i+1] / h;
+            }
+            for (int j = 0; j <= i; j++) {
+               double g = 0.0;
+               for (int k = 0; k <= i; k++) {
+                  g += V[k][i+1] * V[k][j];
+               }
+               for (int k = 0; k <= i; k++) {
+                  V[k][j] -= g * d[k];
+               }
+            }
+         }
+         for (int k = 0; k <= i; k++) {
+            V[k][i+1] = 0.0;
+         }
+      }
+      for (int j = 0; j < n; j++) {
+         d[j] = V[n-1][j];
+         V[n-1][j] = 0.0;
+      }
+      V[n-1][n-1] = 1.0;
+      e[0] = 0.0;
+   } 
+
+   // Symmetric tridiagonal QL algorithm.
+   
+   private void tql2 () {
+
+   //  This is derived from the Algol procedures tql2, by
+   //  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
+   //  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
+   //  Fortran subroutine in EISPACK.
+   
+      for (int i = 1; i < n; i++) {
+         e[i-1] = e[i];
+      }
+      e[n-1] = 0.0;
+   
+      double f = 0.0;
+      double tst1 = 0.0;
+      double eps = Math.pow(2.0,-52.0);
+      for (int l = 0; l < n; l++) {
+
+         // Find small subdiagonal element
+   
+         tst1 = Math.max(tst1,Math.abs(d[l]) + Math.abs(e[l]));
+         int m = l;
+         while (m < n) {
+            if (Math.abs(e[m]) <= eps*tst1) {
+               break;
+            }
+            m++;
+         }
+   
+         // If m == l, d[l] is an eigenvalue,
+         // otherwise, iterate.
+   
+         if (m > l) {
+            int iter = 0;
+            do {
+               iter = iter + 1;  // (Could check iteration count here.)
+   
+               // Compute implicit shift
+   
+               double g = d[l];
+               double p = (d[l+1] - g) / (2.0 * e[l]);
+               double r = Matrix.hypot(p,1.0);
+               if (p < 0) {
+                  r = -r;
+               }
+               d[l] = e[l] / (p + r);
+               d[l+1] = e[l] * (p + r);
+               double dl1 = d[l+1];
+               double h = g - d[l];
+               for (int i = l+2; i < n; i++) {
+                  d[i] -= h;
+               }
+               f = f + h;
+   
+               // Implicit QL transformation.
+   
+               p = d[m];
+               double c = 1.0;
+               double c2 = c;
+               double c3 = c;
+               double el1 = e[l+1];
+               double s = 0.0;
+               double s2 = 0.0;
+               for (int i = m-1; i >= l; i--) {
+                  c3 = c2;
+                  c2 = c;
+                  s2 = s;
+                  g = c * e[i];
+                  h = c * p;
+                  r = Matrix.hypot(p,e[i]);
+                  e[i+1] = s * r;
+                  s = e[i] / r;
+                  c = p / r;
+                  p = c * d[i] - s * g;
+                  d[i+1] = h + s * (c * g + s * d[i]);
+   
+                  // Accumulate transformation.
+   
+                  for (int k = 0; k < n; k++) {
+                     h = V[k][i+1];
+                     V[k][i+1] = s * V[k][i] + c * h;
+                     V[k][i] = c * V[k][i] - s * h;
+                  }
+               }
+               p = -s * s2 * c3 * el1 * e[l] / dl1;
+               e[l] = s * p;
+               d[l] = c * p;
+   
+               // Check for convergence.
+   
+            } while (Math.abs(e[l]) > eps*tst1);
+         }
+         d[l] = d[l] + f;
+         e[l] = 0.0;
+      }
+     
+      // Sort eigenvalues and corresponding vectors.
+   
+      for (int i = 0; i < n-1; i++) {
+         int k = i;
+         double p = d[i];
+         for (int j = i+1; j < n; j++) {
+            if (d[j] < p) {
+               k = j;
+               p = d[j];
+            }
+         }
+         if (k != i) {
+            d[k] = d[i];
+            d[i] = p;
+            for (int j = 0; j < n; j++) {
+               p = V[j][i];
+               V[j][i] = V[j][k];
+               V[j][k] = p;
+            }
+         }
+      }
+   }
+
+   // Nonsymmetric reduction to Hessenberg form.
+
+   private void orthes () {
+   
+      //  This is derived from the Algol procedures orthes and ortran,
+      //  by Martin and Wilkinson, Handbook for Auto. Comp.,
+      //  Vol.ii-Linear Algebra, and the corresponding
+      //  Fortran subroutines in EISPACK.
+   
+      int low = 0;
+      int high = n-1;
+   
+      for (int m = low+1; m <= high-1; m++) {
+   
+         // Scale column.
+   
+         double scale = 0.0;
+         for (int i = m; i <= high; i++) {
+            scale = scale + Math.abs(H[i][m-1]);
+         }
+         if (scale != 0.0) {
+   
+            // Compute Householder transformation.
+   
+            double h = 0.0;
+            for (int i = high; i >= m; i--) {
+               ort[i] = H[i][m-1]/scale;
+               h += ort[i] * ort[i];
+            }
+            double g = Math.sqrt(h);
+            if (ort[m] > 0) {
+               g = -g;
+            }
+            h = h - ort[m] * g;
+            ort[m] = ort[m] - g;
+   
+            // Apply Householder similarity transformation
+            // H = (I-u*u'/h)*H*(I-u*u')/h)
+   
+            for (int j = m; j < n; j++) {
+               double f = 0.0;
+               for (int i = high; i >= m; i--) {
+                  f += ort[i]*H[i][j];
+               }
+               f = f/h;
+               for (int i = m; i <= high; i++) {
+                  H[i][j] -= f*ort[i];
+               }
+           }
+   
+           for (int i = 0; i <= high; i++) {
+               double f = 0.0;
+               for (int j = high; j >= m; j--) {
+                  f += ort[j]*H[i][j];
+               }
+               f = f/h;
+               for (int j = m; j <= high; j++) {
+                  H[i][j] -= f*ort[j];
+               }
+            }
+            ort[m] = scale*ort[m];
+            H[m][m-1] = scale*g;
+         }
+      }
+   
+      // Accumulate transformations (Algol's ortran).
+
+      for (int i = 0; i < n; i++) {
+         for (int j = 0; j < n; j++) {
+            V[i][j] = (i == j ? 1.0 : 0.0);
+         }
+      }
+
+      for (int m = high-1; m >= low+1; m--) {
+         if (H[m][m-1] != 0.0) {
+            for (int i = m+1; i <= high; i++) {
+               ort[i] = H[i][m-1];
+            }
+            for (int j = m; j <= high; j++) {
+               double g = 0.0;
+               for (int i = m; i <= high; i++) {
+                  g += ort[i] * V[i][j];
+               }
+               // Double division avoids possible underflow
+               g = (g / ort[m]) / H[m][m-1];
+               for (int i = m; i <= high; i++) {
+                  V[i][j] += g * ort[i];
+               }
+            }
+         }
+      }
+   }
+
+
+   // Complex scalar division.
+
+   private transient double cdivr, cdivi;
+   private void cdiv(double xr, double xi, double yr, double yi) {
+      double r,d;
+      if (Math.abs(yr) > Math.abs(yi)) {
+         r = yi/yr;
+         d = yr + r*yi;
+         cdivr = (xr + r*xi)/d;
+         cdivi = (xi - r*xr)/d;
+      } else {
+         r = yr/yi;
+         d = yi + r*yr;
+         cdivr = (r*xr + xi)/d;
+         cdivi = (r*xi - xr)/d;
+      }
+   }
+
+
+   // Nonsymmetric reduction from Hessenberg to real Schur form.
+
+   private void hqr2 () {
+   
+      //  This is derived from the Algol procedure hqr2,
+      //  by Martin and Wilkinson, Handbook for Auto. Comp.,
+      //  Vol.ii-Linear Algebra, and the corresponding
+      //  Fortran subroutine in EISPACK.
+   
+      // Initialize
+   
+      int nn = this.n;
+      int n = nn-1;
+      int low = 0;
+      int high = nn-1;
+      double eps = Math.pow(2.0,-52.0);
+      double exshift = 0.0;
+      double p=0,q=0,r=0,s=0,z=0,t,w,x,y;
+   
+      // Store roots isolated by balanc and compute matrix norm
+   
+      double norm = 0.0;
+      for (int i = 0; i < nn; i++) {
+         if (i < low | i > high) {
+            d[i] = H[i][i];
+            e[i] = 0.0;
+         }
+         for (int j = Math.max(i-1,0); j < nn; j++) {
+            norm = norm + Math.abs(H[i][j]);
+         }
+      }
+   
+      // Outer loop over eigenvalue index
+   
+      int iter = 0;
+      while (n >= low) {
+   
+         // Look for single small sub-diagonal element
+   
+         int l = n;
+         while (l > low) {
+            s = Math.abs(H[l-1][l-1]) + Math.abs(H[l][l]);
+            if (s == 0.0) {
+               s = norm;
+            }
+            if (Math.abs(H[l][l-1]) < eps * s) {
+               break;
+            }
+            l--;
+         }
+       
+         // Check for convergence
+         // One root found
+   
+         if (l == n) {
+            H[n][n] = H[n][n] + exshift;
+            d[n] = H[n][n];
+            e[n] = 0.0;
+            n--;
+            iter = 0;
+   
+         // Two roots found
+   
+         } else if (l == n-1) {
+            w = H[n][n-1] * H[n-1][n];
+            p = (H[n-1][n-1] - H[n][n]) / 2.0;
+            q = p * p + w;
+            z = Math.sqrt(Math.abs(q));
+            H[n][n] = H[n][n] + exshift;
+            H[n-1][n-1] = H[n-1][n-1] + exshift;
+            x = H[n][n];
+   
+            // Real pair
+   
+            if (q >= 0) {
+               if (p >= 0) {
+                  z = p + z;
+               } else {
+                  z = p - z;
+               }
+               d[n-1] = x + z;
+               d[n] = d[n-1];
+               if (z != 0.0) {
+                  d[n] = x - w / z;
+               }
+               e[n-1] = 0.0;
+               e[n] = 0.0;
+               x = H[n][n-1];
+               s = Math.abs(x) + Math.abs(z);
+               p = x / s;
+               q = z / s;
+               r = Math.sqrt(p * p+q * q);
+               p = p / r;
+               q = q / r;
+   
+               // Row modification
+   
+               for (int j = n-1; j < nn; j++) {
+                  z = H[n-1][j];
+                  H[n-1][j] = q * z + p * H[n][j];
+                  H[n][j] = q * H[n][j] - p * z;
+               }
+   
+               // Column modification
+   
+               for (int i = 0; i <= n; i++) {
+                  z = H[i][n-1];
+                  H[i][n-1] = q * z + p * H[i][n];
+                  H[i][n] = q * H[i][n] - p * z;
+               }
+   
+               // Accumulate transformations
+   
+               for (int i = low; i <= high; i++) {
+                  z = V[i][n-1];
+                  V[i][n-1] = q * z + p * V[i][n];
+                  V[i][n] = q * V[i][n] - p * z;
+               }
+   
+            // Complex pair
+   
+            } else {
+               d[n-1] = x + p;
+               d[n] = x + p;
+               e[n-1] = z;
+               e[n] = -z;
+            }
+            n = n - 2;
+            iter = 0;
+   
+         // No convergence yet
+   
+         } else {
+   
+            // Form shift
+   
+            x = H[n][n];
+            y = 0.0;
+            w = 0.0;
+            if (l < n) {
+               y = H[n-1][n-1];
+               w = H[n][n-1] * H[n-1][n];
+            }
+   
+            // Wilkinson's original ad hoc shift
+   
+            if (iter == 10) {
+               exshift += x;
+               for (int i = low; i <= n; i++) {
+                  H[i][i] -= x;
+               }
+               s = Math.abs(H[n][n-1]) + Math.abs(H[n-1][n-2]);
+               x = y = 0.75 * s;
+               w = -0.4375 * s * s;
+            }
+
+            // MATLAB's new ad hoc shift
+
+            if (iter == 30) {
+                s = (y - x) / 2.0;
+                s = s * s + w;
+                if (s > 0) {
+                    s = Math.sqrt(s);
+                    if (y < x) {
+                       s = -s;
+                    }
+                    s = x - w / ((y - x) / 2.0 + s);
+                    for (int i = low; i <= n; i++) {
+                       H[i][i] -= s;
+                    }
+                    exshift += s;
+                    x = y = w = 0.964;
+                }
+            }
+   
+            iter = iter + 1;   // (Could check iteration count here.)
+   
+            // Look for two consecutive small sub-diagonal elements
+   
+            int m = n-2;
+            while (m >= l) {
+               z = H[m][m];
+               r = x - z;
+               s = y - z;
+               p = (r * s - w) / H[m+1][m] + H[m][m+1];
+               q = H[m+1][m+1] - z - r - s;
+               r = H[m+2][m+1];
+               s = Math.abs(p) + Math.abs(q) + Math.abs(r);
+               p = p / s;
+               q = q / s;
+               r = r / s;
+               if (m == l) {
+                  break;
+               }
+               if (Math.abs(H[m][m-1]) * (Math.abs(q) + Math.abs(r)) <
+                  eps * (Math.abs(p) * (Math.abs(H[m-1][m-1]) + Math.abs(z) +
+                  Math.abs(H[m+1][m+1])))) {
+                     break;
+               }
+               m--;
+            }
+   
+            for (int i = m+2; i <= n; i++) {
+               H[i][i-2] = 0.0;
+               if (i > m+2) {
+                  H[i][i-3] = 0.0;
+               }
+            }
+   
+            // Double QR step involving rows l:n and columns m:n
+   
+            for (int k = m; k <= n-1; k++) {
+               boolean notlast = (k != n-1);
+               if (k != m) {
+                  p = H[k][k-1];
+                  q = H[k+1][k-1];
+                  r = (notlast ? H[k+2][k-1] : 0.0);
+                  x = Math.abs(p) + Math.abs(q) + Math.abs(r);
+                  if (x != 0.0) {
+                     p = p / x;
+                     q = q / x;
+                     r = r / x;
+                  }
+               }
+               if (x == 0.0) {
+                  break;
+               }
+               s = Math.sqrt(p * p + q * q + r * r);
+               if (p < 0) {
+                  s = -s;
+               }
+               if (s != 0) {
+                  if (k != m) {
+                     H[k][k-1] = -s * x;
+                  } else if (l != m) {
+                     H[k][k-1] = -H[k][k-1];
+                  }
+                  p = p + s;
+                  x = p / s;
+                  y = q / s;
+                  z = r / s;
+                  q = q / p;
+                  r = r / p;
+   
+                  // Row modification
+   
+                  for (int j = k; j < nn; j++) {
+                     p = H[k][j] + q * H[k+1][j];
+                     if (notlast) {
+                        p = p + r * H[k+2][j];
+                        H[k+2][j] = H[k+2][j] - p * z;
+                     }
+                     H[k][j] = H[k][j] - p * x;
+                     H[k+1][j] = H[k+1][j] - p * y;
+                  }
+   
+                  // Column modification
+   
+                  for (int i = 0; i <= Math.min(n,k+3); i++) {
+                     p = x * H[i][k] + y * H[i][k+1];
+                     if (notlast) {
+                        p = p + z * H[i][k+2];
+                        H[i][k+2] = H[i][k+2] - p * r;
+                     }
+                     H[i][k] = H[i][k] - p;
+                     H[i][k+1] = H[i][k+1] - p * q;
+                  }
+   
+                  // Accumulate transformations
+   
+                  for (int i = low; i <= high; i++) {
+                     p = x * V[i][k] + y * V[i][k+1];
+                     if (notlast) {
+                        p = p + z * V[i][k+2];
+                        V[i][k+2] = V[i][k+2] - p * r;
+                     }
+                     V[i][k] = V[i][k] - p;
+                     V[i][k+1] = V[i][k+1] - p * q;
+                  }
+               }  // (s != 0)
+            }  // k loop
+         }  // check convergence
+      }  // while (n >= low)
+      
+      // Backsubstitute to find vectors of upper triangular form
+
+      if (norm == 0.0) {
+         return;
+      }
+   
+      for (n = nn-1; n >= 0; n--) {
+         p = d[n];
+         q = e[n];
+   
+         // Real vector
+   
+         if (q == 0) {
+            int l = n;
+            H[n][n] = 1.0;
+            for (int i = n-1; i >= 0; i--) {
+               w = H[i][i] - p;
+               r = 0.0;
+               for (int j = l; j <= n; j++) {
+                  r = r + H[i][j] * H[j][n];
+               }
+               if (e[i] < 0.0) {
+                  z = w;
+                  s = r;
+               } else {
+                  l = i;
+                  if (e[i] == 0.0) {
+                     if (w != 0.0) {
+                        H[i][n] = -r / w;
+                     } else {
+                        H[i][n] = -r / (eps * norm);
+                     }
+   
+                  // Solve real equations
+   
+                  } else {
+                     x = H[i][i+1];
+                     y = H[i+1][i];
+                     q = (d[i] - p) * (d[i] - p) + e[i] * e[i];
+                     t = (x * s - z * r) / q;
+                     H[i][n] = t;
+                     if (Math.abs(x) > Math.abs(z)) {
+                        H[i+1][n] = (-r - w * t) / x;
+                     } else {
+                        H[i+1][n] = (-s - y * t) / z;
+                     }
+                  }
+   
+                  // Overflow control
+   
+                  t = Math.abs(H[i][n]);
+                  if ((eps * t) * t > 1) {
+                     for (int j = i; j <= n; j++) {
+                        H[j][n] = H[j][n] / t;
+                     }
+                  }
+               }
+            }
+   
+         // Complex vector
+   
+         } else if (q < 0) {
+            int l = n-1;
+
+            // Last vector component imaginary so matrix is triangular
+   
+            if (Math.abs(H[n][n-1]) > Math.abs(H[n-1][n])) {
+               H[n-1][n-1] = q / H[n][n-1];
+               H[n-1][n] = -(H[n][n] - p) / H[n][n-1];
+            } else {
+               cdiv(0.0,-H[n-1][n],H[n-1][n-1]-p,q);
+               H[n-1][n-1] = cdivr;
+               H[n-1][n] = cdivi;
+            }
+            H[n][n-1] = 0.0;
+            H[n][n] = 1.0;
+            for (int i = n-2; i >= 0; i--) {
+               double ra,sa,vr,vi;
+               ra = 0.0;
+               sa = 0.0;
+               for (int j = l; j <= n; j++) {
+                  ra = ra + H[i][j] * H[j][n-1];
+                  sa = sa + H[i][j] * H[j][n];
+               }
+               w = H[i][i] - p;
+   
+               if (e[i] < 0.0) {
+                  z = w;
+                  r = ra;
+                  s = sa;
+               } else {
+                  l = i;
+                  if (e[i] == 0) {
+                     cdiv(-ra,-sa,w,q);
+                     H[i][n-1] = cdivr;
+                     H[i][n] = cdivi;
+                  } else {
+   
+                     // Solve complex equations
+   
+                     x = H[i][i+1];
+                     y = H[i+1][i];
+                     vr = (d[i] - p) * (d[i] - p) + e[i] * e[i] - q * q;
+                     vi = (d[i] - p) * 2.0 * q;
+                     if (vr == 0.0 & vi == 0.0) {
+                        vr = eps * norm * (Math.abs(w) + Math.abs(q) +
+                        Math.abs(x) + Math.abs(y) + Math.abs(z));
+                     }
+                     cdiv(x*r-z*ra+q*sa,x*s-z*sa-q*ra,vr,vi);
+                     H[i][n-1] = cdivr;
+                     H[i][n] = cdivi;
+                     if (Math.abs(x) > (Math.abs(z) + Math.abs(q))) {
+                        H[i+1][n-1] = (-ra - w * H[i][n-1] + q * H[i][n]) / x;
+                        H[i+1][n] = (-sa - w * H[i][n] - q * H[i][n-1]) / x;
+                     } else {
+                        cdiv(-r-y*H[i][n-1],-s-y*H[i][n],z,q);
+                        H[i+1][n-1] = cdivr;
+                        H[i+1][n] = cdivi;
+                     }
+                  }
+   
+                  // Overflow control
+
+                  t = Math.max(Math.abs(H[i][n-1]),Math.abs(H[i][n]));
+                  if ((eps * t) * t > 1) {
+                     for (int j = i; j <= n; j++) {
+                        H[j][n-1] = H[j][n-1] / t;
+                        H[j][n] = H[j][n] / t;
+                     }
+                  }
+               }
+            }
+         }
+      }
+   
+      // Vectors of isolated roots
+   
+      for (int i = 0; i < nn; i++) {
+         if (i < low | i > high) {
+            for (int j = i; j < nn; j++) {
+               V[i][j] = H[i][j];
+            }
+         }
+      }
+   
+      // Back transformation to get eigenvectors of original matrix
+   
+      for (int j = nn-1; j >= low; j--) {
+         for (int i = low; i <= high; i++) {
+            z = 0.0;
+            for (int k = low; k <= Math.min(j,high); k++) {
+               z = z + V[i][k] * H[k][j];
+            }
+            V[i][j] = z;
+         }
+      }
+   }
+
+
+/* ------------------------
+   Constructor
+ * ------------------------ */
+
+   /** Check for symmetry, then construct the eigenvalue decomposition
+   @param Arg    Square matrix
+   */
+
+   public EigenvalueDecomposition (Matrix Arg) {
+      double[][] A = Arg.getArray();
+      n = Arg.getColumnDimension();
+      V = new double[n][n];
+      d = new double[n];
+      e = new double[n];
+
+      issymmetric = true;
+      for (int j = 0; (j < n) & issymmetric; j++) {
+         for (int i = 0; (i < n) & issymmetric; i++) {
+            issymmetric = (A[i][j] == A[j][i]);
+         }
+      }
+
+      if (issymmetric) {
+         for (int i = 0; i < n; i++) {
+            for (int j = 0; j < n; j++) {
+               V[i][j] = A[i][j];
+            }
+         }
+   
+         // Tridiagonalize.
+         tred2();
+   
+         // Diagonalize.
+         tql2();
+
+      } else {
+         H = new double[n][n];
+         ort = new double[n];
+         
+         for (int j = 0; j < n; j++) {
+            for (int i = 0; i < n; i++) {
+               H[i][j] = A[i][j];
+            }
+         }
+   
+         // Reduce to Hessenberg form.
+         orthes();
+   
+         // Reduce Hessenberg to real Schur form.
+         hqr2();
+      }
+   }
+
+/* ------------------------
+   Public Methods
+ * ------------------------ */
+
+   /** Return the eigenvector matrix
+   @return     V
+   */
+
+   public Matrix getV () {
+      return new Matrix(V,n,n);
+   }
+   
+   public Matrix getEigenVectors()
+   {
+       return getV();
+   }
+
+   /** Return the real parts of the eigenvalues
+   @return     real(diag(D))
+   */
+
+   public double[] getRealEigenvalues () {
+      return d;
+   }
+
+   /** Return the imaginary parts of the eigenvalues
+   @return     imag(diag(D))
+   */
+
+   public double[] getImagEigenvalues () {
+      return e;
+   }
+
+   /** Return the block diagonal eigenvalue matrix
+   @return     D
+   */
+
+   public Matrix getD () {
+      Matrix X = new Matrix(n,n);
+      double[][] D = X.getArray();
+      for (int i = 0; i < n; i++) {
+         for (int j = 0; j < n; j++) {
+            D[i][j] = 0.0;
+         }
+         D[i][i] = d[i];
+         if (e[i] > 0) {
+            D[i][i+1] = e[i];
+         } else if (e[i] < 0) {
+            D[i][i-1] = e[i];
+         }
+      }
+      return X;
+   }
+}

java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix
LUDecomposition.java added at 919
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/LUDecomposition.java	                        (rev 0)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/LUDecomposition.java	2014-08-28 15:31:06 UTC (rev 919)
@@ -0,0 +1,310 @@
+package org.hps.recon.tracking.gbl.matrix;
+  /** LU Decomposition.
+   <P>
+   For an m-by-n matrix A with m >= n, the LU decomposition is an m-by-n
+   unit lower triangular matrix L, an n-by-n upper triangular matrix U,
+   and a permutation vector piv of length m so that A(piv,:) = L*U.
+   If m < n, then L is m-by-m and U is m-by-n.
+   <P>
+   The LU decompostion with pivoting always exists, even if the matrix is
+   singular, so the constructor will never fail.  The primary use of the
+   LU decomposition is in the solution of square systems of simultaneous
+   linear equations.  This will fail if isNonsingular() returns false.
+   @version $Id: LUDecomposition.java,v 1.1.1.1 2010/11/30 21:31:59 jeremy Exp $
+   */
+
+public class LUDecomposition implements java.io.Serializable {
+
+/* ------------------------
+   Class variables
+ * ------------------------ */
+
+   /** Array for internal storage of decomposition.
+   @serial internal array storage.
+   */
+   private double[][] LU;
+
+   /** Row and column dimensions, and pivot sign.
+   @serial column dimension.
+   @serial row dimension.
+   @serial pivot sign.
+   */
+   private int m, n, pivsign; 
+
+   /** Internal storage of pivot vector.
+   @serial pivot vector.
+   */
+   private int[] piv;
+
+/* ------------------------
+   Constructor
+ * ------------------------ */
+
+   /** LU Decomposition
+   @param  A   Rectangular matrix
+   */
+
+   public LUDecomposition (Matrix A) {
+
+   // Use a "left-looking", dot-product, Crout/Doolittle algorithm.
+
+      LU = A.getArrayCopy();
+      m = A.getRowDimension();
+      n = A.getColumnDimension();
+      piv = new int[m];
+      for (int i = 0; i < m; i++) {
+         piv[i] = i;
+      }
+      pivsign = 1;
+      double[] LUrowi;
+      double[] LUcolj = new double[m];
+
+      // Outer loop.
+
+      for (int j = 0; j < n; j++) {
+
+         // Make a copy of the j-th column to localize references.
+
+         for (int i = 0; i < m; i++) {
+            LUcolj[i] = LU[i][j];
+         }
+
+         // Apply previous transformations.
+
+         for (int i = 0; i < m; i++) {
+            LUrowi = LU[i];
+
+            // Most of the time is spent in the following dot product.
+
+            int kmax = Math.min(i,j);
+            double s = 0.0;
+            for (int k = 0; k < kmax; k++) {
+               s += LUrowi[k]*LUcolj[k];
+            }
+
+            LUrowi[j] = LUcolj[i] -= s;
+         }
+   
+         // Find pivot and exchange if necessary.
+
+         int p = j;
+         for (int i = j+1; i < m; i++) {
+            if (Math.abs(LUcolj[i]) > Math.abs(LUcolj[p])) {
+               p = i;
+            }
+         }
+         if (p != j) {
+            for (int k = 0; k < n; k++) {
+               double t = LU[p][k]; LU[p][k] = LU[j][k]; LU[j][k] = t;
+            }
+            int k = piv[p]; piv[p] = piv[j]; piv[j] = k;
+            pivsign = -pivsign;
+         }
+
+         // Compute multipliers.
+         
+         if (j < m & LU[j][j] != 0.0) {
+            for (int i = j+1; i < m; i++) {
+               LU[i][j] /= LU[j][j];
+            }
+         }
+      }
+   }
+
+/* ------------------------
+   Temporary, experimental code.
+   ------------------------ *\
+
+   \** LU Decomposition, computed by Gaussian elimination.
+   <P>
+   This constructor computes L and U with the "daxpy"-based elimination
+   algorithm used in LINPACK and MATLAB.  In Java, we suspect the dot-product,
+   Crout algorithm will be faster.  We have temporarily included this
+   constructor until timing experiments confirm this suspicion.
+   <P>
+   @param  A             Rectangular matrix
+   @param  linpackflag   Use Gaussian elimination.  Actual value ignored.
+   @return               Structure to access L, U and piv.
+   *\
+
+   public LUDecomposition (Matrix A, int linpackflag) {
+      // Initialize.
+      LU = A.getArrayCopy();
+      m = A.getRowDimension();
+      n = A.getColumnDimension();
+      piv = new int[m];
+      for (int i = 0; i < m; i++) {
+         piv[i] = i;
+      }
+      pivsign = 1;
+      // Main loop.
+      for (int k = 0; k < n; k++) {
+         // Find pivot.
+         int p = k;
+         for (int i = k+1; i < m; i++) {
+            if (Math.abs(LU[i][k]) > Math.abs(LU[p][k])) {
+               p = i;
+            }
+         }
+         // Exchange if necessary.
+         if (p != k) {
+            for (int j = 0; j < n; j++) {
+               double t = LU[p][j]; LU[p][j] = LU[k][j]; LU[k][j] = t;
+            }
+            int t = piv[p]; piv[p] = piv[k]; piv[k] = t;
+            pivsign = -pivsign;
+         }
+         // Compute multipliers and eliminate k-th column.
+         if (LU[k][k] != 0.0) {
+            for (int i = k+1; i < m; i++) {
+               LU[i][k] /= LU[k][k];
+               for (int j = k+1; j < n; j++) {
+                  LU[i][j] -= LU[i][k]*LU[k][j];
+               }
+            }
+         }
+      }
+   }
+
+\* ------------------------
+   End of temporary code.
+ * ------------------------ */
+
+/* ------------------------
+   Public Methods
+ * ------------------------ */
+
+   /** Is the matrix nonsingular?
+   @return     true if U, and hence A, is nonsingular.
+   */
+
+   public boolean isNonsingular () {
+      for (int j = 0; j < n; j++) {
+         if (LU[j][j] == 0)
+            return false;
+      }
+      return true;
+   }
+
+   /** Return lower triangular factor
+   @return     L
+   */
+
+   public Matrix getL () {
+      Matrix X = new Matrix(m,n);
+      double[][] L = X.getArray();
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            if (i > j) {
+               L[i][j] = LU[i][j];
+            } else if (i == j) {
+               L[i][j] = 1.0;
+            } else {
+               L[i][j] = 0.0;
+            }
+         }
+      }
+      return X;
+   }
+
+   /** Return upper triangular factor
+   @return     U
+   */
+
+   public Matrix getU () {
+      Matrix X = new Matrix(n,n);
+      double[][] U = X.getArray();
+      for (int i = 0; i < n; i++) {
+         for (int j = 0; j < n; j++) {
+            if (i <= j) {
+               U[i][j] = LU[i][j];
+            } else {
+               U[i][j] = 0.0;
+            }
+         }
+      }
+      return X;
+   }
+
+   /** Return pivot permutation vector
+   @return     piv
+   */
+
+   public int[] getPivot () {
+      int[] p = new int[m];
+      for (int i = 0; i < m; i++) {
+         p[i] = piv[i];
+      }
+      return p;
+   }
+
+   /** Return pivot permutation vector as a one-dimensional double array
+   @return     (double) piv
+   */
+
+   public double[] getDoublePivot () {
+      double[] vals = new double[m];
+      for (int i = 0; i < m; i++) {
+         vals[i] = (double) piv[i];
+      }
+      return vals;
+   }
+
+   /** Determinant
+   @return     det(A)
+   @exception  IllegalArgumentException  Matrix must be square
+   */
+
+   public double det () {
+      if (m != n) {
+         throw new IllegalArgumentException("Matrix must be square.");
+      }
+      double d = (double) pivsign;
+      for (int j = 0; j < n; j++) {
+         d *= LU[j][j];
+      }
+      return d;
+   }
+
+   /** Solve A*X = B
+   @param  B   A Matrix with as many rows as A and any number of columns.
+   @return     X so that L*U*X = B(piv,:)
+   @exception  IllegalArgumentException Matrix row dimensions must agree.
+   @exception  RuntimeException  Matrix is singular.
+   */
+
+   public Matrix solve (Matrix B) {
+      if (B.getRowDimension() != m) {
+         throw new IllegalArgumentException("Matrix row dimensions must agree.");
+      }
+      if (!this.isNonsingular()) {
+         throw new RuntimeException("Matrix is singular.");
+      }
+
+      // Copy right hand side with pivoting
+      int nx = B.getColumnDimension();
+      Matrix Xmat = B.getMatrix(piv,0,nx-1);
+      double[][] X = Xmat.getArray();
+
+      // Solve L*Y = B(piv,:)
+      for (int k = 0; k < n; k++) {
+         for (int i = k+1; i < n; i++) {
+            for (int j = 0; j < nx; j++) {
+               X[i][j] -= X[k][j]*LU[i][k];
+            }
+         }
+      }
+      // Solve U*X = Y;
+      for (int k = n-1; k >= 0; k--) {
+         for (int j = 0; j < nx; j++) {
+            X[k][j] /= LU[k][k];
+         }
+         for (int i = 0; i < k; i++) {
+            for (int j = 0; j < nx; j++) {
+               X[i][j] -= X[k][j]*LU[i][k];
+            }
+         }
+      }
+      return Xmat;
+   }
+}
\ No newline at end of file

java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix
Matrix.java added at 919
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/Matrix.java	                        (rev 0)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/Matrix.java	2014-08-28 15:31:06 UTC (rev 919)
@@ -0,0 +1,1553 @@
+package org.hps.recon.tracking.gbl.matrix;
+
+import java.io.BufferedReader;
+import java.io.PrintWriter;
+import java.io.StreamTokenizer;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.NumberFormat;
+import java.util.Locale;
+
+///**
+// * Jama = Java Matrix class.
+// * <P>
+// * The Java Matrix Class provides the fundamental operations of numerical linear
+// * algebra. Various constructors create Matrices from two dimensional arrays of
+// * double precision floating point numbers. Various "gets" and "sets" provide
+// * access to submatrices and matrix elements. Several methods implement basic
+// * matrix arithmetic, including matrix addition and multiplication, matrix
+// * norms, and element-by-element array operations. Methods for reading and
+// * printing matrices are also included. All the operations in this version of
+// * the Matrix Class involve real matrices. Complex matrices may be handled in a
+// * future version.
+// * <P>
+// * Five fundamental matrix decompositions, which consist of pairs or triples of
+// * matrices, permutation vectors, and the like, produce results in five
+// * decomposition classes. These decompositions are accessed by the Matrix class
+// * to compute solutions of simultaneous linear equations, determinants, inverses
+// * and other matrix functions. The five decompositions are:
+// * <P>
+// * <UL>
+// * <LI>Cholesky Decomposition of symmetric, positive definite matrices.
+// * <LI>LU Decomposition of rectangular matrices.
+// * <LI>QR Decomposition of rectangular matrices.
+// * <LI>Singular Value Decomposition of rectangular matrices.
+// * <LI>Eigenvalue Decomposition of both symmetric and nonsymmetric square
+// * matrices.
+// * </UL>
+// * <DL>
+// * <DT><B>Example of use:</B></DT>
+// * <P>
+// * <DD>Solve a linear system A x = b and compute the residual norm, ||b - A x||.
+// * <P>
+// * <
+// * PRE>
+// * double[][] vals = {{1.,2.,3},{4.,5.,6.},{7.,8.,10.}};
+// * Matrix A = new Matrix(vals);
+// * Matrix b = Matrix.random(3,1);
+// * Matrix x = A.solve(b);
+// * Matrix r = A.times(x).minus(b);
+// * double rnorm = r.normInf();
+// * </PRE></DD>
+// * </DL>
+// *
+// * @author The MathWorks, Inc. and the National Institute of Standards and
+// * Technology.
+// * @author Norman A. Graf (modifications for the gbl package)
+// * @version 5 August 1998 $Id: Matrix.java,v 1.1.1.1 2010/11/30 21:31:59 jeremy
+// * Exp $
+// */
+public class Matrix implements Cloneable, java.io.Serializable
+{
+
+    /* ------------------------
+     Class variables
+     * ------------------------ */
+    /**
+     * Array for internal storage of elements.
+     *
+     * @serial internal array storage.
+     */
+    protected double[][] A;
+
+    /**
+     * Row and column dimensions.
+     *
+     * @serial row dimension.
+     * @serial column dimension.
+     */
+    protected int m, n;
+
+    /* ------------------------
+     Constructors
+     * ------------------------ */
+    /**
+     * Construct an m-by-n matrix of zeros.
+     *
+     * @param m Number of rows.
+     * @param n Number of columns.
+     */
+    public Matrix(int m, int n)
+    {
+        this.m = m;
+        this.n = n;
+        A = new double[m][n];
+    }
+//
+//    /**
+//     * Construct an m-by-n constant matrix.
+//     *
+//     * @param m Number of rows.
+//     * @param n Number of colums.
+//     * @param s Fill the matrix with this scalar value.
+//     */
+//    public Matrix(int m, int n, double s)
+//    {
+//        this.m = m;
+//        this.n = n;
+//        A = new double[m][n];
+//        for (int i = 0; i < m; i++)
+//        {
+//            for (int j = 0; j < n; j++)
+//            {
+//                A[i][j] = s;
+//            }
+//        }
+//    }
+//
+//    /**
+//     * Construct a matrix from a 2-D array.
+//     *
+//     * @param A Two-dimensional array of doubles.
+//     * @exception IllegalArgumentException All rows must have the same length
+//     * @see #constructWithCopy
+//     */
+//    public Matrix(double[][] A)
+//    {
+//        m = A.length;
+//        n = A[0].length;
+//        for (int i = 0; i < m; i++)
+//        {
+//            if (A[i].length != n)
+//            {
+//                throw new IllegalArgumentException("All rows must have the same length.");
+//            }
+//        }
+//        this.A = A;
+//    }
+//
+    /**
+     * Construct a matrix quickly without checking arguments.
+     *
+     * @param A Two-dimensional array of doubles.
+     * @param m Number of rows.
+     * @param n Number of colums.
+     */
+    public Matrix(double[][] A, int m, int n)
+    {
+        this.A = A;
+        this.m = m;
+        this.n = n;
+    }
+
+//    /**
+//     * Construct a matrix from a one-dimensional packed array
+//     *
+//     * @param vals One-dimensional array of doubles, packed by columns (ala
+//     * Fortran).
+//     * @param m Number of rows.
+//     * @exception IllegalArgumentException Array length must be a multiple of m.
+//     */
+//    public Matrix(double vals[], int m)
+//    {
+//        this.m = m;
+//        n = (m != 0 ? vals.length / m : 0);
+//        if (m * n != vals.length)
+//        {
+//            throw new IllegalArgumentException("Array length must be a multiple of m.");
+//        }
+//        A = new double[m][n];
+//        for (int i = 0; i < m; i++)
+//        {
+//            for (int j = 0; j < n; j++)
+//            {
+//                A[i][j] = vals[i + j * m];
+//            }
+//        }
+//    }
+//
+//    /* ------------------------
+//     Public Methods
+//     * ------------------------ */
+//    /**
+//     * Construct a matrix from a copy of a 2-D array.
+//     *
+//     * @param A Two-dimensional array of doubles.
+//     * @exception IllegalArgumentException All rows must have the same length
+//     */
+//    public static Matrix constructWithCopy(double[][] A)
+//    {
+//        int m = A.length;
+//        int n = A[0].length;
+//        Matrix X = new Matrix(m, n);
+//        double[][] C = X.getArray();
+//        for (int i = 0; i < m; i++)
+//        {
+//            if (A[i].length != n)
+//            {
+//                throw new IllegalArgumentException("All rows must have the same length.");
+//            }
+//            for (int j = 0; j < n; j++)
+//            {
+//                C[i][j] = A[i][j];
+//            }
+//        }
+//        return X;
+//    }
+//
+//    /**
+//     * Make a deep copy of a matrix
+//     */
+//    public Matrix copy()
+//    {
+//        Matrix X = new Matrix(m, n);
+//        double[][] C = X.getArray();
+//        for (int i = 0; i < m; i++)
+//        {
+//            for (int j = 0; j < n; j++)
+//            {
+//                C[i][j] = A[i][j];
+//            }
+//        }
+//        return X;
+//    }
+//
+//    /**
+//     * Clone the Matrix object.
+//     */
+//    public Object clone()
+//    {
+//        return this.copy();
+//    }
+//
+    /**
+     * Access the internal two-dimensional array.
+     *
+     * @return Pointer to the two-dimensional array of matrix elements.
+     * TODO should this return a copy?
+     */
+    public double[][] getArray()
+    {
+        return A;
+    }
+
+    /**
+     * Copy the internal two-dimensional array.
+     *
+     * @return Two-dimensional array copy of matrix elements.
+     */
+    public double[][] getArrayCopy()
+    {
+        double[][] C = new double[m][n];
+        for (int i = 0; i < m; i++)
+        {
+            for (int j = 0; j < n; j++)
+            {
+                C[i][j] = A[i][j];
+            }
+        }
+        return C;
+    }
+
+//    /**
+//     * Make a one-dimensional column packed copy of the internal array.
+//     *
+//     * @return Matrix elements packed in a one-dimensional array by columns.
+//     */
+//    public double[] getColumnPackedCopy()
+//    {
+//        double[] vals = new double[m * n];
+//        for (int i = 0; i < m; i++)
+//        {
+//            for (int j = 0; j < n; j++)
+//            {
+//                vals[i + j * m] = A[i][j];
+//            }
+//        }
+//        return vals;
+//    }
+//
+//    /**
+//     * Make a one-dimensional row packed copy of the internal array.
+//     *
+//     * @return Matrix elements packed in a one-dimensional array by rows.
+//     */
+//    public double[] getRowPackedCopy()
+//    {
+//        double[] vals = new double[m * n];
+//        for (int i = 0; i < m; i++)
+//        {
+//            for (int j = 0; j < n; j++)
+//            {
+//                vals[i * n + j] = A[i][j];
+//            }
+//        }
+//        return vals;
+//    }
+//
+    /**
+     * @return the number of rows.
+     */
+    public int getRowDimension()
+    {
+        return m;
+    }
+
+    /**
+     * @return the number of columns.
+     */
+    public int getColumnDimension()
+    {
+        return n;
+    }
+
+    /**
+     * @param i Row index.
+     * @param j Column index.
+     * @return A(i,j)
+     * @exception ArrayIndexOutOfBoundsException
+     */
+    public double get(int i, int j)
+    {
+        return A[i][j];
+    }
+
+    //for symmetric matrices
+public Matrix sub(int size, int rIndex, int cIndex)
+{
+    return getMatrix(rIndex, rIndex+size-1,cIndex, cIndex+size-1);
+}
+
+//non-symmetric Matrix
+public Matrix sub(int rSize, int cSize, int rIndex, int cIndex)
+{
+    return getMatrix(rIndex, rIndex+rSize-1,cIndex, cIndex+cSize-1);
+}
+
+public Vector subCol(int size, int colIndex, int rStart)
+{
+  return new Vector(getMatrix(rStart, rStart+size-1, colIndex, colIndex));  
+}
+
+public void placeAt(Matrix a, int rIndex, int cIndex)
+{
+    for(int i=0; i<a.getRowDimension(); ++i)
+    {
+        for(int j=0; j<a.getColumnDimension(); ++j)
+        {
+            A[rIndex+i][cIndex+j] = a.get(i,j);
+        }
+    }
+}
+
+public void placeInCol(Vector v, int rIndex, int cIndex)
+{
+    for(int i=0; i < v.size(); ++i)
+    {
+        A[rIndex+i][cIndex] = v.get(i);
+    }
+}
+    
+    
+    /**
+     * Returns a submatrix.
+     *
+     * @param i0 Initial row index
+     * @param i1 Final row index
+     * @param j0 Initial column index
+     * @param j1 Final column index
+     * @return A(i0:i1,j0:j1)
+     * @exception ArrayIndexOutOfBoundsException Submatrix indices
+     */
+    public Matrix getMatrix(int i0, int i1, int j0, int j1)
+    {
+        Matrix X = new Matrix(i1 - i0 + 1, j1 - j0 + 1);
+        double[][] B = X.getArray();
+        try
+        {
+            for (int i = i0; i <= i1; i++)
+            {
+                for (int j = j0; j <= j1; j++)
+                {
+                    B[i - i0][j - j0] = A[i][j];
+                }
+            }
+        } catch (ArrayIndexOutOfBoundsException e)
+        {
+            throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+        }
+        return X;
+    }
+
+//    /**
+//     * Returns a submatrix.
+//     *
+//     * @param r Array of row indices.
+//     * @param c Array of column indices.
+//     * @return A(r(:),c(:))
+//     * @exception ArrayIndexOutOfBoundsException Submatrix indices
+//     */
+//    public Matrix getMatrix(int[] r, int[] c)
+//    {
+//        Matrix X = new Matrix(r.length, c.length);
+//        double[][] B = X.getArray();
+//        try
+//        {
+//            for (int i = 0; i < r.length; i++)
+//            {
+//                for (int j = 0; j < c.length; j++)
+//                {
+//                    B[i][j] = A[r[i]][c[j]];
+//                }
+//            }
+//        } catch (ArrayIndexOutOfBoundsException e)
+//        {
+//            throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+//        }
+//        return X;
+//    }
+//
+//    /**
+//     * Returns a submatrix.
+//     *
+//     * @param i0 Initial row index
+//     * @param i1 Final row index
+//     * @param c Array of column indices.
+//     * @return A(i0:i1,c(:))
+//     * @exception ArrayIndexOutOfBoundsException Submatrix indices
+//     */
+//    public Matrix getMatrix(int i0, int i1, int[] c)
+//    {
+//        Matrix X = new Matrix(i1 - i0 + 1, c.length);
+//        double[][] B = X.getArray();
+//        try
+//        {
+//            for (int i = i0; i <= i1; i++)
+//            {
+//                for (int j = 0; j < c.length; j++)
+//                {
+//                    B[i - i0][j] = A[i][c[j]];
+//                }
+//            }
+//        } catch (ArrayIndexOutOfBoundsException e)
+//        {
+//            throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+//        }
+//        return X;
+//    }
+//
+    /**
+     * Returns a submatrix.
+     *
+     * @param r Array of row indices.
+     * @param j0 Initial column index
+     * @param j1 Final column index
+     * @return A(r(:),j0:j1)
+     * @exception ArrayIndexOutOfBoundsException Submatrix indices
+     */
+    public Matrix getMatrix(int[] r, int j0, int j1)
+    {
+        Matrix X = new Matrix(r.length, j1 - j0 + 1);
+        double[][] B = X.getArray();
+        try
+        {
+            for (int i = 0; i < r.length; i++)
+            {
+                for (int j = j0; j <= j1; j++)
+                {
+                    B[i][j - j0] = A[r[i]][j];
+                }
+            }
+        } catch (ArrayIndexOutOfBoundsException e)
+        {
+            throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+        }
+        return X;
+    }
+
+    /**
+     * Sets a single element.
+     *
+     * @param i Row index.
+     * @param j Column index.
+     * @param s A(i,j).
+     * @exception ArrayIndexOutOfBoundsException
+     */
+    public void set(int i, int j, double s)
+    {
+        A[i][j] = s;
+    }
+
+//    /**
+//     * Sets a submatrix.
+//     *
+//     * @param i0 Initial row index
+//     * @param i1 Final row index
+//     * @param j0 Initial column index
+//     * @param j1 Final column index
+//     * @param X A(i0:i1,j0:j1)
+//     * @exception ArrayIndexOutOfBoundsException Submatrix indices
+//     */
+//    public void setMatrix(int i0, int i1, int j0, int j1, Matrix X)
+//    {
+//        try
+//        {
+//            for (int i = i0; i <= i1; i++)
+//            {
+//                for (int j = j0; j <= j1; j++)
+//                {
+//                    A[i][j] = X.get(i - i0, j - j0);
+//                }
+//            }
+//        } catch (ArrayIndexOutOfBoundsException e)
+//        {
+//            throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+//        }
+//    }
+//
+//    /**
+//     * Sets a submatrix.
+//     *
+//     * @param r Array of row indices.
+//     * @param c Array of column indices.
+//     * @param X A(r(:),c(:))
+//     * @exception ArrayIndexOutOfBoundsException Submatrix indices
+//     */
+//    public void setMatrix(int[] r, int[] c, Matrix X)
+//    {
+//        try
+//        {
+//            for (int i = 0; i < r.length; i++)
+//            {
+//                for (int j = 0; j < c.length; j++)
+//                {
+//                    A[r[i]][c[j]] = X.get(i, j);
+//                }
+//            }
+//        } catch (ArrayIndexOutOfBoundsException e)
+//        {
+//            throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+//        }
+//    }
+//
+//    /**
+//     * Sets a submatrix.
+//     *
+//     * @param r Array of row indices.
+//     * @param j0 Initial column index
+//     * @param j1 Final column index
+//     * @param X A(r(:),j0:j1)
+//     * @exception ArrayIndexOutOfBoundsException Submatrix indices
+//     */
+//    public void setMatrix(int[] r, int j0, int j1, Matrix X)
+//    {
+//        try
+//        {
+//            for (int i = 0; i < r.length; i++)
+//            {
+//                for (int j = j0; j <= j1; j++)
+//                {
+//                    A[r[i]][j] = X.get(i, j - j0);
+//                }
+//            }
+//        } catch (ArrayIndexOutOfBoundsException e)
+//        {
+//            throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+//        }
+//    }
+//
+//    /**
+//     * Sets a submatrix.
+//     *
+//     * @param i0 Initial row index
+//     * @param i1 Final row index
+//     * @param c Array of column indices.
+//     * @param X A(i0:i1,c(:))
+//     * @exception ArrayIndexOutOfBoundsException Submatrix indices
+//     */
+//    public void setMatrix(int i0, int i1, int[] c, Matrix X)
+//    {
+//        try
+//        {
+//            for (int i = i0; i <= i1; i++)
+//            {
+//                for (int j = 0; j < c.length; j++)
+//                {
+//                    A[i][c[j]] = X.get(i - i0, j);
+//                }
+//            }
+//        } catch (ArrayIndexOutOfBoundsException e)
+//        {
+//            throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+//        }
+//    }
+//
+    /**
+     * Returns the transpose of the matrix. The elements of this matrix remain
+     * unchanged.
+     *
+     * @return a new matrix A<sup>T</sup>
+     */
+    public Matrix transpose()
+    {
+        Matrix X = new Matrix(n, m);
+        double[][] C = X.getArray();
+        for (int i = 0; i < m; i++)
+        {
+            for (int j = 0; j < n; j++)
+            {
+                C[j][i] = A[i][j];
+            }
+        }
+        return X;
+    }
+    
+    /**
+     * Transpose the matrix. The elements of this matrix 
+     * are changed in place.
+     *
+     */
+    public void transposeInPlace()
+    {
+        double[][] C = getArrayCopy();
+        for (int i = 0; i < m; i++)
+        {
+            for (int j = 0; j < n; j++)
+            {
+                A[j][i] = C[i][j];
+            }
+        }
+    }    
+
+//    /**
+//     * One norm
+//     *
+//     * @return maximum column sum.
+//     */
+//    public double norm1()
+//    {
+//        double f = 0;
+//        for (int j = 0; j < n; j++)
+//        {
+//            double s = 0;
+//            for (int i = 0; i < m; i++)
+//            {
+//                s += Math.abs(A[i][j]);
+//            }
+//            f = Math.max(f, s);
+//        }
+//        return f;
+//    }
+//
+//    /**
+//     * Two norm
+//     *
+//     * @return maximum singular value.
+//     */
+//    public double norm2()
+//    {
+//        return (new SingularValueDecomposition(this).norm2());
+//    }
+//
+//    /**
+//     * Infinity norm
+//     *
+//     * @return maximum row sum.
+//     */
+//    public double normInf()
+//    {
+//        double f = 0;
+//        for (int i = 0; i < m; i++)
+//        {
+//            double s = 0;
+//            for (int j = 0; j < n; j++)
+//            {
+//                s += Math.abs(A[i][j]);
+//            }
+//            f = Math.max(f, s);
+//        }
+//        return f;
+//    }
+//
+//    /**
+//     * Frobenius norm
+//     *
+//     * @return sqrt of sum of squares of all elements.
+//     */
+//    public double normF()
+//    {
+//        double f = 0;
+//        for (int i = 0; i < m; i++)
+//        {
+//            for (int j = 0; j < n; j++)
+//            {
+//                f = hypot(f, A[i][j]);
+//            }
+//        }
+//        return f;
+//    }
+//
+    /**
+     * Unary minus
+     *
+     * @return -A
+     */
+    public Matrix uminus()
+    {
+        Matrix X = new Matrix(m, n);
+        double[][] C = X.getArray();
+        for (int i = 0; i < m; i++)
+        {
+            for (int j = 0; j < n; j++)
+            {
+                C[i][j] = -A[i][j];
+            }
+        }
+        return X;
+    }
+
+    /**
+     * C = A + B
+     *
+     * @param B another matrix
+     * @return A + B
+     */
+    public Matrix plus(Matrix B)
+    {
+        checkMatrixDimensions(B);
+        Matrix X = new Matrix(m, n);
+        double[][] C = X.getArray();
+        for (int i = 0; i < m; i++)
+        {
+            for (int j = 0; j < n; j++)
+            {
+                C[i][j] = A[i][j] + B.A[i][j];
+            }
+        }
+        return X;
+    }
+
+//    /**
+//     * A = A + B
+//     *
+//     * @param B another matrix
+//     * @return A + B
+//     */
+//    public Matrix plusEquals(Matrix B)
+//    {
+//        checkMatrixDimensions(B);
+//        for (int i = 0; i < m; i++)
+//        {
+//            for (int j = 0; j < n; j++)
+//            {
+//                A[i][j] = A[i][j] + B.A[i][j];
+//            }
+//        }
+//        return this;
+//    }
+//
+    /**
+     * C = A - B
+     *
+     * @param B another matrix
+     * @return A - B
+     */
+    public Matrix minus(Matrix B)
+    {
+        checkMatrixDimensions(B);
+        Matrix X = new Matrix(m, n);
+        double[][] C = X.getArray();
+        for (int i = 0; i < m; i++)
+        {
+            for (int j = 0; j < n; j++)
+            {
+                C[i][j] = A[i][j] - B.A[i][j];
+            }
+        }
+        return X;
+    }
+
+//    /**
+//     * A = A - B
+//     *
+//     * @param B another matrix
+//     * @return A - B
+//     */
+//    public Matrix minusEquals(Matrix B)
+//    {
+//        checkMatrixDimensions(B);
+//        for (int i = 0; i < m; i++)
+//        {
+//            for (int j = 0; j < n; j++)
+//            {
+//                A[i][j] = A[i][j] - B.A[i][j];
+//            }
+//        }
+//        return this;
+//    }
+//
+//    /**
+//     * Element-by-element multiplication, C = A.*B
+//     *
+//     * @param B another matrix
+//     * @return A.*B
+//     */
+//    public Matrix arrayTimes(Matrix B)
+//    {
+//        checkMatrixDimensions(B);
+//        Matrix X = new Matrix(m, n);
+//        double[][] C = X.getArray();
+//        for (int i = 0; i < m; i++)
+//        {
+//            for (int j = 0; j < n; j++)
+//            {
+//                C[i][j] = A[i][j] * B.A[i][j];
+//            }
+//        }
+//        return X;
+//    }
+//
+//    /**
+//     * Element-by-element multiplication in place, A = A.*B
+//     *
+//     * @param B another matrix
+//     * @return A.*B
+//     */
+//    public Matrix arrayTimesEquals(Matrix B)
+//    {
+//        checkMatrixDimensions(B);
+//        for (int i = 0; i < m; i++)
+//        {
+//            for (int j = 0; j < n; j++)
+//            {
+//                A[i][j] = A[i][j] * B.A[i][j];
+//            }
+//        }
+//        return this;
+//    }
+//
+//    /**
+//     * Element-by-element right division, C = A./B
+//     *
+//     * @param B another matrix
+//     * @return A./B
+//     */
+//    public Matrix arrayRightDivide(Matrix B)
+//    {
+//        checkMatrixDimensions(B);
+//        Matrix X = new Matrix(m, n);
+//        double[][] C = X.getArray();
+//        for (int i = 0; i < m; i++)
+//        {
+//            for (int j = 0; j < n; j++)
+//            {
+//                C[i][j] = A[i][j] / B.A[i][j];
+//            }
+//        }
+//        return X;
+//    }
+//
+//    /**
+//     * Element-by-element right division in place, A = A./B
+//     *
+//     * @param B another matrix
+//     * @return A./B
+//     */
+//    public Matrix arrayRightDivideEquals(Matrix B)
+//    {
+//        checkMatrixDimensions(B);
+//        for (int i = 0; i < m; i++)
+//        {
+//            for (int j = 0; j < n; j++)
+//            {
+//                A[i][j] = A[i][j] / B.A[i][j];
+//            }
+//        }
+//        return this;
+//    }
+//
+//    /**
+//     * Element-by-element left division, C = A.\B
+//     *
+//     * @param B another matrix
+//     * @return A.\B
+//     */
+//    public Matrix arrayLeftDivide(Matrix B)
+//    {
+//        checkMatrixDimensions(B);
+//        Matrix X = new Matrix(m, n);
+//        double[][] C = X.getArray();
+//        for (int i = 0; i < m; i++)
+//        {
+//            for (int j = 0; j < n; j++)
+//            {
+//                C[i][j] = B.A[i][j] / A[i][j];
+//            }
+//        }
+//        return X;
+//    }
+//
+//    /**
+//     * Element-by-element left division in place, A = A.\B
+//     *
+//     * @param B another matrix
+//     * @return A.\B
+//     */
+//    public Matrix arrayLeftDivideEquals(Matrix B)
+//    {
+//        checkMatrixDimensions(B);
+//        for (int i = 0; i < m; i++)
+//        {
+//            for (int j = 0; j < n; j++)
+//            {
+//                A[i][j] = B.A[i][j] / A[i][j];
+//            }
+//        }
+//        return this;
+//    }
+//
+    /**
+     * Multiply a matrix by a scalar, C = s*A
+     *
+     * @param s scalar
+     * @return s*A
+     */
+    public Matrix times(double s)
+    {
+        Matrix X = new Matrix(m, n);
+        double[][] C = X.getArray();
+        for (int i = 0; i < m; i++)
+        {
+            for (int j = 0; j < n; j++)
+            {
+                C[i][j] = s * A[i][j];
+            }
+        }
+        return X;
+    }
+
+//    /**
+//     * Multiply a matrix by a scalar in place, A = s*A
+//     *
+//     * @param s scalar
+//     * @return replace A by s*A
+//     */
+//    public Matrix timesEquals(double s)
+//    {
+//        for (int i = 0; i < m; i++)
+//        {
+//            for (int j = 0; j < n; j++)
+//            {
+//                A[i][j] = s * A[i][j];
+//            }
+//        }
+//        return this;
+//    }
+//
+    /**
+     * Linear algebraic matrix multiplication, A * B
+     *
+     * @param B another matrix
+     * @return Matrix product, A * B
+     * @exception IllegalArgumentException Matrix inner dimensions must agree.
+     */
+    public Matrix times(Matrix B)
+    {
+        if (B.m != n)
+        {
+            throw new IllegalArgumentException("Matrix inner dimensions must agree.");
+        }
+        Matrix X = new Matrix(m, B.n);
+        double[][] C = X.getArray();
+        double[] Bcolj = new double[n];
+        for (int j = 0; j < B.n; j++)
+        {
+            for (int k = 0; k < n; k++)
+            {
+                Bcolj[k] = B.A[k][j];
+            }
+            for (int i = 0; i < m; i++)
+            {
+                double[] Arowi = A[i];
+                double s = 0;
+                for (int k = 0; k < n; k++)
+                {
+                    s += Arowi[k] * Bcolj[k];
+                }
+                C[i][j] = s;
+            }
+        }
+        return X;
+    }
+
+//    /**
+//     * Calculates the vector y = A.x
+//     *
+//     * @param x
+//     * @return a new vector y
[truncated at 1000 lines; 556 more skipped]

java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix
QRDecomposition.java added at 919
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/QRDecomposition.java	                        (rev 0)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/QRDecomposition.java	2014-08-28 15:31:06 UTC (rev 919)
@@ -0,0 +1,218 @@
+package org.hps.recon.tracking.gbl.matrix;
+
+
+/** QR Decomposition.
+<P>
+   For an m-by-n matrix A with m >= n, the QR decomposition is an m-by-n
+   orthogonal matrix Q and an n-by-n upper triangular matrix R so that
+   A = Q*R.
+<P>
+   The QR decompostion always exists, even if the matrix does not have
+   full rank, so the constructor will never fail.  The primary use of the
+   QR decomposition is in the least squares solution of nonsquare systems
+   of simultaneous linear equations.  This will fail if isFullRank()
+   returns false.
+   @version $Id: QRDecomposition.java,v 1.1.1.1 2010/11/30 21:31:59 jeremy Exp $
+*/
+
+public class QRDecomposition implements java.io.Serializable {
+
+/* ------------------------
+   Class variables
+ * ------------------------ */
+
+   /** Array for internal storage of decomposition.
+   @serial internal array storage.
+   */
+   private double[][] QR;
+
+   /** Row and column dimensions.
+   @serial column dimension.
+   @serial row dimension.
+   */
+   private int m, n;
+
+   /** Array for internal storage of diagonal of R.
+   @serial diagonal of R.
+   */
+   private double[] Rdiag;
+
+/* ------------------------
+   Constructor
+ * ------------------------ */
+
+   /** QR Decomposition, computed by Householder reflections.
+   @param A    Rectangular matrix
+   */
+
+   public QRDecomposition (Matrix A) {
+      // Initialize.
+      QR = A.getArrayCopy();
+      m = A.getRowDimension();
+      n = A.getColumnDimension();
+      Rdiag = new double[n];
+
+      // Main loop.
+      for (int k = 0; k < n; k++) {
+         // Compute 2-norm of k-th column without under/overflow.
+         double nrm = 0;
+         for (int i = k; i < m; i++) {
+            nrm = Matrix.hypot(nrm,QR[i][k]);
+         }
+
+         if (nrm != 0.0) {
+            // Form k-th Householder vector.
+            if (QR[k][k] < 0) {
+               nrm = -nrm;
+            }
+            for (int i = k; i < m; i++) {
+               QR[i][k] /= nrm;
+            }
+            QR[k][k] += 1.0;
+
+            // Apply transformation to remaining columns.
+            for (int j = k+1; j < n; j++) {
+               double s = 0.0; 
+               for (int i = k; i < m; i++) {
+                  s += QR[i][k]*QR[i][j];
+               }
+               s = -s/QR[k][k];
+               for (int i = k; i < m; i++) {
+                  QR[i][j] += s*QR[i][k];
+               }
+            }
+         }
+         Rdiag[k] = -nrm;
+      }
+   }
+
+/* ------------------------
+   Public Methods
+ * ------------------------ */
+
+   /** Is the matrix full rank?
+   @return     true if R, and hence A, has full rank.
+   */
+
+   public boolean isFullRank () {
+      for (int j = 0; j < n; j++) {
+         if (Rdiag[j] == 0)
+            return false;
+      }
+      return true;
+   }
+
+   /** Return the Householder vectors
+   @return     Lower trapezoidal matrix whose columns define the reflections
+   */
+
+   public Matrix getH () {
+      Matrix X = new Matrix(m,n);
+      double[][] H = X.getArray();
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            if (i >= j) {
+               H[i][j] = QR[i][j];
+            } else {
+               H[i][j] = 0.0;
+            }
+         }
+      }
+      return X;
+   }
+
+   /** Return the upper triangular factor
+   @return     R
+   */
+
+   public Matrix getR () {
+      Matrix X = new Matrix(n,n);
+      double[][] R = X.getArray();
+      for (int i = 0; i < n; i++) {
+         for (int j = 0; j < n; j++) {
+            if (i < j) {
+               R[i][j] = QR[i][j];
+            } else if (i == j) {
+               R[i][j] = Rdiag[i];
+            } else {
+               R[i][j] = 0.0;
+            }
+         }
+      }
+      return X;
+   }
+
+   /** Generate and return the (economy-sized) orthogonal factor
+   @return     Q
+   */
+
+   public Matrix getQ () {
+      Matrix X = new Matrix(m,n);
+      double[][] Q = X.getArray();
+      for (int k = n-1; k >= 0; k--) {
+         for (int i = 0; i < m; i++) {
+            Q[i][k] = 0.0;
+         }
+         Q[k][k] = 1.0;
+         for (int j = k; j < n; j++) {
+            if (QR[k][k] != 0) {
+               double s = 0.0;
+               for (int i = k; i < m; i++) {
+                  s += QR[i][k]*Q[i][j];
+               }
+               s = -s/QR[k][k];
+               for (int i = k; i < m; i++) {
+                  Q[i][j] += s*QR[i][k];
+               }
+            }
+         }
+      }
+      return X;
+   }
+
+   /** Least squares solution of A*X = B
+   @param B    A Matrix with as many rows as A and any number of columns.
+   @return     X that minimizes the two norm of Q*R*X-B.
+   @exception  IllegalArgumentException  Matrix row dimensions must agree.
+   @exception  RuntimeException  Matrix is rank deficient.
+   */
+
+   public Matrix solve (Matrix B) {
+      if (B.getRowDimension() != m) {
+         throw new IllegalArgumentException("Matrix row dimensions must agree.");
+      }
+      if (!this.isFullRank()) {
+         throw new RuntimeException("Matrix is rank deficient.");
+      }
+      
+      // Copy right hand side
+      int nx = B.getColumnDimension();
+      double[][] X = B.getArrayCopy();
+
+      // Compute Y = transpose(Q)*B
+      for (int k = 0; k < n; k++) {
+         for (int j = 0; j < nx; j++) {
+            double s = 0.0; 
+            for (int i = k; i < m; i++) {
+               s += QR[i][k]*X[i][j];
+            }
+            s = -s/QR[k][k];
+            for (int i = k; i < m; i++) {
+               X[i][j] += s*QR[i][k];
+            }
+         }
+      }
+      // Solve R*X = Y;
+      for (int k = n-1; k >= 0; k--) {
+         for (int j = 0; j < nx; j++) {
+            X[k][j] /= Rdiag[k];
+         }
+         for (int i = 0; i < k; i++) {
+            for (int j = 0; j < nx; j++) {
+               X[i][j] -= X[k][j]*QR[i][k];
+            }
+         }
+      }
+      return (new Matrix(X,n,nx).getMatrix(0,n-1,0,nx-1));
+   }
+}

java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix
SymMatrix.java added at 919
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/SymMatrix.java	                        (rev 0)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/SymMatrix.java	2014-08-28 15:31:06 UTC (rev 919)
@@ -0,0 +1,66 @@
+package org.hps.recon.tracking.gbl.matrix;
+
+/**
+ *
+ * @author Norman A Graf
+ * 
+ *  @version $Id:
+ */
+public class SymMatrix extends Matrix implements java.io.Serializable
+{
+
+    public SymMatrix(int n)
+    {
+        super(n, n);
+    }
+
+    public SymMatrix(SymMatrix smat)
+    {
+        super(smat.getRowDimension(), smat.getColumnDimension());
+        for (int i = 0; i < m; i++)
+        {
+            for (int j = 0; j < n; j++)
+            {
+                A[i][j] = smat.get(i, j);
+            }
+        }
+    }
+    
+    public SymMatrix(Matrix mat)
+    {
+        super(mat.getRowDimension(), mat.getColumnDimension());
+        for (int i = 0; i < m; i++)
+        {
+            for (int j = 0; j < n; j++)
+            {
+                A[i][j] = mat.get(i, j);
+            }
+        }
+    }
+
+    @Override
+    public void set(int i, int j, double s)
+    {
+        super.set(i, j, s);
+        super.set(j, i, s);
+    }
+
+    public void setToIdentity()
+    {
+        for (int i = 0; i < m; i++)
+        {
+            for (int j = 0; j < n; j++)
+            {
+                A[i][j] = (i == j ? 1.0 : 0.0);
+            }
+        }
+    } 
+    
+    //Calculate B * (this) * B^T , final matrix will be (nrowsb x nrowsb)
+    //TODO see if this needs to be made more efficient
+    public SymMatrix Similarity(Matrix b)
+    {
+        SymMatrix X =  new SymMatrix(b.times(this.times(b.transpose())));
+        return X;
+    }
+}

java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix
VMatrix.java added at 919
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/VMatrix.java	                        (rev 0)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/VMatrix.java	2014-08-28 15:31:06 UTC (rev 919)
@@ -0,0 +1,201 @@
+package org.hps.recon.tracking.gbl.matrix;
+
+import static java.lang.Math.min;
+import java.util.ArrayList;
+
+/**
+ * Simple Vector based on ArrayList
+ *
+ * @author Norman A. Graf
+ *
+ * @version $Id$
+ */
+public class VMatrix
+{
+
+    private int numRows;
+    private int numCols;
+    //TODO replace with a simple double[]
+    private ArrayList theVec;
+
+    public VMatrix(int nRows, int nCols)
+    {
+        numRows = nRows;
+        numCols = nCols;
+        theVec = new ArrayList(nRows * nCols);
+        for (int i = 0; i < numRows * nCols; ++i)
+        {
+            theVec.add(0.);
+        }
+    }
+    
+public VMatrix(VMatrix m)
+    {
+        numRows = m.numRows;
+        numCols = m.numCols;
+        theVec = new ArrayList(numRows * numCols);
+        for (int i = 0; i < numRows; ++i)
+        {
+            for(int j=0; j<numCols; ++j)
+            {
+            theVec.set(numCols * i + j, m.get(i, j));
+            }
+        }
+    }    
+
+    public VMatrix copy()
+    {
+        VMatrix aResult = new VMatrix(numRows, numCols);
+        for (int i = 0; i < numRows; ++i)
+        {
+            for (int j = 0; j < numCols; ++j)
+            {
+                {
+                    aResult.set(i, j, get(i, j));
+                }
+            }
+        }
+        return aResult;
+    }
+
+    /// Resize Matrix.
+    /**
+     * \param [in] nRows Number of rows. \param [in] nCols Number of columns.
+     */
+    // TODO understand what this method is supposed to do.
+    // may not need it as ArrayList already automatically resizes...
+    public void resize(int nRows, int nCols)
+    {
+        numRows = nRows;
+        numCols = nCols;
+        theVec = new ArrayList(numRows * nCols);
+        for (int i = 0; i < numRows * nCols; ++i)
+        {
+            theVec.add(0.);
+        }
+    }
+
+/// Get transposed matrix.
+    /**
+     * \return Transposed matrix.
+     */
+    public VMatrix transpose()
+    {
+        VMatrix aResult = new VMatrix(numCols, numRows);
+        for (int i = 0; i < numRows; ++i)
+        {
+            for (int j = 0; j < numCols; ++j)
+            {
+                //System.out.println("row: "+i+" col: "+j+" val: "+theVec.get(numCols * i + j));
+                aResult.set(j, i, (double) theVec.get(numCols * i + j));
+            }
+        }
+        return aResult;
+    }
+
+    public void set(int row, int col, double val)
+    {
+        theVec.set(numCols * row + col, val);
+    }
+    
+     public void addTo(int row, int col, double val)
+    {
+        theVec.set(numCols * row + col, (double) theVec.get(numCols * row + col)+val);
+    }
+     public void subFrom(int row, int col, double val)
+    {
+        theVec.set(numCols * row + col, (double) theVec.get(numCols * row + col)-val);
+    }
+
+    public double get(int row, int col)
+    {
+        return (double) theVec.get(numCols * row + col);
+    }
+
+/// Get number of rows.
+    /**
+     * \return Number of rows.
+     */
+    int getNumRows()
+    {
+        return numRows;
+    }
+
+/// Get number of columns.
+    /**
+     * \return Number of columns.
+     */
+    int getNumCols()
+    {
+        return numCols;
+    }
+
+/// Multiplication Matrix*Vector.
+    VVector times(VVector aVector)
+    {
+        VVector aResult = new VVector(numRows);
+        for (int i = 0; i < numRows; ++i)
+        {
+            double sum = 0.0;
+            for (int j = 0; j < numCols; ++j)
+            {
+                sum += (double) theVec.get(numCols * i + j) * aVector.get(j);
+            }
+            aResult.set(i, sum);
+        }
+        return aResult;
+    }
+
+// Multiplication Matrix*Matrix.
+    VMatrix times(VMatrix aMatrix)
+    {
+
+        VMatrix aResult = new VMatrix(numRows, aMatrix.numCols);
+        for (int i = 0; i < numRows; ++i)
+        {
+            for (int j = 0; j < aMatrix.numCols; ++j)
+            {
+                double sum = 0.0;
+                for (int k = 0; k < numCols; ++k)
+                {
+                    sum += (double) theVec.get(numCols * i + k) * aMatrix.get(k, j);
+                }
+                aResult.set(i, j, sum);
+            }
+        }
+        return aResult;
+    }
+
+/// Addition Matrix+Matrix.
+    VMatrix plus(VMatrix aMatrix)
+    {
+        VMatrix aResult = new VMatrix(numRows, numCols);
+        for (int i = 0; i < numRows; ++i)
+        {
+            for (int j = 0; j < numCols; ++j)
+            {
+                aResult.set(i, j, (double) theVec.get(numCols * i + j) + (double) aMatrix.get(i, j));
+            }
+        }
+        return aResult;
+    }
+
+/// Print matrix.
+    public void print()
+    {
+        System.out.println(" VMatrix: " + numRows + "*" + numCols);
+        for (int i = 0; i < numRows; ++i)
+        {
+            for (int j = 0; j < numCols; ++j)
+            {
+                if (j % 5 == 0)
+                {
+                    System.out.format("%n%4d " + "," + "%4d" + " - " + "%4d" + " : ", i, j, min(j + 4, numCols));
+                }
+                System.out.format("%13f", theVec.get(numCols * i + j));
+            }
+        }
+        System.out.print("\n\n\n");
+    }
+
+}

java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix
VSymMatrix.java added at 919
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/VSymMatrix.java	                        (rev 0)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/VSymMatrix.java	2014-08-28 15:31:06 UTC (rev 919)
@@ -0,0 +1,303 @@
+package org.hps.recon.tracking.gbl.matrix;
+
+import static java.lang.Math.min;
+import static java.lang.Math.max;
+import static java.lang.Math.abs;
+import java.util.ArrayList;
+
+/**
+ * Simple symmetric Matrix based on ArrayList
+ *
+ * @author Norman A. Graf
+ *
+ * @version $Id$
+ */
+public class VSymMatrix
+{
+
+    private int numRows;
+    //TODO replace with a simple double[]
+    private ArrayList theVec;
+
+    public VSymMatrix(int nRows)
+    {
+        numRows = nRows;
+        theVec = new ArrayList((nRows * nRows + nRows) / 2);
+        for (int i = 0; i < (nRows * nRows + nRows) / 2; ++i)
+        {
+            theVec.add(i, 0.);
+        }
+    }
+
+    public VSymMatrix copy()
+    {
+        VSymMatrix aResult = new VSymMatrix(numRows);
+        for (int i = 0; i < numRows; ++i)
+        {
+            for (int j = 0; j < numRows; ++j)
+            {
+                {
+                    aResult.set(i, j, get(i, j));
+                }
+            }
+        }
+        return aResult;
+    }
+
+/// Resize symmetric matrix.
+    /**
+     * \param [in] nRows Number of rows.
+     */
+    // TODO understand what this method is supposed to do.
+    // may not need it as ArrayList already automatically resizes...
+    void resize(int nRows)
+    {
+        numRows = nRows;
+        theVec = new ArrayList(nRows * nRows + nRows);
+        for (int i = 0; i < nRows * nRows + nRows; ++i)
+        {
+            theVec.add(0.);
+        }
+    }
+
+/// Get number of rows (= number of colums).
+    /**
+     * \return Number of rows.
+     */
+    int getNumRows()
+    {
+        return numRows;
+    }
+
+    public void set(int row, int col, double val)
+    {
+        theVec.set((row * row + row) / 2 + col, val);
+    }
+
+    public void addTo(int row, int col, double val)
+    {
+        theVec.set((row * row + row) / 2 + col, (double) theVec.get((row * row + row) / 2 + col) + val);
+    }
+    
+    public void subFrom(int row, int col, double val)
+    {
+        theVec.set((row * row + row) / 2 + col, (double) theVec.get((row * row + row) / 2 + col) - val);
+    }
+
+    public double get(int row, int col)
+    {
+        return (double) theVec.get((row * row + row) / 2 + col);
+    }
+
+/// Print matrix.
+    void print()
+    {
+        System.out.println(" VSymMatrix: " + numRows + "*" + numRows);
+        for (int i = 0; i < numRows; ++i)
+        {
+            for (int j = 0; j <= i; ++j)
+            {
+                if (j % 5 == 0)
+                {
+                    System.out.format("%n%4d " + "," + "%4d" + " - " + "%4d" + " : ", i, j, min(j + 4, i));
+                }
+                System.out.format("%13f", theVec.get((i * i + i) / 2 + j));
+            }
+        }
+        System.out.print("\n\n\n");
+    }
+
+/// Subtraction SymMatrix-(sym)Matrix.
+    VSymMatrix minus(VMatrix aMatrix)
+    {
+        VSymMatrix aResult = new VSymMatrix(numRows);
+        for (int i = 0; i < numRows; ++i)
+        {
+            for (int j = 0; j <= i; ++j)
+            {
+                aResult.set(i, j, (double) theVec.get((i * i + i) / 2 + j) - (double) aMatrix.get(i, j));
+            }
+        }
+        return aResult;
+    }
+
+/// Multiplication SymMatrix*Vector.
+    VVector times(VVector aVector)
+    {
+        VVector aResult = new VVector(numRows);
+        for (int i = 0; i < numRows; ++i)
+        {
+            aResult.set(i, (double) theVec.get((i * i + i) / 2 + i) * (double) aVector.get(i));
+            for (int j = 0; j < i; ++j)
+            {
+                aResult.set(j, aResult.get(j) + (double) theVec.get((i * i + i) / 2 + j) * aVector.get(i));
+                aResult.set(i, aResult.get(i) + (double) theVec.get((i * i + i) / 2 + j) * aVector.get(j));
+            }
+        }
+        return aResult;
+    }
+
+/// Multiplication SymMatrix*Matrix.
+    VMatrix times(VMatrix aMatrix)
+    {
+        int nCol = aMatrix.getNumCols();
+        VMatrix aResult = new VMatrix(numRows, nCol);
+        for (int l = 0; l < nCol; ++l)
+        {
+            for (int i = 0; i < numRows; ++i)
+            {
+                aResult.set(i, l, (double) theVec.get((i * i + i) / 2 + i) * (double) aMatrix.get(i, l));
+                for (int j = 0; j < i; ++j)
+                {
+                    aResult.set(j, l, aResult.get(j, l) + (double) theVec.get((i * i + i) / 2 + j) * aMatrix.get(i, l));
+                    aResult.set(i, l, aResult.get(i, l) + (double) theVec.get((i * i + i) / 2 + j) * aMatrix.get(j, l));
+                }
+            }
+        }
+        return aResult;
+    }
+
+    /*============================================================================
+     from mpnum.F (MillePede-II by V. Blobel, Univ. Hamburg)
+     ============================================================================*/
+/// Matrix inversion.
+    /**
+     * Invert symmetric N-by-N matrix V in symmetric storage mode V(1) = V11,
+     * V(2) = V12, V(3) = V22, V(4) = V13, . . . replaced by inverse matrix
+     *
+     * Method of solution is by elimination selecting the pivot on the diagonal
+     * each stage. The rank of the matrix is returned in NRANK. For NRANK ne N,
+     * all remaining rows and cols of the resulting matrix V are set to zero.
+     * \exception 1 : matrix is singular. \return Rank of matrix.
+     */
+    public int invert()
+    {
+
+        final double eps = 1.0E-10;
+        int aSize = numRows;
+        int[] next = new int[aSize];
+        double[] diag = new double[aSize];
+        int nSize = aSize;
+
+        int first = 1;
+        for (int i = 1; i <= nSize; ++i)
+        {
+            next[i - 1] = i + 1; // set "next" pointer
+            diag[i - 1] = abs((double) theVec.get((i * i + i) / 2 - 1)); // save abs of diagonal elements
+        }
+        next[aSize - 1] = -1; // end flag
+
+        int nrank = 0;
+        for (int i = 1; i <= nSize; ++i)
+        { // start of loop
+            int k1 = 0;
+            double vkk = 0.0;
+
+            int j1 = first;
+            int previous = 0;
+            int last = previous;
+            // look for pivot
+            while (j1 > 0)
+            {
+                int jj = (j1 * j1 + j1) / 2 - 1;
+                if (abs((double) theVec.get(jj)) > max(abs(vkk), eps * diag[j1 - 1]))
+                {
+                    vkk = (double) theVec.get(jj);
+                    k1 = j1;
+                    last = previous;
+                }
+                previous = j1;
+                j1 = next[j1 - 1];
+            }
+            // pivot found
+            if (k1 > 0)
+            {
+                int kk = (k1 * k1 + k1) / 2 - 1;
+                if (last <= 0)
+                {
+                    first = next[k1 - 1];
+                } else
+                {
+                    next[last - 1] = next[k1 - 1];
+                }
+                next[k1 - 1] = 0; // index is used, reset
+                nrank++; // increase rank and ...
+
+                vkk = 1.0 / vkk;
+                theVec.set(kk, -vkk);
+                int jk = kk - k1;
+                int jl = -1;
+                for (int j = 1; j <= nSize; ++j)
+                { // elimination
+                    if (j == k1)
+                    {
+                        jk = kk;
+                        jl += j;
+                    } else
+                    {
+                        if (j < k1)
+                        {
+                            ++jk;
+                        } else
+                        {
+                            jk += j - 1;
+                        }
+
+                        double vjk = (double) theVec.get(jk);
+                        theVec.set(jk, vkk * vjk);
+                        int lk = kk - k1;
+                        if (j >= k1)
+                        {
+                            for (int l = 1; l <= k1 - 1; ++l)
+                            {
+                                ++jl;
+                                ++lk;
+                                theVec.set(jl, (double) theVec.get(jl) - (double) theVec.get(lk) * vjk);
+                            }
+                            ++jl;
+                            lk = kk;
+                            for (int l = k1 + 1; l <= j; ++l)
+                            {
+                                ++jl;
+                                lk += l - 1;
+                                theVec.set(jl, (double) theVec.get(jl) - (double) theVec.get(lk) * vjk);
+                            }
+                        } else
+                        {
+                            for (int l = 1; l <= j; ++l)
+                            {
+                                ++jl;
+                                ++lk;
+                                theVec.set(jl, (double) theVec.get(jl) - (double) theVec.get(lk) * vjk);
+                            }
+                        }
+                    }
+                }
+
+            } else
+            {
+                for (int k = 1; k <= nSize; ++k)
+                {
+                    if (next[k - 1] >= 0)
+                    {
+                        int kk = (k * k - k) / 2 - 1;
+                        for (int j = 1; j <= nSize; ++j)
+                        {
+                            if (next[j - 1] >= 0)
+                            {
+                                theVec.set(kk + j, 0.0); // clear matrix row/col
+                            }
+                        }
+                    }
+                }
+                throw new RuntimeException("Symmetric matrix inversion is singular");//1; // singular
+            }
+        }
+        for (int ij = 0; ij < (nSize * nSize + nSize) / 2; ++ij)
+        {
+            theVec.set(ij, -(double) theVec.get(ij)); // finally reverse sign of all matrix elements
+        }
+        return nrank;
+    }
+
+}

java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix
VVector.java added at 919
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/VVector.java	                        (rev 0)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/VVector.java	2014-08-28 15:31:06 UTC (rev 919)
@@ -0,0 +1,129 @@
+package org.hps.recon.tracking.gbl.matrix;
+
+import java.util.ArrayList;
+import java.util.List;
+import static java.lang.Math.min;
+
+/**
+ * Simple Vector based on ArrayList
+ *
+ * @author Norman A. Graf
+ *
+ * @version $Id$
+ */
+public class VVector
+{
+
+    private int numRows;
+    private ArrayList theVec;
+
+    public VVector(int nRows)
+    {
+        numRows = nRows;
+        theVec = new ArrayList(nRows);
+        for (int i = 0; i < numRows; ++i)
+        {
+            theVec.add(0.);
+        }
+    }
+
+    public VVector(VVector old)
+    {
+        numRows = old.numRows;
+        theVec = new ArrayList(old.theVec);
+    }
+
+    public VVector(List list)
+    {
+        theVec = new ArrayList(list);
+        theVec.trimToSize();
+        numRows = theVec.size();
+    }
+
+    public void set(int row, double val)
+    {
+        theVec.set(row, val);
+    }
+    
+    public void addTo(int row, double val)
+    {
+        theVec.set(row, (double) theVec.get(row) + val);
+    }
+    
+    public void subFrom(int row, double val)
+    {
+        theVec.set(row, (double) theVec.get(row) - val);
+    }
+
+    public double get(int row)
+    {
+        return (double) theVec.get(row);
+    }
+
+    //Get part of vector.
+    /**
+     * \param [in] len Length of part. \param [in] start Offset of part. \return
+     * Part of vector.
+     */
+    public VVector getVec(int len, int start)
+    {
+        return new VVector(theVec.subList(start, start + len - 1));
+
+    }
+
+/// Put part of vector.
+    /**
+     * \param [in] aVector Vector with part. \param [in] start Offset of part.
+     */
+    public void putVec(VVector aVector, int start)
+    {
+        theVec.addAll(start, aVector.theVec);
+    }
+
+/// Get number of rows.
+    /**
+     * \return Number of rows.
+     */
+    int getNumRows()
+    {
+        return numRows;
+    }
+
+/// Print vector.
+    public void print()
+    {
+        System.out.println(theVec.size());
+        for (int i = 0; i < numRows; ++i)
+        {
+            if (i % 5 == 0)
+            {
+                System.out.format("%n%4d " + " - " + "%4d" + " : ", i, min(i + 4, numRows));
+            }
+            System.out.format("%13f", theVec.get(i));
+        }
+        System.out.print("\n\n\n");
+    }
+
+/// Subtraction Vector-Vector.
+    VVector minus(VVector aVector)
+    {
+        VVector aResult = new VVector(numRows);
+        for (int i = 0; i < numRows; ++i)
+        {
+            aResult.set(i, (double) theVec.get(i) - aVector.get(i));
+        }
+        return aResult;
+    }
+
+/// Assignment Vector=Vector.
+    public VVector copy()
+    {
+        VVector aResult = new VVector(numRows);
+        for (int i = 0; i < numRows; ++i)
+        {
+            aResult.set(i, get(i));
+        }
+        return aResult;
+    }
+
+}

java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix
Vector.java added at 919
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/Vector.java	                        (rev 0)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/Vector.java	2014-08-28 15:31:06 UTC (rev 919)
@@ -0,0 +1,337 @@
+package org.hps.recon.tracking.gbl.matrix;
+
+import java.io.PrintWriter;
+
+/**
+ * Specializes the Matrix class to a vector.
+ *
+ * @author CKAllen
+ * @author Norman A. Graf (modifications for the gbl package)
+ * @version $Id$
+ */
+public class Vector extends Matrix implements java.io.Serializable
+{
+//
+    /**
+     * Constructs a column vector of zeros
+     *
+     *
+     * @param nSize vector size
+     *
+     */
+    public Vector(int nSize)
+    {
+        super(nSize, 1);
+    }
+
+//    /**
+//     * Constructs a constant column vector
+//     *
+//     * @param nSize vector size
+//     * @param dblVal constant value
+//     */
+//    public Vector(int nSize, double dblVal)
+//    {
+//        super(nSize, 1, dblVal);
+//    }
+//
+    public int size()
+    {
+        return getRowDimension();
+    }
+
+//    public Vector getSub(int start, int end)
+//    {
+//        int size = end - start + 1;
+//        Vector X = new Vector(size);
+//        for (int i = 0; i < size; ++i) {
+//            X.set(i, get(i + start, 0));
+//        }
+//        return X;
+//    }
+//
+    public Vector minus(Vector v)
+    {
+        Vector x = copyVector();
+        for (int i = 0; i < v.size(); ++i) {
+            x.minusEquals(i, v.get(i));
+        }
+        return x;
+    }
+
+    public void plusEquals(int i, double val)
+    {
+        A[i][0] += val;
+    }
+
+    public void minusEquals(int i, double val)
+    {
+        A[i][0] -= val;
+    }
+
+    public Vector uminus()
+    {
+        Vector x = copyVector();
+        for (int i = 0; i < size(); ++i) {
+            A[i][0] = -A[i][0];
+        }
+        return x;
+    }
+
+    /**
+     * Constructs a Vector specified by the double array
+     *
+     * @param arrVals element values for vector
+     */
+    public Vector(double[] arrVals)
+    {
+        super(arrVals.length, 1);
+        for (int i = 0; i < arrVals.length; i++) {
+            super.set(i, 0, arrVals[i]);
+        }
+    }
+
+//    /**
+//     * Copy Constructor Constructs a new Vector initialized to the argument.
+//     *
+//     * @param vecInit initial value
+//     */
+//    public Vector(Vector vecInit)
+//    {
+//        this(vecInit.getSize());
+//        for (int i = 0; i < vecInit.getSize(); i++) {
+//            this.set(i, vecInit.get(i));
+//        }
+//    }
+//
+    /**
+     * Constructs a new Vector from a Matrix object. Vector is initialized to
+     * the first column of the matrix. This constructor is meant to take a
+     * column vector in Matrix form to the standard vector format.
+     *
+     * @param mat initial values
+     */
+    public Vector(Matrix mat)
+    {
+        super(mat.getRowDimension(), 1);
+        for (int i = 0; i < mat.getRowDimension(); i++) {
+            this.set(i, mat.get(i, 0));
+        }
+    }
+
+    /**
+     * Perform a deep copy of this Vector object
+     */
+    public Vector copyVector()
+    {
+        return new Vector(this);
+    }
+
+    /**
+     * Get size of Vector (number of elements)
+     */
+    public int getSize()
+    {
+        return super.getRowDimension();
+    }
+
+    /**
+     * Get individual element of a vector
+     *
+     * @param iIndex index of element
+     * @return value of element
+     * @exception ArrayIndexOutOfBoundsException iIndex is larger than vector
+     * size
+     */
+    public double get(int iIndex) throws ArrayIndexOutOfBoundsException
+    {
+        return this.get(iIndex, 0);
+    }
+//
+    /**
+     * Set individual element of a vector
+     *
+     * @param iIndex index of element
+     * @param dblVal new value of element
+     *
+     * @exception ArrayIndexOutOfBoundsException iIndex is larger than the
+     * vector
+     */
+    public void set(int iIndex, double dblVal) throws ArrayIndexOutOfBoundsException
+    {
+        super.set(iIndex, 0, dblVal);
+    }
+
+//    /**
+//     * Vector in-place addition
+//     *
+//     * @param vec Vector to add to this vector
+//     *
+//     * @exception IllegalArgumentException vec is not proper dimension
+//     */
+//    public void plusEquals(Vector vec) throws IllegalArgumentException
+//    {
+//        super.plusEquals(vec);
+//    }
+//
+    /**
+     * Vector addition without destruction
+     *
+     * @param vec vector to add
+     *
+     * @exception IllegalArgumentException vec is not proper dimension
+     */
+
+    public Vector plus(Vector vec) throws IllegalArgumentException
+    {
+        return (Vector) super.plus(vec);
+    }
+
+    /**
+     * Scalar multiplication
+     *
+     * @param s scalar value
+     *
+     * @return result of scalar multiplication
+     */
+    public Vector timesScalar(double s)
+    {
+        return (Vector) super.times(s);
+    }
+
+//    /**
+//     * In place scalar multiplication
+//     *
+//     * @param s scalar
+//     */
+//    public void timesScalarEqual(double s)
+//    {
+//        this.timesEquals(s);
+//    }
+//
+//    /**
+//     * Vector inner product.
+//     *
+//     * Computes the inner product of two vectors of the same dimension.
+//     *
+//     * @param vec second vector
+//     *
+//     * @return inner product of this vector and argument
+//     *
+//     * @exception IllegalArgumentException dimensions must agree
+//     */
+//    public double innerProd(Vector vec) throws IllegalArgumentException
+//    {
+//        int N;      // vector dimensions
+//        int n;      // coordinate index
+//        double dblSum; // running sum
+//        N = vec.getSize();
+//        if (this.getSize() != N) {
+//            throw new IllegalArgumentException("Vector#innerProd() - unequal dimensions.");
+//        }
+//        dblSum = 0.0;
+//        for (n = 0; n < N; n++) {
+//            dblSum += this.get(n) * vec.get(n);
+//        }
+//        return dblSum;
+//    }
+//
+//    /**
+//     *
+//     * Vector outer product - computes the tensor product of two vector objects.
+//     *
+//     *
+//     *
+//     * Returns the value this*vec' where the prime indicates transposition
+//     *
+//     *
+//     *
+//     * @param vec right argument
+//     *
+//     *
+//     *
+//     * @return outer product *
+//     *
+//     *
+//     * @exception IllegalArgumentException vector dimension must agree
+//     *
+//     */
+//    public Matrix outerProd(Vector vec) throws IllegalArgumentException
+//    {
+//        return super.times(vec.transpose());
+//    }
+//
+//    /**
+//     * *
+//     * Vector left multiplication (post-multiply vector by matrix).
+//     *
+//     *
+//     *
+//     * @param mat matrix operator
+//     *
+//     *
+//     *
+//     * @return result of vector-matrix product
+//     *
+//     *
+//     *
+//     * @exception IllegalArgumentException dimensions must agree
+//     *
+//     */
+//    public Vector leftMultiply(Matrix mat) throws IllegalArgumentException
+//    {
+//        Matrix matRes = this.times(mat).transpose();
+//        return new Vector(matRes);
+//    }
+//
+//    /**
+//     * Vector right multiplication (pre-multiply vector by matrix).
+//     *
+//     * @param mat matrix operator
+//     *
+//     * @return result of vector-matrix product
+//     *
+//     * @exception IllegalArgumentException dimensions must agree
+//     */
+//    public Vector rightMultiply(Matrix mat) throws IllegalArgumentException
+//    {
+//        Matrix matRes = mat.times(this);
+//        return new Vector(matRes);
+//    }
+//
+//    /**
+//     * Print the vector contents to an output stream, does not add new line.
+//     *
+//     * @param os output stream object
+//     */
+//    public void print(PrintWriter os)
+//    {
+//        // Create vector string
+//        int indLast = this.getSize() - 1;
+//        String strVec = "(";
+//        for (int i = 0; i < indLast; i++) {
+//            strVec = strVec + this.get(i) + ",";
+//        }
+//        strVec = strVec + this.get(indLast) + ")";
+//        // Send to output stream
+//        os.print(strVec);
+//    }
+//
+//    /**
+//     * Print the vector contents to an output stream, add new line character.
+//     *
+//     * @param os output stream object
+//     */
+//    public void println(PrintWriter os)
+//    {
+//        // Create vector string
+//        int indLast = this.getSize() - 1;
+//        String strVec = "(";
+//        for (int i = 0; i < indLast; i++) {
+//            strVec = strVec + this.get(i) + ",";
+//        }
+//        strVec = strVec + this.get(indLast) + ")";
+//        // Send to output stream
+//        os.println(strVec);
+//    }
+}
SVNspam 0.1