1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.math.linear;
19  
20  import org.apache.commons.math.linear.BiDiagonalTransformer;
21  import org.apache.commons.math.linear.MatrixUtils;
22  import org.apache.commons.math.linear.RealMatrix;
23  
24  import junit.framework.Test;
25  import junit.framework.TestCase;
26  import junit.framework.TestSuite;
27  
28  public class BiDiagonalTransformerTest extends TestCase {
29  
30      private double[][] testSquare = {
31              { 24.0 / 25.0, 43.0 / 25.0 },
32              { 57.0 / 25.0, 24.0 / 25.0 }
33      };
34  
35      private double[][] testNonSquare = {
36          {  -540.0 / 625.0,  963.0 / 625.0, -216.0 / 625.0 },
37          { -1730.0 / 625.0, -744.0 / 625.0, 1008.0 / 625.0 },
38          {  -720.0 / 625.0, 1284.0 / 625.0, -288.0 / 625.0 },
39          {  -360.0 / 625.0,  192.0 / 625.0, 1756.0 / 625.0 },
40      };
41  
42      public BiDiagonalTransformerTest(String name) {
43          super(name);
44      }
45  
46      public void testDimensions() {
47          checkdimensions(MatrixUtils.createRealMatrix(testSquare));
48          checkdimensions(MatrixUtils.createRealMatrix(testNonSquare));
49          checkdimensions(MatrixUtils.createRealMatrix(testNonSquare).transpose());
50      }
51  
52      private void checkdimensions(RealMatrix matrix) {
53          final int m = matrix.getRowDimension();
54          final int n = matrix.getColumnDimension();
55          BiDiagonalTransformer transformer = new BiDiagonalTransformer(matrix);
56          assertEquals(m, transformer.getU().getRowDimension());
57          assertEquals(m, transformer.getU().getColumnDimension());
58          assertEquals(m, transformer.getB().getRowDimension());
59          assertEquals(n, transformer.getB().getColumnDimension());
60          assertEquals(n, transformer.getV().getRowDimension());
61          assertEquals(n, transformer.getV().getColumnDimension());
62  
63      }
64  
65      public void testAEqualUSVt() {
66          checkAEqualUSVt(MatrixUtils.createRealMatrix(testSquare));
67          checkAEqualUSVt(MatrixUtils.createRealMatrix(testNonSquare));
68          checkAEqualUSVt(MatrixUtils.createRealMatrix(testNonSquare).transpose());
69      }
70  
71      private void checkAEqualUSVt(RealMatrix matrix) {
72          BiDiagonalTransformer transformer = new BiDiagonalTransformer(matrix);
73          RealMatrix u = transformer.getU();
74          RealMatrix b = transformer.getB();
75          RealMatrix v = transformer.getV();
76          double norm = u.multiply(b).multiply(v.transpose()).subtract(matrix).getNorm();
77          assertEquals(0, norm, 1.0e-14);
78      }
79  
80      public void testUOrthogonal() {
81          checkOrthogonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testSquare)).getU());
82          checkOrthogonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testNonSquare)).getU());
83          checkOrthogonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testNonSquare).transpose()).getU());
84      }
85  
86      public void testVOrthogonal() {
87          checkOrthogonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testSquare)).getV());
88          checkOrthogonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testNonSquare)).getV());
89          checkOrthogonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testNonSquare).transpose()).getV());
90      }
91  
92      private void checkOrthogonal(RealMatrix m) {
93          RealMatrix mTm = m.transpose().multiply(m);
94          RealMatrix id  = MatrixUtils.createRealIdentityMatrix(mTm.getRowDimension());
95          assertEquals(0, mTm.subtract(id).getNorm(), 1.0e-14);        
96      }
97  
98      public void testBBiDiagonal() {
99          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 }