Java Code Examples for org.apache.commons.math.util.MathUtils#SAFE_MIN

The following examples show how to use org.apache.commons.math.util.MathUtils#SAFE_MIN . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: EigenDecompositionImplTest.java    From astor with GNU General Public License v2.0 6 votes vote down vote up
/** test a matrix already in tridiagonal form. */
@Test
public void testTridiagonal() {
    Random r = new Random(4366663527842l);
    double[] ref = new double[30];
    for (int i = 0; i < ref.length; ++i) {
        if (i < 5) {
            ref[i] = 2 * r.nextDouble() - 1;
        } else {
            ref[i] = 0.0001 * r.nextDouble() + 6;
        }
    }
    Arrays.sort(ref);
    TriDiagonalTransformer t =
        new TriDiagonalTransformer(createTestMatrix(r, ref));
    EigenDecomposition ed =
        new EigenDecompositionImpl(t.getMainDiagonalRef(),
                                   t.getSecondaryDiagonalRef(),
                                   MathUtils.SAFE_MIN);
    double[] eigenValues = ed.getRealEigenvalues();
    Assert.assertEquals(ref.length, eigenValues.length);
    for (int i = 0; i < ref.length; ++i) {
        Assert.assertEquals(ref[ref.length - i - 1], eigenValues[i], 2.0e-14);
    }

}
 
Example 2
Source File: EigenDecompositionImplTest.java    From astor with GNU General Public License v2.0 6 votes vote down vote up
/** test eigenvalues for a big matrix. */
public void testBigMatrix() {
    Random r = new Random(17748333525117l);
    double[] bigValues = new double[200];
    for (int i = 0; i < bigValues.length; ++i) {
        bigValues[i] = 2 * r.nextDouble() - 1;
    }
    Arrays.sort(bigValues);
    EigenDecomposition ed =
        new EigenDecompositionImpl(createTestMatrix(r, bigValues), MathUtils.SAFE_MIN);
    double[] eigenValues = ed.getRealEigenvalues();
    assertEquals(bigValues.length, eigenValues.length);
    for (int i = 0; i < bigValues.length; ++i) {
        assertEquals(bigValues[bigValues.length - i - 1], eigenValues[i], 2.0e-14);
    }
}
 
Example 3
Source File: EigenDecompositionImplTest.java    From astor with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Verifies operation on indefinite matrix
 */
public void testZeroDivide() {
    RealMatrix indefinite = MatrixUtils.createRealMatrix(new double [][] {
            { 0.0, 1.0, -1.0 },
            { 1.0, 1.0, 0.0 },
            { -1.0,0.0, 1.0 }
    });
    EigenDecomposition ed = new EigenDecompositionImpl(indefinite, MathUtils.SAFE_MIN);
    checkEigenValues((new double[] {2, 1, -1}), ed, 1E-12);
    double isqrt3 = 1/Math.sqrt(3.0);
    checkEigenVector((new double[] {isqrt3,isqrt3,-isqrt3}), ed, 1E-12);
    double isqrt2 = 1/Math.sqrt(2.0);
    checkEigenVector((new double[] {0.0,-isqrt2,-isqrt2}), ed, 1E-12);
    double isqrt6 = 1/Math.sqrt(6.0);
    checkEigenVector((new double[] {2*isqrt6,-isqrt6,isqrt6}), ed, 1E-12);
}
 
Example 4
Source File: EigenDecompositionImplTest.java    From astor with GNU General Public License v2.0 6 votes vote down vote up
/** test eigenvalues for a big matrix. */
public void testBigMatrix() {
    Random r = new Random(17748333525117l);
    double[] bigValues = new double[200];
    for (int i = 0; i < bigValues.length; ++i) {
        bigValues[i] = 2 * r.nextDouble() - 1;
    }
    Arrays.sort(bigValues);
    EigenDecomposition ed =
        new EigenDecompositionImpl(createTestMatrix(r, bigValues), MathUtils.SAFE_MIN);
    double[] eigenValues = ed.getRealEigenvalues();
    assertEquals(bigValues.length, eigenValues.length);
    for (int i = 0; i < bigValues.length; ++i) {
        assertEquals(bigValues[bigValues.length - i - 1], eigenValues[i], 2.0e-14);
    }
}
 
