home *** CD-ROM | disk | FTP | other *** search
- ------------ SIMTEL20 Ada Software Repository Proloque --------------
- -- -*
- -- Unit name : MATRIX_PACKAGE
- -- Version : 1.0
- -- Author : Dr. Roger Lee
- -- : Naval Air Developement Center
- -- : Advanced Software Technology Division
- -- : Warminster Pa. 18974
- -- DDN Address : LEE at NADC
- -- Copyright : (c) 1984 Roger Lee
- -- Date created : Feb 84
- -- Release date : 7 Jun 85
- -- Last update : Feb 84
- -- Machine/System Compiled/Run on : VMS VAX11/780 Telesoft Ada compiler
- -- -*
- -----------------------------------------------------------------------
- -- -*
- -- Keywords :
- ----------------: MATRIX,VECTOR
- --
- -- ABSTRACT :
- ----------------: MATRIX_PACKAGE is a general purpose matrix package.
- -- It defines data types VECTOR and MATRIX, and contains functions
- -- to perform general matrix algebra operations. It provides for addition,
- -- subtraction, and multiplication of VECTORS, MATRICES and SCALARS.
- -- It also provides for matrix inversion and vector dot product.
- --
- -- -*
- ---------------- Revision history --------------------------------------
- -- -*
- -- DATE VERSION AUTHOR HISTORY
- -- 2/84 1.0 Roger Lee Initial Release
- -- -*
- ---------------- Distribution and Copyright ----------------------------
- -- -*
- -- This prologue must be included in all copies of this software.
- --
- -- This software is copyright by the author.
- --
- -- This software is released to the Ada community.
- -- This software is released to the Public Domain (note:
- -- software released to the Public Domain is not subject
- -- to copyright protection).
- -- Restrictions on use or distribution: NONE
- -- -*
- --------------------- Disclaimer ---------------------------------------
- -- -*
- -- This software and its documentation are provided "AS IS" and
- -- without any expressed or implied warranties whatsoever.
- -- No warranties as to performance, merchantability, or fitness
- -- for a particular purpose exist.
- --
- -- Because of the diverity of conditions and hardware under
- -- which this software may be used, no warranty of fitness for
- -- a particular purpose is offered. The user is advised to
- -- test the software thoroughly before relying on it. The user
- -- must assume the entire risk and liability of using this
- -- software.
- --
- -- In no event shall any person or organization of people be
- -- held responsible for any direct, indirect, consequential
- -- or inconsequential damages or lost profits.
- -- -*
- -------------------- END-PROLOGUE ---------------------------------------
- --
- --
- --
- package MATRIX_PACKAGE is
- --> PROLOGUE
- -->
- -->**************************************************************************
- --> This package is a general purpose matrix package. It defines data types
- --> VECTOR and MATRIX, and contains functions to perform general matrix
- --> algebra operations.
- -->**************************************************************************
- -->
-
- type VECTOR is array(INTEGER range<>) of FLOAT ;
- type MATRIX is array(INTEGER range<>,INTEGER range <>) of FLOAT;
- INCOMPARABLE_DIMENSION :exception; -- the dimension of matrices
- -- or vectors to be operated are
- -- incomparable
- SINGULAR : exception; -- matrix to be inverted is singular
- function TRANSPOSE(A : MATRIX) return MATRIX ; -- transpose of matrix
- function TRANSPOSE(A : VECTOR) return VECTOR ; -- transpose of vector
- function "+" (A : VECTOR; B : VECTOR) return VECTOR ; -- sum of vector
- function "+" (A : MATRIX; B : MATRIX) return MATRIX ; -- sum of matrix
- function "-" (A : VECTOR; B : VECTOR) return VECTOR ;
- -- difference of vector
- function "-" (A : MATRIX; B : MATRIX) return MATRIX ;
- -- difference of matrix
- function "*" (A : FLOAT; B : VECTOR) return VECTOR ;
- -- scalar, vector multiplication
- function "*" (A : VECTOR; B : FLOAT) return VECTOR ;
- -- vector, scalar multiplication
- function "*" (A : VECTOR; B : VECTOR) return FLOAT ;
- -- inner(dot) product of two vectors
- function "*" (A : MATRIX; B : VECTOR) return VECTOR ;
- -- matrix,column vector multiplication
- function "*" (A : VECTOR; B : MATRIX) return VECTOR ;
- -- row vector,matrix multiplication
- function "*" (A : FLOAT; B : MATRIX) return MATRIX ;
- -- scalar, matrix multiplication
- function "*" (A : MATRIX; B : FLOAT) return MATRIX ;
- -- matrix, scalar multiplication
- function "*" (A : MATRIX; B : MATRIX) return MATRIX ;
- -- matrix, matrix multiplication
- function "**"(A : MATRIX; P : INTEGER) return MATRIX;
- -- square matrix raised to integer
- -- power
- --
- --> CALLS
- --> NONE
- -->
- end MATRIX_PACKAGE;
-
-
- ---
- package body MATRIX_PACKAGE is
-
- ---
- function TRANSPOSE(A : MATRIX) return MATRIX is
- B : MATRIX(A'FIRST(2)..A'LAST(2),A'FIRST(1)..A'LAST(1)) ;
- -- ******************************************************************
- -- This function performs the tranpose of input matrix A
- -- ******************************************************************
- begin
- for I in A'RANGE(2) loop
- for J in A'RANGE(1) loop
- B(I,J) := A(J,I) ;
- end loop ;
- end loop ;
- return B ;
- end TRANSPOSE;
- ---
- function TRANSPOSE(A : VECTOR) return VECTOR is
- -- *****************************************************************
- -- This function returns the transpose of a vector. In programming
- -- a vector is always stored as one-dimensional array. Therefore,
- -- there is no difference between row vector and column vector.
- -- Thus, this function just returns the input vector (do nothing).
- -- *****************************************************************
- begin
- return A;
- end TRANSPOSE;
- ---
- function "+" (A : VECTOR; B : VECTOR) return VECTOR is
- C : VECTOR(A'FIRST..A'LAST) ;
- -- **************************************************************
- -- This function performs the addition of vector A and vector B
- -- resulting in a vector. Comparability of dimensions is checked.
- -- **************************************************************
- begin
- if A'FIRST /= B'FIRST or A'LAST /= B'LAST then
- raise INCOMPARABLE_DIMENSION;
- end if ;
- for I in A'RANGE loop
- C(I) := A(I)+B(I) ;
- end loop ;
- return C ;
- end "+";
- ---
- function "+" (A : MATRIX; B : MATRIX) return MATRIX is
- C : MATRIX(A'FIRST(1)..A'LAST(1),A'FIRST(2)..A'LAST(2)) ;
- -- *******************************************************************
- -- This function performs the addition of matrix A and matrix B
- -- resulting in a matrix. Comparability of dimensions is checked.
- -- *******************************************************************
- begin
- if (A'FIRST(1) /= B'FIRST(1) or A'LAST(1) /= B'LAST(1))
- or (A'FIRST(2) /= B'FIRST(2) or A'LAST(2) /= B'LAST(2)) then
- raise INCOMPARABLE_DIMENSION;
- end if ;
- for I in A'RANGE(1) loop
- for J in A'RANGE(2) loop
- C(I,J) := A(I,J)+B(I,J) ;
- end loop ;
- end loop ;
- return C ;
- end "+";
- ---
- function "-" (A : VECTOR; B : VECTOR) return VECTOR is
- C : VECTOR(A'FIRST..A'LAST) ;
- -- ******************************************************************
- -- This function performs the subtraction of vector B from vector A
- -- resulting in a vector. Comparability of dimensions is checked.
- -- ******************************************************************
- begin
- if A'FIRST /= B'FIRST or A'LAST /= B'LAST then
- raise INCOMPARABLE_DIMENSION;
- end if ;
- for I in A'RANGE loop
- C(I) := A(I)-B(I) ;
- end loop ;
- return C ;
- end "-";
- ---
- function "-" (A : MATRIX; B : MATRIX) return MATRIX is
- C : MATRIX(A'FIRST(1)..A'LAST(1),A'FIRST(2)..A'LAST(2)) ;
- -- ******************************************************************
- -- This function performs the subtraction of matrix B from matrix A
- -- resulting in a matrix. Comparability of dimensions is checked.
- -- ******************************************************************
- begin
- if (A'FIRST(1) /= B'FIRST(1) or A'LAST(1) /= B'LAST(1))
- or (A'FIRST(2) /= B'FIRST(2) or A'LAST(2) /= B'LAST(2)) then
- raise INCOMPARABLE_DIMENSION;
- end if ;
- for I in A'RANGE(1) loop
- for J in A'RANGE(2) loop
- C(I,J) := A(I,J)-B(I,J) ;
- end loop ;
- end loop ;
- return C ;
- end "-";
- ---
- function "*" (A:FLOAT; B:VECTOR) return VECTOR is
- C: VECTOR(B'FIRST..B'LAST);
- -- ******************************************************************
- -- This function performs the scalar multiplication of a floating
- -- number A and a vector B resulting in a vector.
- -- ******************************************************************
- begin
- for I in B'RANGE loop
- C(I):=A*B(I);
- end loop;
- return C ;
- end "*";
-
- ---
- function "*" (A:VECTOR; B:FLOAT) return VECTOR is
- begin
- -- ********************************************************************
- -- This function performs the scalar multiplication of a vector A and
- -- a floating number B resulting in a vector.
- -- ********************************************************************
- return B*A;
- end "*";
-
- ---
- function "*" (A : VECTOR; B : VECTOR) return FLOAT is
- S :FLOAT:=0.0;
- -- *******************************************************************
- -- This function performs the inner (dot) product of two vectors A
- -- and B resulting in a floating number.
- -- Comparability of dimensions is checked.
- -- *******************************************************************
- begin
- if A'FIRST /= B'FIRST or A'LAST /= B'LAST then
- raise INCOMPARABLE_DIMENSION;
- end if ;
- for I in A'RANGE loop
- S := S+A(I)*B(I) ;
- end loop ;
- return S ;
- end "*";
- ---
- function "*" (A:MATRIX; B:VECTOR) return VECTOR is
- C:VECTOR(A'FIRST(1)..A'LAST(1));
- SUM:FLOAT;
- -- **********************************************************************
- -- This function performs the multiplication of a matrix A and a column
- -- vector B resulting in a column vector.
- -- Comparability of dimensions is checked.
- -- **********************************************************************
- begin
- if A'FIRST(2)/=B'FIRST or A'LAST(2) /= B'LAST then
- raise INCOMPARABLE_DIMENSION;
- end if ;
- for I in A'RANGE(1) loop
- SUM := 0.0 ;
- for K in A'RANGE(2) loop
- SUM := SUM+A(I,K)*B(K);
- end loop;
- C(I):=SUM;
- end loop ;
- return C ;
- end "*";
- ---
- function "*" (A:VECTOR; B:MATRIX) return VECTOR is
- C:VECTOR(B'FIRST(2)..B'LAST(2));
- SUM:FLOAT;
- -- ********************************************************************
- -- This function performs the multiplication of a row vector A and a
- -- matrix B resulting in a row vector.
- -- Comparability of dimensions is checked.
- -- ********************************************************************
- begin
- if A'FIRST/=B'FIRST(1) or A'LAST/=B'LAST(1) then
- raise INCOMPARABLE_DIMENSION;
- end if ;
- for J in B'RANGE(2) loop
- SUM := 0.0 ;
- for K in A'RANGE loop
- SUM := SUM+A(K)*B(K,J);
- end loop;
- C(J):=SUM;
- end loop ;
- return C ;
- end "*";
- ---
- function "*" (A:FLOAT; B:MATRIX) return MATRIX is
- C:MATRIX(B'FIRST(1)..B'LAST(1),B'FIRST(2)..B'LAST(2));
- -- ********************************************************************
- -- This function performs the scalar multipliction of a matrix B by
- -- a floating number A resulting in a matrix.
- -- ********************************************************************
- begin
- for I in B'RANGE(1) loop
- for J in B'RANGE(2) loop
- C(I,J) := A*B(I,J);
- end loop ;
- end loop ;
- return C ;
- end "*";
- ---
- function "*" (A:MATRIX; B:FLOAT) return MATRIX is
- C:MATRIX(A'FIRST(1)..A'LAST(1),A'FIRST(2)..A'LAST(2));
- -- *****************************************************************
- -- This function performs the scalar multipliction of a matrix A
- -- by a floating number B resulting in a matrix.
- -- *****************************************************************
- begin
- return B*A ;
- end "*";
- ---
- function "*" (A:MATRIX; B:MATRIX) return MATRIX is
- C:MATRIX(A'FIRST(1)..A'LAST(1),B'FIRST(2)..B'LAST(2));
- SUM: FLOAT;
- -- ********************************************************************
- -- This function performs the multiplication of matrix A and matrix B
- -- resulting in a matrix. Comparability of dimensions is checked.
- -- ********************************************************************
- begin
- if A'FIRST(2)/=B'FIRST(1) or A'LAST(2)/=B'LAST(1) then
- raise INCOMPARABLE_DIMENSION;
- end if ;
- for I in A'RANGE(1) loop
- for J in B'RANGE(2) loop
- SUM := 0.0 ;
- for K in A'RANGE(2) loop
- SUM := SUM+A(I,K)*B(K,J);
- end loop;
- C(I,J) := SUM;
- end loop ;
- end loop ;
- return C ;
- end "*";
- ---
- function "**" (A : MATRIX; P : INTEGER) return MATRIX is
- B,C : MATRIX(A'FIRST(1)..A'LAST(1), A'FIRST(1)..A'LAST(1));
- I_PIVOT,J_PIVOT : INTEGER range A'FIRST(1)..A'LAST(1);
- BIG_ENTRY, TEMP, EPSILON : FLOAT ;
- L, M : array(A'RANGE(1)) of INTEGER ;
- -- *******************************************************************
- -- This function performs the square matrix operation of " matrix A
- -- raise to integer power P ". When P is negative , say P = -N ,
- -- A**(-N) = (inverse(A))**N , that is, the inverse of A raise to
- -- power N . In this case, matrix A must be non-singular.
- -- Exceptions will be raised if the matrix A is not a square matrix,
- -- or if matrix A is singular.
- -- *******************************************************************
- begin
- if A'FIRST(1)/=A'FIRST(2) or A'LAST(1)/=A'LAST(2) then
- -- if not a square matrix
- raise INCOMPARABLE_DIMENSION ;
- end if;
-
- if P=0 then
- --& B = identity matrix
-
- for I in A'RANGE(1) loop
- for J in A'RANGE(1) loop
- if I /= J then
- B(I,J) := 0.0;
- else
- B(I,J) := 1.0;
- end if;
- end loop;
- end loop;
- return B;
- end if ;
-
- B := A ;
-
- if P>0 then
- --& B = A multiplied itself for P times
-
- for I in 1..P-1 loop
- B := B*A ;
- end loop ;
- return B ;
- end if;
-
- -- P is negative, find inverse first
-
- -- initiate the row and column interchange information
-
- for K in B'RANGE(1) loop
- L(K) := K ; -- row interchage information
- M(K) := K ; -- column interchange information
- end loop;
-
- -- major loop for inverse
-
- for K in B'RANGE(1) loop
-
- -- & search for row and column index I_PIVOT, J_PIVOT
- -- & both in (K .. B'LAST(1) ) for maximum B(I,J)
- -- & in absolute value :BIG_ENTRY
-
- BIG_ENTRY := 0.0 ;
- --
- -- check matrix singularity
- --
- for I in K..B'LAST(1) loop
- for J in K..B'LAST(1) loop
- if abs(B(I,J)) > abs(BIG_ENTRY) then
- BIG_ENTRY := B(I,J) ;
- I_PIVOT := I ;
- J_PIVOT := J ;
- end if;
- end loop;
- end loop;
- if K = B'FIRST(1) then
- if BIG_ENTRY = 0.0 then
- raise SINGULAR;
- else
- EPSILON := FLOAT(A'LENGTH(1))*abs(BIG_ENTRY)
- *0.000001;
- end if;
- else
- if abs(BIG_ENTRY) < EPSILON then
- raise SINGULAR ;
- end if;
- end if;
-
- -- interchange row and column
-
- --& interchange K-th and I_PIVOT-th rows
- if I_PIVOT/=K then
- for J in B'RANGE(1) loop
- TEMP := B(I_PIVOT,J);
- B(I_PIVOT,J) := B(K,J) ;
- B(K,J) := TEMP ;
- end loop;
- L(K) := I_PIVOT ;
- end if;
- --& interchange K-th and J_PIVOT-th columns
- if J_PIVOT/=K then
- for I in B'RANGE(1) loop
- TEMP := B(I,J_PIVOT) ;
- B(I,J_PIVOT) := B(I,K) ;
- B(I,K) := TEMP ;
- end loop ;
- M(K) := J_PIVOT ;
- end if ;
-
- --& divide K-th column by minus pivot (-BIG_ENTRY)
-
- for I in B'RANGE(1) loop
- if I/=K then
- B(I,K) := B(I,K)/(-BIG_ENTRY) ;
- end if;
- end loop ;
-
- -- reduce matrix row by row
-
- for I in B'RANGE(1) loop
- if I/=K then
- for J in B'RANGE(1) loop
- if J/=K then
- B(I,J):=B(I,J)+B(I,K)*B(K,J);
- end if ;
- end loop ;
- end if ;
- end loop ;
-
- --& divide K-th row by pivot
-
- for J in B'RANGE(1) loop
- if J/=K then
- B(K,J) := B(K,J)/BIG_ENTRY ;
- end if ;
- end loop ;
- B(K,K) := 1.0/BIG_ENTRY ;
-
- end loop ; -- end of major inverse loop
-
- -- final column and row interchange to obtain
- -- inverse of A, i.e. A**(-1)
-
- for K in reverse B'RANGE(1) loop
- -- column interchage
- J_PIVOT := L(K) ;
- if J_PIVOT/=K then
- --& intechange B(I,J_PIVOT) and B(I,K) for each row I
- for I in B'RANGE(1) loop
- TEMP := B(I,J_PIVOT) ;
- B(I,J_PIVOT) := B(I,K) ;
- B(I,K) := TEMP ;
- end loop ;
- end if ;
- -- row interchage
- I_PIVOT := M(K) ;
- if I_PIVOT/=K then
- --& INTECHANGE B(I_PIVOT,J) and B(K,J) for each column J
- for J in B'RANGE(1) loop
- TEMP := B(I_PIVOT,J) ;
- B(I_PIVOT,J) := B(K,J) ;
- B(K,J) := TEMP ;
- end loop ;
- end if ;
- end loop ;
-
- -- inverse of A is obtained and stored in B
- -- now ready to handle the negative power
-
- -- & C = B**(-P)
- if P=-1 then
- return B ;
- end if ;
-
- C := B ;
- for I in P+1..-1 loop
- C:= C*B ;
- end loop ;
- return C;
- end "**" ;
- ---
- end MATRIX_PACKAGE;
-