gt:         for(Double matrixValue : matrixValues) {
context: /*
   * DiscreteRatePriorGenerator.java
   *
   * Copyright (c) 2002-2015 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.app.phylogeography.tools;
  
  
  import dr.app.tools.TimeSlicer;
  import dr.app.util.Arguments;
  import dr.geo.math.SphericalPolarCoordinates;
  import dr.stats.DiscreteStatistics;
  import org.jdom.Element;
  import org.jdom.output.Format;
  import org.jdom.output.XMLOutputter;
  
  import java.io.*;
  import java.util.ArrayList;
  import java.util.List;
  import java.util.StringTokenizer;
  
  /**
   * @author Philippe Lemey
   * @author Andrew Rambaut
   * @author Marc A. Suchard
   */
  public class DiscreteRatePriorGenerator {
  
      public static final String HELP = "help";
      public static final String COORDINATES = "coordinates";
      public static final String DENSITIES = "densities";
      public static final String GENERICS = "generics";
      public static final String FORMAT = "format";
      public static final String MODEL = "model";
  
      public DiscreteRatePriorGenerator(String[] locations, Double[] latitudes, Double[] longitudes, Double[] densities) {
  
          if (locations == null) {
              //System.out.println(locations[0]);
              System.err.println("no locations specified!");
          } else {
              this.locations = locations;
          }
  
          this.latitudes = latitudes;
          this.longitudes = longitudes;
          this.densities = densities;
  
          if ((latitudes == null)||(longitudes == null)) {
              progressStream.println("no latitudes or longitudes specified!");
          } else {
              distances = getUpperTriangleDistanceMatrix(latitudes,longitudes);
          }
  
          if (densities != null) {
              densityDonorMatrix = getDensityMatrix(densities, true);
              densityRecipientMatrix = getDensityMatrix(densities, false);
          }
  
      }
      // for the time being, locations, latitudes and longitudes are not required
      private String[] locations;
      private Double[] latitudes;
      private Double[] longitudes;
      private final Double[] densities;
      private double[] distances;
      private double[] densityDonorMatrix;
      private double[] densityRecipientMatrix;
  
      private double[] getUpperTriangleDistanceMatrix(Double[] latitudes, Double[] longitudes) {
  
          double[] distances = new double[(latitudes.length * (latitudes.length - 1))/2];
  
          int distanceCounter = 0;
          int pairwiseCounter1 = 0;
          for (int c = 0; c < latitudes.length; c++) {
              pairwiseCounter1 ++;
              for (int d = pairwiseCounter1; d < latitudes.length; d++) {
                  distances[distanceCounter] = getKilometerGreatCircleDistance(latitudes[c],longitudes[c],latitudes[d],longitudes[d]);
                  distanceCounter++;
              }
          }
          return distances;
      }
  
      private double[] getFullDistanceMatrix(Double[] latitudes, Double[] longitudes) {
  
          double[] distances = new double[latitudes.length * latitudes.length];
  
          int distanceCounter = 0;
          for (int a = 0; a < latitudes.length; a++) {
              //resultsStream.print(locations[a]+"\t");
              for (int b = 0; b < latitudes.length; b++) {
                  distances[distanceCounter] = getKilometerGreatCircleDistance(latitudes[a],longitudes[a],latitudes[b],longitudes[b]);
                  distanceCounter++;
              }
          }
          return distances;
      }
  
      private double[] getFullCoordDiffMatrix(Double[] coordinates, boolean positive, boolean negative) {
  
          double[] differences = new double[coordinates.length * coordinates.length];
  
          int differenceCounter = 0;
          for (int a = 0; a < coordinates.length; a++) {
              for (int b = 0; b < coordinates.length; b++) {
                  double difference = coordinates[b]-coordinates[a];
                  if (difference > 0 && positive) {
                      differences[differenceCounter] = difference;
                  }  else if (difference < 0 && negative) {
                      differences[differenceCounter] = difference;
                  } else {
                      differences[differenceCounter] = 0;
                  }
                  differenceCounter++;
              }
          }
          return differences;
      }
  
      private static double getKilometerGreatCircleDistance(double lat1, double long1, double lat2, double long2) {
           SphericalPolarCoordinates coord1 = new SphericalPolarCoordinates(lat1, long1);
           SphericalPolarCoordinates coord2 = new SphericalPolarCoordinates(lat2, long2);
           return (coord1.distance(coord2));
      }
  
      private double[] getDensityMatrix(Double[] densities, boolean donor) {
  
          double[] returnMatrix = new double[densities.length * (densities.length - 1)];
          int distanceCounter = 0;
          int matrixEntry;
          for (int c = 0; c < densities.length; c++) {
              for (int d = 0; d < densities.length; d++) {
                  if (c == d) {
                      continue;
                  }                
                  if (donor) {
                      matrixEntry = c;
                  } else {
                      matrixEntry = d;
                  }
                  returnMatrix[distanceCounter] = densities[matrixEntry];
                  distanceCounter++;
              }
          }
          return returnMatrix;
      }
  
      private void printLocations(String[] locs, boolean upper) {
  
          int pairwiseCounter1 = 0;
          for (int c = 0; c < locs.length; c++) {
              pairwiseCounter1 ++;
              for (int d = pairwiseCounter1; d < locs.length; d++) {
                  if (upper) {
                      System.out.println(locs[c]+"\t"+locs[d]);                    
                  }  else {
                      System.out.println(locs[d]+"\t"+locs[c]);
                  }
              }
          }
      }
  
      private void printLocationsDensitiesDistances (String[] locs, boolean upper) {
  
          double[] firstDensity = getSingleElementFromFullMatrix(densities,false);
          double[] secondDensity = getSingleElementFromFullMatrix(densities,true);
  
          System.out.println("location1\tlocation2\tdistance\tdensity1\tdensity2");
          int pairwiseCounter1 = 0;
          int arrayCounter = 0;
          for (int c = 0; c < locs.length; c++) {
              pairwiseCounter1 ++;
              for (int d = pairwiseCounter1; d < locs.length; d++) {
                  if (upper) {
                      System.out.println(locs[c]+"\t"+locs[d]+"\t"+distances[arrayCounter]+"\t"+firstDensity[arrayCounter]+"\t"+secondDensity[arrayCounter]);
                      arrayCounter ++;
                  }  else {
                      System.out.println(locs[d]+"\t"+locs[c]+"\t"+distances[arrayCounter]+"\t"+firstDensity[(firstDensity.length/2)+arrayCounter]+"\t"+secondDensity[(secondDensity.length/2)+arrayCounter]);
                      arrayCounter ++;
                      }
              }
          }
      }
  
      private void printFullDistanceMatrix(String name, boolean locationNames) {
          try {
              PrintWriter outFile = new PrintWriter(new FileWriter(name), true);
  
              outFile.print("location");
              for (int a = 0; a < locations.length; a++) {
                  outFile.print(locations[a]+"\t");
                  for (int b = 0; b < locations.length; b++) {
                      double lat1 = latitudes[a];
                      double lat2 = latitudes[b];
                      double long1 = longitudes[a];
                      double long2 = longitudes[b];
                      double distance = getKilometerGreatCircleDistance(lat1,long1,lat2,long2);
                      outFile.print(distance+"\t");
                  }
                  outFile.print("\r");
              }
              outFile.close();
  
          } catch(IOException io) {
             System.err.print("Error writing to file: " + name);
          }
  
      }
  
      enum OutputFormat {
          TAB,
          SPACE,
          XML
      }
  
      enum Model {
          PRIOR,
          GLM,
          JUMP
      }
  
      public void output(String outputFileName, OutputFormat outputFormat, Model model) {
  
          //printLocations(locations,false);
          //printLocationsDensitiesDistances(locations,true);
          //printLocationsDensitiesDistances(locations,false);
          //printFullDistanceMatrix("test.txt", false);
          resultsStream = System.out;
  
          if (outputFileName != null) {
              try {
              resultsStream = new PrintStream(new File(outputFileName));
              } catch (IOException e) {
                  System.err.println("Error opening file: "+outputFileName);
                  System.exit(1);
              }
          }
  
          if (model == model.PRIOR) {
  
              int predictor = 0;
  
              if (distances != null) {
                  outputStringLine("reversible priors: distances",outputFormat);
                  resultsStream.print("\r");
                  outputArray(distances, outputFormat, model, predictor, false);
                  resultsStream.print("\r");
                  outputStringLine("reversible priors: normalized inverse distances",outputFormat);
                  resultsStream.print("\r");
                  outputArray(transform(distances,true, true, false, false), outputFormat, model, predictor, false);
                  resultsStream.print("\r");
                  outputStringLine("reversible priors: normalized inverse log distances",outputFormat);
                  resultsStream.print("\r");
                  outputArray(transform(distances,true, true, false, true), outputFormat, model, predictor, false);
                  resultsStream.print("\r");
              }
              if (densities != null) {
                  outputStringLine("reversible priors: densities",outputFormat);
                  resultsStream.print("\r");
                  outputArray(transform(getUpperTrianglePairwiseProductMatrix(densities),false,false,false,false), outputFormat, model, predictor, false);
                  resultsStream.print("\r");
                  outputStringLine("reversible priors: normalized densities",outputFormat);
                  resultsStream.print("\r");
                  outputArray(transform(getUpperTrianglePairwiseProductMatrix(densities),false,true,false,false), outputFormat, model, predictor, false);
                  resultsStream.print("\r");
                  outputStringLine("reversible priors: normalized log densities",outputFormat);
                  resultsStream.print("\r");
                  outputArray(transform(getUpperTrianglePairwiseProductMatrix(densities),false,true,false,true), outputFormat, model, predictor, false);
                  resultsStream.print("\r");
  
                  if (distances != null) {
                      outputStringLine("reversible priors: product of normalized densities divided by normalized distances",outputFormat);
                      resultsStream.print("\r");
                      outputArray(productOfArrays(transform(getUpperTrianglePairwiseProductMatrix(densities),false,true,false,false),transform(distances,false, true,false,false),true), outputFormat, model, predictor, false);
                      resultsStream.print("\r");
                      outputStringLine("reversible priors: normalized product of densities divided by distances",outputFormat);
                      resultsStream.print("\r");
                      outputArray(transform(productOfArrays(getUpperTrianglePairwiseProductMatrix(densities),distances, true),false,true,false,false), outputFormat, model, predictor, false);
                      resultsStream.print("\r");
                      outputStringLine("reversible priors: normalized log product of densities divided by distances",outputFormat);
                      resultsStream.print("\r");
                      outputArray(transform(productOfArrays(getUpperTrianglePairwiseProductMatrix(densities),distances, true),false,true,false,true), outputFormat, model, predictor, false);
                      resultsStream.print("\r");
                  }
  
              }
              if (distances != null) {
                  outputStringLine("nonreversible priors: distances",outputFormat);
                  resultsStream.print("\r");
                  outputArray(distances, outputFormat, model, predictor, true);
                  resultsStream.print("\r");
                  outputStringLine("nonreversible priors: normalized inverse distances",outputFormat);
                  resultsStream.print("\r");
                  outputArray(transform(distances,true, true, false, false), outputFormat, model, predictor, true);
                  resultsStream.print("\r");
                  outputStringLine("nonreversible priors: normalized inverse log distances",outputFormat);
                  resultsStream.print("\r");
                  outputArray(transform(distances,true, true, false, true), outputFormat, model,predictor, true);
                  resultsStream.print("\r");
              }
              if (densities != null) {
                  outputStringLine("nonreversible priors: densities",outputFormat);
                  resultsStream.print("\r");
                  outputArray(transform(getUpperTrianglePairwiseProductMatrix(densities),false,false,false,false), outputFormat, model, predictor, true);
                  resultsStream.print("\r");
                  outputStringLine("nonreversible priors: normalized densities",outputFormat);
                  resultsStream.print("\r");
                  outputArray(transform(getUpperTrianglePairwiseProductMatrix(densities),false,true,false,false), outputFormat, model, predictor, true);
                  resultsStream.print("\r");
                  outputStringLine("nonreversible priors: normalized log densities",outputFormat);
                  resultsStream.print("\r");
                  outputArray(transform(getUpperTrianglePairwiseProductMatrix(densities),false,true,false,true), outputFormat, model, predictor, true);
                  resultsStream.print("\r");
  
                  if (distances != null) {
                      outputStringLine("nonreversible priors: product of normalized densities divided by normalized distances",outputFormat);
                      resultsStream.print("\r");
                      outputArray(productOfArrays(transform(getUpperTrianglePairwiseProductMatrix(densities),false,true,false,false),transform(distances,false, true, false, false),true), outputFormat, model, predictor, true);
                      resultsStream.print("\r");
                      outputStringLine("nonreversible priors: normalized product of densities divided by distances",outputFormat);
                      resultsStream.print("\r");
                      outputArray(transform(productOfArrays(getUpperTrianglePairwiseProductMatrix(densities),distances, true),false,true,false,false), outputFormat, model, predictor, true);
                      resultsStream.print("\r");
                      outputStringLine("nonreversible priors: normalized log product of densities divided by distances",outputFormat);
                      resultsStream.print("\r");
                      outputArray(transform(productOfArrays(getUpperTrianglePairwiseProductMatrix(densities),distances, true),false,true,false,true), outputFormat, model, predictor, true);
                      resultsStream.print("\r");
                  }
  
              }
          } else if (model == model.GLM) {
  
              int predictor = 1;
  
              //TODO: fully implement glm output
              if (distances != null) {
                  //printLocations(locations, true);
                  //printLocations(locations, false);
                  outputStringLine("predictor: distances",outputFormat);
                  resultsStream.print("\r");
                  outputArray(transform(distances,false, false, true, false), outputFormat, model, predictor, true);
                  predictor++;
                  outputStringLine("predictor: standardized log distances",outputFormat);
                  resultsStream.print("\r");
                  outputArray(transform(distances,false, false, true, true), outputFormat, model, predictor, true);
              }
              if (densities != null) {
                  predictor++;
                  outputStringLine("predictor: standardized donor densities",outputFormat);
                  resultsStream.print("\r");
                  outputArray(transform(getSingleElementFromFullMatrix(densities, false),false,false,true,true), outputFormat, model, predictor, false);
                  predictor++;
                  outputStringLine("predictor: standardized recipient densities",outputFormat);
                  resultsStream.print("\r");
                  outputArray(transform(getSingleElementFromFullMatrix(densities, true),false,false,true,true), outputFormat, model, predictor, false);
  
    // products not necessary, and shouldn't be normalized but standardized, also log
    //              outputStringLine("predictor: normalized product of densities divided by distances",outputFormat);
    //              resultsStream.print("\r");
    //              outputArray(transform(productOfArrays(getUpperTrianglePairwiseProductMatrix(densities),distances, true),false,true,false,false), outputFormat, predictor, true);
    //              resultsStream.print("\r");
    //              predictor++;
    //              outputStringLine("predictor: normalized log product of densities divided by distances",outputFormat);
    //              resultsStream.print("\r");
    //              outputArray(transform(productOfArrays(getUpperTrianglePairwiseProductMatrix(densities),distances, true),false,true,false,true), outputFormat, predictor, true);
    //              resultsStream.print("\r");
              }
  
  
          } else if (model == model.JUMP) {
  
              int predictor = 0;
  
              outputStringLine("great circle distance jump matrix",outputFormat);
              resultsStream.print("\r");
              outputArray(transform(getFullDistanceMatrix(latitudes, longitudes),false,false,false,false), outputFormat, model, predictor, false);
              resultsStream.print("\r");
              predictor ++;
  
              outputStringLine("latitude jump matrix",outputFormat);
              resultsStream.print("\r");
              outputArray(transform(getFullCoordDiffMatrix(latitudes, true, true),false,false,false,false), outputFormat, model, predictor, false);
              resultsStream.print("\r");
              predictor ++;
  
              outputStringLine("longitude jump matrix",outputFormat);
              resultsStream.print("\r");
              outputArray(transform(getFullCoordDiffMatrix(longitudes, true, true),false,false,false,false), outputFormat, model, predictor, false);
              resultsStream.print("\r");
              predictor ++;
  
              outputStringLine("westward jump matrix",outputFormat);
              resultsStream.print("\r");
              outputArray(transform(getFullCoordDiffMatrix(longitudes, false, true),false,false,false,false), outputFormat, model, predictor, false);
              resultsStream.print("\r");
              predictor ++;
  
              outputStringLine("eastward jump matrix",outputFormat);
              resultsStream.print("\r");
              outputArray(transform(getFullCoordDiffMatrix(longitudes, true, false),false,false,false,false), outputFormat, model, predictor, false);
              resultsStream.print("\r");
              predictor ++;
  
              outputStringLine("northward jump matrix",outputFormat);
              resultsStream.print("\r");
              outputArray(transform(getFullCoordDiffMatrix(latitudes, true, false),false,false,false,false), outputFormat, model, predictor, false);
              resultsStream.print("\r");
              predictor ++;
  
              outputStringLine("southward jump matrix",outputFormat);
              resultsStream.print("\r");
              outputArray(transform(getFullCoordDiffMatrix(latitudes, false, true),false,false,false,false), outputFormat, model, predictor, false);
              resultsStream.print("\r");
              predictor ++;
  
  //            outputStringLine("latitude reward parameter",outputFormat);
  //            resultsStream.print("\r");
  //            outputArray(transform(objectToPrimitiveArray(latitudes),false,false,false,false), outputFormat, model, predictor, false);
  //            resultsStream.print("\r");
  //            predictor ++;
  
  //            outputStringLine("longitude reward parameter",outputFormat);
  //            resultsStream.print("\r");
  //            outputArray(transform(objectToPrimitiveArray(longitudes),false,false,false,false), outputFormat, model, predictor, false);
  //            resultsStream.print("\r");
  //            predictor ++;
  
              for (int i = 0; i < locations.length; i++) {
  
                  double[] locationReward = getLocationReward(i,locations.length);
                  outputStringLine(locations[i]+" reward parameter",outputFormat);
                  resultsStream.print("\r");
                  outputArray(transform(locationReward,false,false,false,false), outputFormat, model, predictor, false);
                  resultsStream.print("\r");
                  predictor ++;
  
              }
  
          }
      }
  
      private double[] getUpperTrianglePairwiseProductMatrix(Double[] matrixValues) {
  
          double[] pairwiseProducts = new double[(matrixValues.length * (matrixValues.length - 1))/2];
  
          int counter = 0;
          int pairwiseCounter1 = 0;
  