Example 5
Source File: EigenDecompositionImplTest.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
/** test dimensions */
public void testDimensions() {
    final int m = matrix.getRowDimension();
    EigenDecomposition ed = new EigenDecompositionImpl(matrix, MathUtils.SAFE_MIN);
    assertEquals(m, ed.getV().getRowDimension());
    assertEquals(m, ed.getV().getColumnDimension());
    assertEquals(m, ed.getD().getColumnDimension());
    assertEquals(m, ed.getD().getColumnDimension());
    assertEquals(m, ed.getVT().getRowDimension());
    assertEquals(m, ed.getVT().getColumnDimension());
}
 
Example 6
Source File: EigenDecompositionImplTest.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
/** test eigenvalues */
public void testEigenvalues() {
    EigenDecomposition ed = new EigenDecompositionImpl(matrix, MathUtils.SAFE_MIN);
    double[] eigenValues = ed.getRealEigenvalues();
    assertEquals(refValues.length, eigenValues.length);
    for (int i = 0; i < refValues.length; ++i) {
        assertEquals(refValues[i], eigenValues[i], 3.0e-15);
    }
}
 
Example 7
Source File: EigenDecompositionImplTest.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
public void testDimension3() {
    RealMatrix matrix =
        MatrixUtils.createRealMatrix(new double[][] {
                               {  39632.0, -4824.0, -16560.0 },
                               {  -4824.0,  8693.0,   7920.0 },
                               { -16560.0,  7920.0,  17300.0 }
                           });
    EigenDecomposition ed = new EigenDecompositionImpl(matrix, MathUtils.SAFE_MIN);
    assertEquals(50000.0, ed.getRealEigenvalue(0), 3.0e-11);
    assertEquals(12500.0, ed.getRealEigenvalue(1), 3.0e-11);
    assertEquals( 3125.0, ed.getRealEigenvalue(2), 3.0e-11);
}
 
Example 8
Source File: EigenDecompositionImplTest.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
@Test
public void testDimension4WithoutSplit() {
    RealMatrix matrix =
        MatrixUtils.createRealMatrix(new double[][] {
                               {  0.5608, -0.2016,  0.1152, -0.2976 },
                               { -0.2016,  0.4432, -0.2304,  0.1152 },
                               {  0.1152, -0.2304,  0.3088, -0.1344 },
                               { -0.2976,  0.1152, -0.1344,  0.3872 }
                           });
    EigenDecomposition ed = new EigenDecompositionImpl(matrix, MathUtils.SAFE_MIN);
    Assert.assertEquals(1.0, ed.getRealEigenvalue(0), 1.0e-15);
    Assert.assertEquals(0.4, ed.getRealEigenvalue(1), 1.0e-15);
    Assert.assertEquals(0.2, ed.getRealEigenvalue(2), 1.0e-15);
    Assert.assertEquals(0.1, ed.getRealEigenvalue(3), 1.0e-15);
}
 
Example 9
Source File: EigenDecompositionImplTest.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
@Test
public void testDimension1() {
    RealMatrix matrix =
        MatrixUtils.createRealMatrix(new double[][] { { 1.5 } });
    EigenDecomposition ed = new EigenDecompositionImpl(matrix, MathUtils.SAFE_MIN);
    Assert.assertEquals(1.5, ed.getRealEigenvalue(0), 1.0e-15);
}
 
Example 10
Source File: EigenDecompositionImplTest.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Matrix with eigenvalues {2, 0, 12}
 */
@Test
public void testDistinctEigenvalues() {
    RealMatrix distinct = MatrixUtils.createRealMatrix(new double[][] {
            {3, 1, -4},
            {1, 3, -4},
            {-4, -4, 8}
    });
    EigenDecomposition ed = new EigenDecompositionImpl(distinct, MathUtils.SAFE_MIN);
    checkEigenValues((new double[] {2, 0, 12}), ed, 1E-12);
    checkEigenVector((new double[] {1, -1, 0}), ed, 1E-12);
    checkEigenVector((new double[] {1, 1, 1}), ed, 1E-12);
    checkEigenVector((new double[] {-1, -1, 2}), ed, 1E-12);
}
 
