001        package com.croftsoft.core.math.matrix;
002        
003        /***********************************************************************
004        * A library of static methods to manipulate Matrix objects.
005        * 
006        * @version
007        *   $Id: MatrixLib.java,v 1.4 2008/05/09 18:35:55 croft Exp $
008        * @since
009        *   2008-04-25
010        * @author
011        *   <a href="https://www.croftsoft.com/">David Wallace Croft</a>
012        ***********************************************************************/
013    
014        public final class  MatrixLib
015        ////////////////////////////////////////////////////////////////////////
016        ////////////////////////////////////////////////////////////////////////
017        {
018          
019        public static void  copyToSelf (
020          final MatrixMut  matrixMut,
021          final Matrix     matrix )
022        ////////////////////////////////////////////////////////////////////////
023        {
024          final int  rowCount = matrixMut.getRowCount ( );
025          
026          final int  columnCount = matrixMut.getColumnCount ( );
027          
028          if ( rowCount != matrix.getRowCount ( ) )
029          {
030            throw new IllegalArgumentException ( "rowCount not equal" );
031          }
032          
033          if ( columnCount != matrix.getColumnCount ( ) )
034          {
035            throw new IllegalArgumentException ( "columnCount not equal" );
036          }
037          
038          for ( int  row = 0; row < rowCount; row++ )
039          {
040            for ( int  column = 0; column < columnCount; column++ )
041            {
042              matrixMut.set ( row, column, matrix.get ( row, column ) );
043            }
044          }
045        }
046        
047        public static boolean  matches (
048          final Matrix  matrix0,
049          final Matrix  matrix1 )
050        ////////////////////////////////////////////////////////////////////////
051        {
052          final int  rowCount = matrix0.getRowCount ( );
053          
054          if ( rowCount != matrix1.getRowCount ( ) )
055          {
056            return false;
057          }
058          
059          final int  columnCount = matrix0.getColumnCount ( );
060          
061          if ( columnCount != matrix1.getColumnCount ( ) )
062          {
063            return false;
064          }
065          
066          for ( int  row = 0; row < rowCount; row++ )
067          {
068            for ( int  column = 0; column < columnCount; column++ )
069            {
070              if ( matrix0.get ( row, column ) != matrix1.get ( row, column ) )
071              {
072                return false;
073              }
074            }
075          }
076          
077          return true;
078        }
079          
080        public static boolean  matches (
081          final Matrix  matrix0,
082          final Matrix  matrix1,
083          final double  tolerance )
084        ////////////////////////////////////////////////////////////////////////
085        {
086          if ( tolerance < 0 )
087          {
088            throw new IllegalArgumentException ( "tolerance < 0" );
089          }
090          
091          final int  rowCount = matrix0.getRowCount ( );
092          
093          if ( rowCount != matrix1.getRowCount ( ) )
094          {
095            return false;
096          }
097          
098          final int  columnCount = matrix0.getColumnCount ( );
099          
100          if ( columnCount != matrix1.getColumnCount ( ) )
101          {
102            return false;
103          }
104          
105          for ( int  row = 0; row < rowCount; row++ )
106          {
107            for ( int  column = 0; column < columnCount; column++ )
108            {
109              if ( Math.abs ( matrix0.get ( row, column )
110                            - matrix1.get ( row, column ) ) > tolerance )
111              {
112                return false;
113              }
114            }
115          }
116          
117          return true;
118        }
119          
120        public static MatrixMut  multiply (
121          final Matrix  matrix,
122          final double  scalar )
123        ////////////////////////////////////////////////////////////////////////
124        {
125          final MatrixMut  scaledCopy = matrix.copy ( );
126          
127          final int  rowCount = matrix.getRowCount ( );
128          
129          final int  columnCount = matrix.getColumnCount ( );
130          
131          for ( int  row = 0; row < rowCount; row++ )
132          {
133            for ( int  column = 0; column < columnCount; column++ )
134            {
135              scaledCopy.set (
136                row,
137                column,
138                matrix.get ( row, column ) * scalar );
139            }
140          }
141          
142          return scaledCopy;
143        }
144        
145        public static MatrixMut  multiply (
146          final Matrix  matrixAcc0,
147          final Matrix  matrixAcc1 )
148        ////////////////////////////////////////////////////////////////////////
149        {
150          final int  rowCount0    = matrixAcc0.getRowCount ( );
151          
152          final int  columnCount0 = matrixAcc0.getColumnCount ( );
153          
154          final int  rowCount1    = matrixAcc1.getRowCount ( );
155          
156          final int  columnCount1 = matrixAcc1.getColumnCount ( );
157          
158          if ( columnCount0 != rowCount1 )
159          {
160            throw new IllegalArgumentException ( "columnCount0 != rowCount1" );
161          }
162          
163          final MatrixMut  matrixMut
164            = new MatrixImp ( rowCount0, columnCount1 );
165          
166          for ( int  row = 0; row < rowCount0; row++ )
167          {
168            for ( int  column = 0; column < columnCount1; column++ )
169            {
170              double  value = 0;
171              
172              for ( int  i = 0; i < columnCount0; i++ )
173              {
174                value += matrixAcc0.get ( row, i )
175                       * matrixAcc1.get ( i, column );
176              }
177              
178              matrixMut.set ( row, column, value );
179            }
180          }
181          
182          return matrixMut;
183        }
184        
185        public static void  multiplyToSelf (
186          final MatrixMut  matrixMut,
187          final Matrix     matrix )
188        ////////////////////////////////////////////////////////////////////////
189        {
190          if ( !matrixMut.isSquare ( ) )
191          {
192            throw new IllegalArgumentException ( "matrixMut is not square" );
193          }
194          
195          if ( !matrix.isSquare ( ) )
196          {
197            throw new IllegalArgumentException ( "matrix is not square" );
198          }
199          
200          matrixMut.copyToSelf ( multiply ( matrixMut, matrix ) );
201        }
202        
203        public static String  toString ( final Matrix  matrix )
204        ////////////////////////////////////////////////////////////////////////
205        {
206          final StringBuilder  stringBuilder = new StringBuilder ( );
207          
208          final int  rowCount = matrix.getRowCount ( );
209          
210          final int  columnCount = matrix.getColumnCount ( );
211          
212          for ( int  row = 0; row < rowCount; row++ )
213          {
214            for ( int  column = 0; column < columnCount;  column++ )
215            {
216              stringBuilder.append (
217                String.format (
218                  "%1$1.3f",
219                  new Double ( matrix.get ( row, column ) ) ) );
220              
221              if ( column != columnCount - 1 )
222              {
223                stringBuilder.append ( ", " );
224              }
225              else if ( row != rowCount - 1 )
226              {
227                stringBuilder.append ( "; " );
228              }
229            }
230          }
231          
232          return stringBuilder.toString ( );
233        }
234        
235        public static MatrixMut  transpose ( final Matrix  matrix )
236        ////////////////////////////////////////////////////////////////////////
237        {
238          final int  rowCount = matrix.getRowCount ( );
239          
240          final int  columnCount = matrix.getColumnCount ( );
241          
242          final MatrixMut  matrixMut = new MatrixImp ( columnCount, rowCount );
243          
244          for ( int  row = 0; row < rowCount; row++ )
245          {
246            for ( int  column = 0; column < columnCount; column++ )
247            {
248              matrixMut.set ( column, row, matrix.get ( row, column ) );
249            }
250          }
251          
252          return matrixMut;
253        }
254        
255        public static void  transposeSelf ( final MatrixMut  matrixMut )
256        ////////////////////////////////////////////////////////////////////////
257        {
258          if ( !matrixMut.isSquare ( ) )
259          {
260            throw new IllegalArgumentException ( "matrix is not square" );
261          }
262          
263          final int  rowCount = matrixMut.getRowCount ( );
264          
265          for ( int  row = 0; row < rowCount; row++ )
266          {
267            for ( int  column = 0; column < row; column++ )
268            {
269              final double  valueRC = matrixMut.get ( row, column );
270                
271              final double  valueCR = matrixMut.get ( column, row );
272                
273              matrixMut.set ( row, column, valueCR );
274                
275              matrixMut.set ( column, row, valueRC );
276            }
277          }
278        }
279        
280        ////////////////////////////////////////////////////////////////////////
281        // private methods
282        ////////////////////////////////////////////////////////////////////////
283        
284        private  MatrixLib ( )
285        ////////////////////////////////////////////////////////////////////////
286        {
287          // empty
288        }
289        
290        ////////////////////////////////////////////////////////////////////////
291        ////////////////////////////////////////////////////////////////////////
292        }