001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.math.linear;
019    
020    import org.apache.commons.math.linear.BiDiagonalTransformer;
021    import org.apache.commons.math.linear.MatrixUtils;
022    import org.apache.commons.math.linear.RealMatrix;
023    
024    import junit.framework.Test;
025    import junit.framework.TestCase;
026    import junit.framework.TestSuite;
027    
028    public class BiDiagonalTransformerTest extends TestCase {
029    
030        private double[][] testSquare = {
031                { 24.0 / 25.0, 43.0 / 25.0 },
032                { 57.0 / 25.0, 24.0 / 25.0 }
033        };
034    
035        private double[][] testNonSquare = {
036            {  -540.0 / 625.0,  963.0 / 625.0, -216.0 / 625.0 },
037            { -1730.0 / 625.0, -744.0 / 625.0, 1008.0 / 625.0 },
038            {  -720.0 / 625.0, 1284.0 / 625.0, -288.0 / 625.0 },
039            {  -360.0 / 625.0,  192.0 / 625.0, 1756.0 / 625.0 },
040        };
041    
042        public BiDiagonalTransformerTest(String name) {
043            super(name);
044        }
045    
046        public void testDimensions() {
047            checkdimensions(MatrixUtils.createRealMatrix(testSquare));
048            checkdimensions(MatrixUtils.createRealMatrix(testNonSquare));
049            checkdimensions(MatrixUtils.createRealMatrix(testNonSquare).transpose());
050        }
051    
052        private void checkdimensions(RealMatrix matrix) {
053            final int m = matrix.getRowDimension();
054            final int n = matrix.getColumnDimension();
055            BiDiagonalTransformer transformer = new BiDiagonalTransformer(matrix);
056            assertEquals(m, transformer.getU().getRowDimension());
057            assertEquals(m, transformer.getU().getColumnDimension());
058            assertEquals(m, transformer.getB().getRowDimension());
059            assertEquals(n, transformer.getB().getColumnDimension());
060            assertEquals(n, transformer.getV().getRowDimension());
061            assertEquals(n, transformer.getV().getColumnDimension());
062    
063        }
064    
065        public void testAEqualUSVt() {
066            checkAEqualUSVt(MatrixUtils.createRealMatrix(testSquare));
067            checkAEqualUSVt(MatrixUtils.createRealMatrix(testNonSquare));
068            checkAEqualUSVt(MatrixUtils.createRealMatrix(testNonSquare).transpose());
069        }
070    
071        private void checkAEqualUSVt(RealMatrix matrix) {
072            BiDiagonalTransformer transformer = new BiDiagonalTransformer(matrix);
073            RealMatrix u = transformer.getU();
074            RealMatrix b = transformer.getB();
075            RealMatrix v = transformer.getV();
076            double norm = u.multiply(b).multiply(v.transpose()).subtract(matrix).getNorm();
077            assertEquals(0, norm, 1.0e-14);
078        }
079    
080        public void testUOrthogonal() {
081            checkOrthogonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testSquare)).getU());
082            checkOrthogonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testNonSquare)).getU());
083            checkOrthogonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testNonSquare).transpose()).getU());
084        }
085    
086        public void testVOrthogonal() {
087            checkOrthogonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testSquare)).getV());
088            checkOrthogonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testNonSquare)).getV());
089            checkOrthogonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testNonSquare).transpose()).getV());
090        }
091    
092        private void checkOrthogonal(RealMatrix m) {
093            RealMatrix mTm = m.transpose().multiply(m);
094            RealMatrix id  = MatrixUtils.createRealIdentityMatrix(mTm.getRowDimension());
095            assertEquals(0, mTm.subtract(id).getNorm(), 1.0e-14);        
096        }
097    
098        public void testBBiDiagonal() {
099            checkBiDiagonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testSquare)).getB());
100            checkBiDiagonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testNonSquare)).getB());
101            checkBiDiagonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testNonSquare).transpose()).getB());
102        }
103    
104        private void checkBiDiagonal(RealMatrix m) {
105            final int rows = m.getRowDimension();
106            final int cols = m.getColumnDimension();
107            for (int i = 0; i < rows; ++i) {
108                for (int j = 0; j < cols; ++j) {
109                    if (rows < cols) {
110                        if ((i < j) || (i > j + 1)) {
111                            assertEquals(0, m.getEntry(i, j), 1.0e-16);
112                        }                    
113                    } else {
114                        if ((i < j - 1) || (i > j)) {
115                            assertEquals(0, m.getEntry(i, j), 1.0e-16);
116                        }
117                    }
118                }
119            }
120        }
121    
122        public void testMatricesValues() {
123           BiDiagonalTransformer transformer =
124                new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testSquare));
125           final double s17 = Math.sqrt(17.0);
126            RealMatrix uRef = MatrixUtils.createRealMatrix(new double[][] {
127                    {  -8 / (5 * s17), 19 / (5 * s17) },
128                    { -19 / (5 * s17), -8 / (5 * s17) }
129            });
130            RealMatrix bRef = MatrixUtils.createRealMatrix(new double[][] {
131                    { -3 * s17 / 5, 32 * s17 / 85 },
132                    {      0.0,     -5 * s17 / 17 }
133            });
134            RealMatrix vRef = MatrixUtils.createRealMatrix(new double[][] {
135                    { 1.0,  0.0 },
136                    { 0.0, -1.0 }
137            });
138    
139            // check values against known references
140            RealMatrix u = transformer.getU();
141            assertEquals(0, u.subtract(uRef).getNorm(), 1.0e-14);
142            RealMatrix b = transformer.getB();
143            assertEquals(0, b.subtract(bRef).getNorm(), 1.0e-14);
144            RealMatrix v = transformer.getV();
145            assertEquals(0, v.subtract(vRef).getNorm(), 1.0e-14);
146    
147            // check the same cached instance is returned the second time
148            assertTrue(u == transformer.getU());
149            assertTrue(b == transformer.getB());
150            assertTrue(v == transformer.getV());
151            
152        }
153    
154        public void testUpperOrLower() {
155            assertTrue(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testSquare)).isUpperBiDiagonal());
156            assertTrue(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testNonSquare)).isUpperBiDiagonal());
157            assertFalse(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testNonSquare).transpose()).isUpperBiDiagonal());
158        }
159    
160        public static Test suite() {
161            return new TestSuite(BiDiagonalTransformerTest.class);
162        }
163    
164    }