Example 11
Source File: EigenDecompositionImplTest.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Matrix with eigenvalues {2, 0, 12}
 */
public void testDistinctEigenvalues() {
    RealMatrix distinct = MatrixUtils.createRealMatrix(new double[][] {
            {3, 1, -4},  
            {1, 3, -4}, 
            {-4, -4, 8}
    });
    EigenDecomposition ed = new EigenDecompositionImpl(distinct, MathUtils.SAFE_MIN);
    checkEigenValues((new double[] {2, 0, 12}), ed, 1E-12);
    checkEigenVector((new double[] {1, -1, 0}), ed, 1E-12);
    checkEigenVector((new double[] {1, 1, 1}), ed, 1E-12);
    checkEigenVector((new double[] {-1, -1, 2}), ed, 1E-12);
}
 
Example 12
Source File: EigenDecompositionImplTest.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
/** test dimensions */
@Test
public void testDimensions() {
    final int m = matrix.getRowDimension();
    EigenDecomposition ed = new EigenDecompositionImpl(matrix, MathUtils.SAFE_MIN);
    Assert.assertEquals(m, ed.getV().getRowDimension());
    Assert.assertEquals(m, ed.getV().getColumnDimension());
    Assert.assertEquals(m, ed.getD().getColumnDimension());
    Assert.assertEquals(m, ed.getD().getColumnDimension());
    Assert.assertEquals(m, ed.getVT().getRowDimension());
    Assert.assertEquals(m, ed.getVT().getColumnDimension());
}
 
Example 13
Source File: EigenDecompositionImplTest.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
/** test dimensions */
public void testDimensions() {
    final int m = matrix.getRowDimension();
    EigenDecomposition ed = new EigenDecompositionImpl(matrix, MathUtils.SAFE_MIN);
    assertEquals(m, ed.getV().getRowDimension());
    assertEquals(m, ed.getV().getColumnDimension());
    assertEquals(m, ed.getD().getColumnDimension());
    assertEquals(m, ed.getD().getColumnDimension());
    assertEquals(m, ed.getVT().getRowDimension());
    assertEquals(m, ed.getVT().getColumnDimension());
}
 
Example 14
Source File: EigenDecompositionImplTest.java    From astor with GNU General Public License v2.0 4 votes vote down vote up
public void testMathpbx02() {

        double[] mainTridiagonal = {
              7484.860960227216, 18405.28129035345, 13855.225609560746,
             10016.708722343366, 559.8117399576674, 6750.190788301587,
                71.21428769782159
        };
        double[] secondaryTridiagonal = {
             -4175.088570476366,1975.7955858241994,5193.178422374075,
              1995.286659169179,75.34535882933804,-234.0808002076056
        };

        // the reference values have been computed using routine DSTEMR
        // from the fortran library LAPACK version 3.2.1
        double[] refEigenValues = {
                20654.744890306974412,16828.208208485466457,
                6893.155912634994820,6757.083016675340332,
                5887.799885688558788,64.309089923240379,
                57.992628792736340
        };
        RealVector[] refEigenVectors = {
                new ArrayRealVector(new double[] {-0.270356342026904, 0.852811091326997, 0.399639490702077, 0.198794657813990, 0.019739323307666, 0.000106983022327, -0.000001216636321}),
                new ArrayRealVector(new double[] {0.179995273578326,-0.402807848153042,0.701870993525734,0.555058211014888,0.068079148898236,0.000509139115227,-0.000007112235617}),
                new ArrayRealVector(new double[] {-0.399582721284727,-0.056629954519333,-0.514406488522827,0.711168164518580,0.225548081276367,0.125943999652923,-0.004321507456014}),
                new ArrayRealVector(new double[] {0.058515721572821,0.010200130057739,0.063516274916536,-0.090696087449378,-0.017148420432597,0.991318870265707,-0.034707338554096}),
                new ArrayRealVector(new double[] {0.855205995537564,0.327134656629775,-0.265382397060548,0.282690729026706,0.105736068025572,-0.009138126622039,0.000367751821196}),
                new ArrayRealVector(new double[] {-0.002913069901144,-0.005177515777101,0.041906334478672,-0.109315918416258,0.436192305456741,0.026307315639535,0.891797507436344}),
                new ArrayRealVector(new double[] {-0.005738311176435,-0.010207611670378,0.082662420517928,-0.215733886094368,0.861606487840411,-0.025478530652759,-0.451080697503958})
        };

        // the following line triggers the exception
        EigenDecomposition decomposition =
            new EigenDecompositionImpl(mainTridiagonal, secondaryTridiagonal, MathUtils.SAFE_MIN);

        double[] eigenValues = decomposition.getRealEigenvalues();
        for (int i = 0; i < refEigenValues.length; ++i) {
            assertEquals(refEigenValues[i], eigenValues[i], 1.0e-3);
            if (refEigenVectors[i].dotProduct(decomposition.getEigenvector(i)) < 0) {
                assertEquals(0, refEigenVectors[i].add(decomposition.getEigenvector(i)).getNorm(), 1.0e-5);
            } else {
                assertEquals(0, refEigenVectors[i].subtract(decomposition.getEigenvector(i)).getNorm(), 1.0e-5);
            }
        }

    }
 
