float[][][] backwardMatrix() {
   int[][] matrix = new int[this.height][this.width];
   PolygonFillerTest.fillInMatrix(
       matrix,
       PolygonFillerTest.convertNewEdgeListToOldEdgeList(
           PolygonFiller.cloneEdgeList(
               PolygonFillerTest.convertOldEdgeListToNewEdgeList(this.eT))),
       1,
       0);
   matrix = (int[][]) Array.transpose2DMatrix().fn(matrix);
   matrix = (int[][]) Array.reverseXAxisOf2DMatrix().fn(matrix);
   matrix = (int[][]) Array.reverseYAxisOf2DMatrix().fn(matrix);
   final float[] eS = this.endStates.clone();
   Array.reverseArray(eS, 0, eS.length);
   final int[] rLTL2 = new int[1000];
   final int[] lLTL2 = new int[1000];
   PolygonFiller.reverseLessThanCoordinates(
       MatrixIteratorTest.convertLTPoints(this.rLTL), rLTL2, this.width - 1, this.height - 1);
   PolygonFiller.reverseLessThanCoordinates(
       MatrixIteratorTest.convertLTPoints(this.lLTL), lLTL2, this.width - 1, this.height - 1);
   final float[][][] matrixB =
       MatrixIteratorTest.computeMatrix(
           matrix,
           new Cell.CellCalculator() {
             /* (non-Javadoc)
              * @see bp.pecan.dpc.Cell.CellCalculator#calc(float[], int, int)
              */
             public void calc(float[] cells, int offset, int x, int y) {
               ForwardBackwardMatrixIterTest.this.setCellsBackwardsLL.calc(
                   cells,
                   offset,
                   ForwardBackwardMatrixIterTest.this.width - 1 - x,
                   ForwardBackwardMatrixIterTest.this.height - 1 - y);
             }
           },
           this.stateNumber,
           eS,
           Float.NEGATIVE_INFINITY,
           rLTL2,
           lLTL2);
   final float[][][] matrixB2 = new float[matrixB.length][matrixB[0].length][this.stateNumber];
   for (int i = 0; i < matrixB.length; i++) {
     for (int j = 0; j < matrixB[i].length; j++) {
       for (int k = 0; k < matrixB[i][j].length; k++) {
         matrixB2[matrixB.length - 1 - i][matrixB[i].length - 1 - j][this.stateNumber - 1 - k] =
             matrixB[i][j][k];
       }
     }
   }
   return matrixB2;
 }
 float[][][] forwardMatrix() {
   int[][] matrix = new int[this.height][this.width];
   PolygonFillerTest.fillInMatrix(
       matrix,
       PolygonFillerTest.convertNewEdgeListToOldEdgeList(
           PolygonFiller.cloneEdgeList(
               PolygonFillerTest.convertOldEdgeListToNewEdgeList(this.eT))),
       1,
       0);
   matrix = (int[][]) Array.transpose2DMatrix().fn(matrix);
   return MatrixIteratorTest.computeMatrix(
       matrix,
       this.setCellsForwardsLL,
       this.stateNumber,
       this.startStates.clone(),
       Float.NEGATIVE_INFINITY,
       MatrixIteratorTest.convertLTPoints(this.lLTL),
       MatrixIteratorTest.convertLTPoints(this.rLTL));
 }
 public void testAddTogetherDiagonals() throws Exception {
   for (int trial = 0; trial < 100; trial++) {
     Debug.pl(" trial " + trial);
     this.setup(0);
     final float[][][] fM = this.forwardMatrix();
     final float[][][] bM = this.backwardMatrix();
     final float[][][] pM = this.sumForwardBackwardMatrices(fM, bM);
     int fD = this.r.nextInt(this.height + this.width - 2 - this.minMaxOffset); // inclusive
     Object[] oA = (Object[]) this.polygonClipper.fn(fD);
     final int[] dC = (int[]) oA[2]; // 1];
     oA = (Object[]) this.polygonClipper.fn(this.height + this.width - 2);
     final int[] dC2 = (int[]) oA[2]; // 1];
     float total = Float.NEGATIVE_INFINITY;
     for (int i = 0; i < this.stateNumber; i++) {
       total = Maths.logAdd(total, pM[pM.length - 1][pM[0].length - 1][i]);
     }
     float totalS = Float.NEGATIVE_INFINITY;
     for (int i = 0; i < this.stateNumber; i++) {
       totalS = Maths.logAdd(totalS, pM[0][0][i]);
     }
     Assert.assertEquals(total, totalS, 0.1);
     final float[] forwardDiag = this.getDiagonal(dC[6], dC[7], dC[4], dC[5], fM);
     final float[] backwardDiag =
         this.getBackwardDiagonal(dC2[0], dC2[1], dC2[2], dC2[3], this.width, this.height, bM);
     final int diagLength = (dC2[2] - dC2[0] + 1) * 2 + 1;
     int forwardDiagStartOffset, forwardDiagEndOffset;
     float[] iA;
     if (dC[6] + dC[7] + 2 == dC2[0] + dC2[1]) {
       iA = new float[this.stateNumber];
       System.arraycopy(forwardDiag, this.stateNumber, iA, 0, this.stateNumber);
       forwardDiagStartOffset = 1;
       forwardDiagEndOffset = 1;
     } else {
       forwardDiagStartOffset = (dC[6] - dC[7] - 1) - (dC2[0] - dC2[1] - 1);
       forwardDiagEndOffset = (dC[4] - dC[5] + 1) - (dC2[0] - dC2[1] - 1);
       iA = forwardDiag;
     }
     final int[] lLTA = MatrixIteratorTest.convertLTPoints(this.lLTL);
     final int[] rLTA = MatrixIteratorTest.convertLTPoints(this.rLTL);
     final int x0 = dC[6];
     final int y0 = dC[5];
     final int fDiagC = dC[4] - x0;
     fD = x0 + y0 + fDiagC;
     final boolean isOnForwardLineL =
         ForwardBackwardMatrixIterTest.isOnTheLine(lLTA, fD + 1, Integer.MAX_VALUE);
     final boolean isOnBackwardLineL =
         ForwardBackwardMatrixIterTest.isOnTheLine(lLTA, fD + 2, Integer.MAX_VALUE);
     final boolean isOnForwardLineR =
         ForwardBackwardMatrixIterTest.isOnTheLine(rLTA, fD + 1, Integer.MAX_VALUE);
     final boolean isOnBackwardLineR =
         ForwardBackwardMatrixIterTest.isOnTheLine(rLTA, fD + 2, Integer.MAX_VALUE);
     Assert.assertEquals(
         ForwardBackwardMatrixIter.addTogetherDiagonals(
             iA,
             backwardDiag,
             diagLength,
             forwardDiagStartOffset,
             forwardDiagEndOffset,
             dC2[0],
             dC2[1] + 1,
             this.setCellsForwardsLL,
             this.stateNumber,
             isOnForwardLineL,
             isOnBackwardLineL,
             isOnForwardLineR,
             isOnBackwardLineR),
         total,
         0.1);
   }
 }
  protected void setup(final int minWidth) throws Exception {
    super.setUp();
    this.r = new Random();
    this.minMaxOffset = 1 + (int) (Math.random() * 5);
    this.height = 2 * this.minMaxOffset + (int) (Math.random() * 300);
    this.width = 2 * this.minMaxOffset + (int) (Math.random() * 300);
    this.stateNumber = 3;
    this.d1 = MatrixIteratorTest.getRandomSeq(this.width + 1, 4);
    this.d2 = MatrixIteratorTest.getRandomSeq(this.height + 1, 4);
    final Object[] oA =
        ForwardBackwardMatrixIterTest.getStateMachine_Float(
            ForwardBackwardMatrixIterTest.getD(this.d1),
            ForwardBackwardMatrixIterTest.getD(this.d2),
            "bp/pecan/asymmetric.hmm",
            1001);

    this.setCellsForwardsLL = (Cell.CellCalculator) oA[0];
    this.setCellsBackwardsLL = (Cell.CellCalculator) oA[1];
    this.setCellsForwardsL = (Cell.CellCalculator) oA[2];
    this.setCellsForwardsR = (Cell.CellCalculator) oA[3];
    this.setCellsBackwardsL = (Cell.CellCalculator) oA[4];
    this.setCellsBackwardsR = (Cell.CellCalculator) oA[5];

    final List[] poly =
        PolygonFillerTest.getRandomPolygon(this.width, this.height, this.minMaxOffset, minWidth);
    this.lREL = poly[0];
    this.rREL = poly[1];
    // lLTL =
    // MatrixIteratorTest.getRandomLTPoints(PolygonFillerTest.convertOldEdgeListToNewEdgeList(lREL));
    // rLTL =
    // MatrixIteratorTest.getRandomLTPoints(PolygonFillerTest.convertOldEdgeListToNewEdgeList(rREL));

    this.eT =
        PolygonFillerTest.convertNewEdgeListToOldEdgeList(
            (List)
                IterationTools.append(
                    PolygonFiller.combineEdgeLists(
                        PolygonFiller.cloneEdgeList(
                                PolygonFillerTest.convertOldEdgeListToNewEdgeList(this.lREL))
                            .iterator(),
                        PolygonFiller.cloneEdgeList(
                                PolygonFillerTest.convertOldEdgeListToNewEdgeList(this.rREL))
                            .iterator()),
                    new ArrayList()));

    int[][] matrix = new int[this.height][this.width];
    PolygonFillerTest.fillInMatrix(
        matrix,
        PolygonFillerTest.convertNewEdgeListToOldEdgeList(
            PolygonFiller.cloneEdgeList(
                PolygonFillerTest.convertOldEdgeListToNewEdgeList(this.eT))),
        1,
        0);
    matrix = (int[][]) Array.transpose2DMatrix().fn(matrix);

    this.lLTL = MatrixIteratorTest.getRandomLTPPointsL(matrix);
    this.rLTL = MatrixIteratorTest.getRandomLTPPointsR(matrix);

    this.mI = new MatrixIterator(this.stateNumber, 1000);
    this.polygonClipper =
        PolygonFiller.clipPolygons(
            Generators.iteratorGenerator(
                PolygonFiller.cloneEdgeList(
                        PolygonFillerTest.convertOldEdgeListToNewEdgeList(this.lREL))
                    .iterator()),
            Generators.iteratorGenerator(
                PolygonFiller.cloneEdgeList(
                        PolygonFillerTest.convertOldEdgeListToNewEdgeList(this.rREL))
                    .iterator()),
            this.width,
            this.height);
    this.startStates =
        new float[] {
          (float) Math.log(1.0 / 3), (float) Math.log(1.0 / 3), (float) Math.log(1.0 / 3)
        };
    this.endStates =
        new float[] {
          (float) Math.log(1.0 / 3), (float) Math.log(1.0 / 3), (float) Math.log(1.0 / 3)
        };
  }