gt:         if (currentMean.hasNext()) {
context: /*
   * LoadingsGibbsOperator.java
   *
   * Copyright (c) 2002-2014 Alexei Drummond, Andrew Rambaut and Marc Suchard
   *
   * This file is part of BEAST.
   * See the NOTICE file distributed with this work for additional
   * information regarding copyright ownership and licensing.
   *
   * BEAST is free software; you can redistribute it and/or modify
   * it under the terms of the GNU Lesser General Public License as
   * published by the Free Software Foundation; either version 2
   * of the License, or (at your option) any later version.
   *
   *  BEAST is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *  GNU Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
   * License along with BEAST; if not, write to the
   * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
   * Boston, MA  02110-1301  USA
   */
  
  package dr.inference.operators;
  
  import dr.inference.distribution.DistributionLikelihood;
  import dr.inference.model.LatentFactorModel;
  import dr.inference.model.MatrixParameter;
  import dr.inference.model.TransposedBlockUpperTriangularMatrixParameter;
  import dr.math.MathUtils;
  import dr.math.distributions.MultivariateNormalDistribution;
  import dr.math.distributions.NormalDistribution;
  import dr.math.matrixAlgebra.CholeskyDecomposition;
  import dr.math.matrixAlgebra.IllegalDimension;
  import dr.math.matrixAlgebra.SymmetricMatrix;
  
  import java.util.ArrayList;
  import java.util.ListIterator;
  
  /**
   * Created with IntelliJ IDEA.
   * User: max
   * Date: 5/23/14
   * Time: 2:23 PM
   * To change this template use File | Settings | File Templates.
   */
  public class LoadingsGibbsOperator extends SimpleMCMCOperator implements GibbsOperator {
      NormalDistribution prior;
      LatentFactorModel LFM;
      ArrayList<double[][]> precisionArray;
      ArrayList<double[]> meanMidArray;
      ArrayList<double[]> meanArray;
      boolean randomScan;
      double pathParameter=1.0;
  
  
      double priorPrecision;
      double priorMeanPrecision;
  
      public LoadingsGibbsOperator(LatentFactorModel LFM, DistributionLikelihood prior, double weight, boolean randomScan) {
          setWeight(weight);
  
          this.prior = (NormalDistribution) prior.getDistribution();
          this.LFM = LFM;
          precisionArray = new ArrayList<double[][]>();
          double[][] temp;
          this.randomScan = randomScan;
  
  
          meanArray = new ArrayList<double[]>();
          meanMidArray = new ArrayList<double[]>();
          double[] tempMean;
          if (!randomScan) {
              for (int i = 0; i < LFM.getFactorDimension(); i++) {
                  temp = new double[i + 1][i + 1];
                  precisionArray.add(temp);
              }
              for (int i = 0; i < LFM.getFactorDimension(); i++) {
                  tempMean = new double[i + 1];
                  meanArray.add(tempMean);
              }
  
              for (int i = 0; i < LFM.getFactorDimension(); i++) {
                  tempMean = new double[i + 1];
                  meanMidArray.add(tempMean);
              }
          } else {
              for (int i = 0; i < LFM.getFactorDimension(); i++) {
                  temp = new double[LFM.getFactorDimension() - i][LFM.getFactorDimension() - i];
                  precisionArray.add(temp);
              }
              for (int i = 0; i < LFM.getFactorDimension(); i++) {
                  tempMean = new double[LFM.getFactorDimension() - i];
                  meanArray.add(tempMean);
              }
  
              for (int i = 0; i < LFM.getFactorDimension(); i++) {
                  tempMean = new double[LFM.getFactorDimension() - i];
                  meanMidArray.add(tempMean);
              }
          }
  
  //            vectorProductAnswer=new MatrixParameter[LFM.getLoadings().getRowDimension()];
  //            for (int i = 0; i <vectorProductAnswer.length ; i++) {
  //                vectorProductAnswer[i]=new MatrixParameter(null);
  //                vectorProductAnswer[i].setDimensions(i+1, 1);
  //            }
  
  //        priorMeanVector=new MatrixParameter[LFM.getLoadings().getRowDimension()];
  //            for (int i = 0; i <priorMeanVector.length ; i++) {
  //                priorMeanVector[i]=new MatrixParameter(null, i+1, 1, this.prior.getMean()/(this.prior.getSD()*this.prior.getSD()));
  //
  //
  //            }
          priorPrecision = 1 / (this.prior.getSD() * this.prior.getSD());
          priorMeanPrecision = this.prior.getMean() * priorPrecision;
      }
  
      private void getPrecisionOfTruncated(MatrixParameter full, int newRowDimension, int row, double[][] answer) {
  
  //        MatrixParameter answer=new MatrixParameter(null);
  //        answer.setDimensions(this.getRowDimension(), Right.getRowDimension());
  //        System.out.println(answer.getRowDimension());
  //        System.out.println(answer.getColumnDimension());
  
          int p = full.getColumnDimension();
          for (int i = 0; i < newRowDimension; i++) {
              for (int j = i; j < newRowDimension; j++) {
                  double sum = 0;
                  for (int k = 0; k < p; k++)
                      sum += full.getParameterValue(i, k) * full.getParameterValue(j, k);
                  answer[i][j] = sum * LFM.getColumnPrecision().getParameterValue(row, row);
                  if (i == j) {
                      answer[i][j] =answer[i][j]*pathParameter+ priorPrecision;
                  } else {
                      answer[i][j]*=pathParameter;
                      answer[j][i] = answer[i][j];
                  }
              }
          }
      }
  
  
      private void getTruncatedMean(int newRowDimension, int dataColumn, double[][] variance, double[] midMean, double[] mean) {
  
  //        MatrixParameter answer=new MatrixParameter(null);
  //        answer.setDimensions(this.getRowDimension(), Right.getRowDimension());
  //        System.out.println(answer.getRowDimension());
  //        System.out.println(answer.getColumnDimension());
          MatrixParameter data = LFM.getScaledData();
          MatrixParameter Left = LFM.getFactors();
          int p = data.getColumnDimension();
          for (int i = 0; i < newRowDimension; i++) {
              double sum = 0;
              for (int k = 0; k < p; k++)
                  sum += Left.getParameterValue(i, k) * data.getParameterValue(dataColumn, k);
              sum = sum * LFM.getColumnPrecision().getParameterValue(dataColumn, dataColumn);
              sum += priorMeanPrecision;
              midMean[i] = sum;
          }
          for (int i = 0; i < newRowDimension; i++) {
              double sum = 0;
              for (int k = 0; k < newRowDimension; k++)
                  sum += variance[i][k] * midMean[k];
              mean[i] = sum;
          }
  
      }
  
      private void getPrecision(int i, double[][] answer) {
          int size = LFM.getFactorDimension();
          if (i < size) {
              getPrecisionOfTruncated(LFM.getFactors(), i + 1, i, answer);
          } else {
              getPrecisionOfTruncated(LFM.getFactors(), size, i, answer);
          }
      }
  
      private void getMean(int i, double[][] variance, double[] midMean, double[] mean) {
  //        Matrix factors=null;
          int size = LFM.getFactorDimension();
  //        double[] scaledDataColumn=LFM.getScaledData().getRowValues(i);
  //        Vector dataColumn=null;
  //        Vector priorVector=null;
  //        Vector temp=null;
  //        Matrix data=new Matrix(LFM.getScaledData().getParameterAsMatrix());
          if (i < size) {
              getTruncatedMean(i + 1, i, variance, midMean, mean);
  //            dataColumn=new Vector(data.toComponents()[i]);
  //            try {
  //                answer=precision.inverse().product(new Matrix(priorMeanVector[i].add(vectorProductAnswer[i]).getParameterAsMatrix()));
  //            } catch (IllegalDimension illegalDimension) {
  //                illegalDimension.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
  //            }
          } else {
              getTruncatedMean(size, i, variance, midMean, mean);
  //            dataColumn=new Vector(data.toComponents()[i]);
  //            try {
  //                answer=precision.inverse().product(new Matrix(priorMeanVector[size-1].add(vectorProductAnswer[size-1]).getParameterAsMatrix()));
  //            } catch (IllegalDimension illegalDimension) {
  //                illegalDimension.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
  //            }
          }
          for (int j = 0; j <mean.length ; j++) {//TODO implement for generic prior
              mean[j]*=pathParameter;
          }
  
      }
  
      private void copy(int i, double[] random) {
          TransposedBlockUpperTriangularMatrixParameter changing = (TransposedBlockUpperTriangularMatrixParameter) LFM.getLoadings();
          for (int j = 0; j < random.length; j++) {
              changing.setParameterValue(i, j, random[j]);
          }
      }
  
      private void drawI(int i, ListIterator<double[][]> currentPrecision, ListIterator<double[]> currentMidMean, ListIterator<double[]> currentMean) {
          double[] draws = null;
          double[][] precision = null;
          double[][] variance;
          double[] midMean = null;
          double[] mean = null;
          double[][] cholesky = null;
          if (currentPrecision.hasNext()) {
              precision = currentPrecision.next();
          }
          else
              precision = currentPrecision.previous();
  
          if (currentMidMean.hasNext()) {
              midMean = currentMidMean.next();
          }
          else
              midMean = currentMidMean.previous();
  