Example 15
Source File: Arja_0086_s.java    From coming with MIT License 4 votes vote down vote up
/**
 * Perform two iterations with Li's tests for initial splits.
 * @param n number of rows of the matrix to process
 */
private void initialSplits(final int n) {

    pingPong = 0;
    for (int k = 0; k < 2; ++k) {

        // apply Li's reverse test
        double d = work[4 * (n - 1) + pingPong];
        for (int i = 4 * (n - 2) + pingPong; i >= 0; i -= 4) {
            if (work[i + 2] <= TOLERANCE_2 * d) {
                work[i + 2] = -0.0;
                d = work[i];
            } else {
                d *= work[i] / (d + work[i + 2]);
            }
        }

        // apply dqd plus Li's forward test.
        d = work[pingPong];
        for (int i = 2 + pingPong; i < 4 * n - 2; i += 4) {
            final int j = i - 2 * pingPong - 1;
            work[j] = d + work[i];
            if (work[i] <= TOLERANCE_2 * d) {
                work[i]     = -0.0;
                work[j]     = d;
                work[j + 2] = 0.0;
                d = work[i + 2];
            } else if ((MathUtils.SAFE_MIN * work[i + 2] < work[j]) &&
                       (MathUtils.SAFE_MIN * work[j] < work[i + 2])) {
                final double tmp = work[i + 2] / work[j];
                work[j + 2] = work[i] * tmp;
                d *= tmp;
            } else {
                work[j + 2] = work[i + 2] * (work[i] / work[j]);
                d *= work[i + 2] / work[j];
           }
        }
        work[4 * n - 3 - pingPong] = d;

        // from ping to pong
        pingPong = 1 - pingPong;

    }

}
 
Example 16
Source File: Arja_00128_s.java    From coming with MIT License 4 votes vote down vote up
/**
 * Perform two iterations with Li's tests for initial splits.
 * @param n number of rows of the matrix to process
 */
private void initialSplits(final int n) {

    pingPong = 0;
    for (int k = 0; k < 2; ++k) {

        // apply Li's reverse test
        double d = work[4 * (n - 1) + pingPong];
        for (int i = 4 * (n - 2) + pingPong; i >= 0; i -= 4) {
            if (work[i + 2] <= TOLERANCE_2 * d) {
                work[i + 2] = -0.0;
                d = work[i];
            } else {
                d *= work[i] / (d + work[i + 2]);
            }
        }

        // apply dqd plus Li's forward test.
        d = work[pingPong];
        for (int i = 2 + pingPong; i < 4 * n - 2; i += 4) {
            final int j = i - 2 * pingPong - 1;
            work[j] = d + work[i];
            if (work[i] <= TOLERANCE_2 * d) {
                work[i]     = -0.0;
                work[j]     = d;
                work[j + 2] = 0.0;
                d = work[i + 2];
            } else if ((MathUtils.SAFE_MIN * work[i + 2] < work[j]) &&
                       (MathUtils.SAFE_MIN * work[j] < work[i + 2])) {
                final double tmp = work[i + 2] / work[j];
                work[j + 2] = work[i] * tmp;
                d *= tmp;
            } else {
                work[j + 2] = work[i + 2] * (work[i] / work[j]);
                d *= work[i + 2] / work[j];
           }
        }
        work[4 * n - 3 - pingPong] = d;

        // from ping to pong
        pingPong = 1 - pingPong;

    }

}
 
Example 17
Source File: EigenDecompositionImplTest.java    From astor with GNU General Public License v2.0 4 votes vote down vote up
public void testMathpbx02() {

        double[] mainTridiagonal = {
              7484.860960227216, 18405.28129035345, 13855.225609560746,
             10016.708722343366, 559.8117399576674, 6750.190788301587,
                71.21428769782159
        };
        double[] secondaryTridiagonal = {
             -4175.088570476366,1975.7955858241994,5193.178422374075,
              1995.286659169179,75.34535882933804,-234.0808002076056
        };

        // the reference values have been computed using routine DSTEMR
        // from the fortran library LAPACK version 3.2.1
        double[] refEigenValues = {
                20654.744890306974412,16828.208208485466457,
                6893.155912634994820,6757.083016675340332,
                5887.799885688558788,64.309089923240379,
                57.992628792736340
        };
        RealVector[] refEigenVectors = {
                new ArrayRealVector(new double[] {-0.270356342026904, 0.852811091326997, 0.399639490702077, 0.198794657813990, 0.019739323307666, 0.000106983022327, -0.000001216636321}),
                new ArrayRealVector(new double[] {0.179995273578326,-0.402807848153042,0.701870993525734,0.555058211014888,0.068079148898236,0.000509139115227,-0.000007112235617}),
                new ArrayRealVector(new double[] {-0.399582721284727,-0.056629954519333,-0.514406488522827,0.711168164518580,0.225548081276367,0.125943999652923,-0.004321507456014}),
                new ArrayRealVector(new double[] {0.058515721572821,0.010200130057739,0.063516274916536,-0.090696087449378,-0.017148420432597,0.991318870265707,-0.034707338554096}),
                new ArrayRealVector(new double[] {0.855205995537564,0.327134656629775,-0.265382397060548,0.282690729026706,0.105736068025572,-0.009138126622039,0.000367751821196}),
                new ArrayRealVector(new double[] {-0.002913069901144,-0.005177515777101,0.041906334478672,-0.109315918416258,0.436192305456741,0.026307315639535,0.891797507436344}),
                new ArrayRealVector(new double[] {-0.005738311176435,-0.010207611670378,0.082662420517928,-0.215733886094368,0.861606487840411,-0.025478530652759,-0.451080697503958})
        };

        // the following line triggers the exception
        EigenDecomposition decomposition =
            new EigenDecompositionImpl(mainTridiagonal, secondaryTridiagonal, MathUtils.SAFE_MIN);

        double[] eigenValues = decomposition.getRealEigenvalues();
        for (int i = 0; i < refEigenValues.length; ++i) {
            assertEquals(refEigenValues[i], eigenValues[i], 1.0e-3);
            if (refEigenVectors[i].dotProduct(decomposition.getEigenvector(i)) < 0) {
                assertEquals(0, refEigenVectors[i].add(decomposition.getEigenvector(i)).getNorm(), 1.0e-5);
            } else {
                assertEquals(0, refEigenVectors[i].subtract(decomposition.getEigenvector(i)).getNorm(), 1.0e-5);
            }
        }

    }
 
Example 18
Source File: Cardumen_0061_s.java    From coming with MIT License 4 votes vote down vote up
/**
 * Perform two iterations with Li's tests for initial splits.
 * @param n number of rows of the matrix to process
 */
private void initialSplits(final int n) {

    pingPong = 0;
    for (int k = 0; k < 2; ++k) {

        // apply Li's reverse test
        double d = work[4 * (n - 1) + pingPong];
        for (int i = 4 * (n - 2) + pingPong; i >= 0; i -= 4) {
            if (work[i + 2] <= TOLERANCE_2 * d) {
                work[i + 2] = -0.0;
                d = work[i];
            } else {
                d *= work[i] / (d + work[i + 2]);
            }
        }

        // apply dqd plus Li's forward test.
        d = work[pingPong];
        for (int i = 2 + pingPong; i < 4 * n - 2; i += 4) {
            final int j = i - 2 * pingPong - 1;
            work[j] = d + work[i];
            if (work[i] <= TOLERANCE_2 * d) {
                work[i]     = -0.0;
                work[j]     = d;
                work[j + 2] = 0.0;
                d = work[i + 2];
            } else if ((MathUtils.SAFE_MIN * work[i + 2] < work[j]) &&
                       (MathUtils.SAFE_MIN * work[j] < work[i + 2])) {
                final double tmp = work[i + 2] / work[j];
                work[j + 2] = work[i] * tmp;
                d *= tmp;
            } else {
                work[j + 2] = work[i + 2] * (work[i] / work[j]);
                d *= work[i + 2] / work[j];
           }
        }
        work[4 * n - 3 - pingPong] = d;

        // from ping to pong
        pingPong = 1 - pingPong;

    }

}
 
Example 19
Source File: Math_80_EigenDecompositionImpl_s.java    From coming with MIT License 4 votes vote down vote up
/**
 * Perform two iterations with Li's tests for initial splits.
 * @param n number of rows of the matrix to process
 */
private void initialSplits(final int n) {

    pingPong = 0;
    for (int k = 0; k < 2; ++k) {

        // apply Li's reverse test
        double d = work[4 * (n - 1) + pingPong];
        for (int i = 4 * (n - 2) + pingPong; i >= 0; i -= 4) {
            if (work[i + 2] <= TOLERANCE_2 * d) {
                work[i + 2] = -0.0;
                d = work[i];
            } else {
                d *= work[i] / (d + work[i + 2]);
            }
        }

        // apply dqd plus Li's forward test.
        d = work[pingPong];
        for (int i = 2 + pingPong; i < 4 * n - 2; i += 4) {
            final int j = i - 2 * pingPong - 1;
            work[j] = d + work[i];
            if (work[i] <= TOLERANCE_2 * d) {
                work[i]     = -0.0;
                work[j]     = d;
                work[j + 2] = 0.0;
                d = work[i + 2];
            } else if ((MathUtils.SAFE_MIN * work[i + 2] < work[j]) &&
                       (MathUtils.SAFE_MIN * work[j] < work[i + 2])) {
                final double tmp = work[i + 2] / work[j];
                work[j + 2] = work[i] * tmp;
                d *= tmp;
            } else {
                work[j + 2] = work[i + 2] * (work[i] / work[j]);
                d *= work[i + 2] / work[j];
           }
        }
        work[4 * n - 3 - pingPong] = d;

        // from ping to pong
        pingPong = 1 - pingPong;

    }

}
 
Example 20
Source File: 1_EigenDecompositionImpl.java    From SimFix with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Perform two iterations with Li's tests for initial splits.
 * @param n number of rows of the matrix to process
 */
private void initialSplits(final int n) {

    pingPong = 0;
    for (int k = 0; k < 2; ++k) {

        // apply Li's reverse test
        double d = work[4 * (n - 1) + pingPong];
        for (int i = 4 * (n - 2) + pingPong; i >= 0; i -= 4) {
            if (work[i + 2] <= TOLERANCE_2 * d) {
                work[i + 2] = -0.0;
                d = work[i];
            } else {
                d *= work[i] / (d + work[i + 2]);
            }
        }

        // apply dqd plus Li's forward test.
        d = work[pingPong];
        for (int i = 2 + pingPong; i < 4 * n - 2; i += 4) {
            final int j = i - 2 * pingPong - 1;
            work[j] = d + work[i];
            if (work[i] <= TOLERANCE_2 * d) {
                work[i]     = -0.0;
                work[j]     = d;
                work[j + 2] = 0.0;
                d = work[i + 2];
            } else if ((MathUtils.SAFE_MIN * work[i + 2] < work[j]) &&
                       (MathUtils.SAFE_MIN * work[j] < work[i + 2])) {
                final double tmp = work[i + 2] / work[j];
                work[j + 2] = work[i] * tmp;
                d *= tmp;
            } else {
                work[j + 2] = work[i + 2] * (work[i] / work[j]);
                d *= work[i + 2] / work[j];
           }
        }
        work[4 * n - 3 - pingPong] = d;

        // from ping to pong
        pingPong = 1 - pingPong;

    }

}