with MathAKD; use MathAKD; with MatrAK ; use MatrAK ; package body DOS_010_Matrix_Solutions is ---------------------------------------------------------------------- ---------------------------------------------------------------------- function Least_Squares ( A : Matrix_Type; B : Vector_Type ) return Vector_Type is ---------------------------------------------------------------------- begin return ( Inverse ( Transpose ( A ) * A ) * Transpose ( A ) ) * B; end Least_Squares; procedure Singular_Value_Decomposition ( W : out Vector_Type; V : out Matrix_Type; A : in out Matrix_Type ) is ---------------------------------------------------------------------- -- Translated from "svdcmp" of _Numerical Recipes_ ---------------------------------------------------------------------- M : integer := A'last ( 1 ); N : integer := A'last ( 2 ); N_Max : constant := 100; NM, L, K, JJ, ITS : integer; Z, Y, X, Scale, S, H, G, F, C, A_Norm : float; RV1 : Vector_Type ( 1..N_Max ); function Max ( A, B : float ) return float is begin if A > B then return A; else return B; end if; end Max; function Sign ( A, B : float ) return float is begin if B >= 0.0 then return abs ( A ); else return -abs ( A ); end if; end Sign; begin G := 0.0; Scale := 0.0; A_Norm := 0.0; for I in A'range ( 2 ) loop L := I + 1; RV1 ( I ) := Scale * G; G := 0.0; S := 0.0; Scale := 0.0; if I <= M then for K in I..M loop Scale := Scale + abs ( A ( K, I ) ); end loop; F := A ( I, I ); G := -Sign ( SqRt ( S ), F ); H := F * G - S; A ( I, I ) := F - G; if I /= N then for J in A'range ( 2 ) loop S := 0.0; for K in I..M loop S := S + A ( K, I ) * A ( K, J ); end loop; F := S / H; for K in I..M loop A ( K, J ) := A ( K, J ) + F * A ( K, I ); end loop; end loop; end if; W ( I ) := Scale * G; G := 0.0; S := 0.0; Scale := 0.0; if ( I <= M ) and ( I /= N ) then for K in A'range ( 2 ) loop Scale := Scale + abs ( A ( I, K ) ); end loop; if Scale /= 0.0 then for K in 1..N loop A ( I, K ) := A ( I, K ) / Scale; S := S + A ( I, K ) * A ( I, K ); end loop; F := A ( I, L ); G := -Sign ( SqRt ( S ), F ); H := F * G - S; A ( I, L ) := F - G; for K in A'range ( 2 ) loop RV1 ( K ) := A ( I, K ) / H; end loop; if I /= M then for J in A'range ( 1 ) loop S := 0.0; for K in A'range ( 2 ) loop S := S + A ( J, K ) * A ( I, K ); end loop; for K in A'range ( 2 ) loop A ( J, K ) := A ( J, K ) + S * RV1 ( K ); end loop; end loop; end if; for K in A'range loop A ( I, K ) := Scale * A ( I, K ); end loop; end if; end if; A_Norm := Max ( A_Norm, abs ( W ( I ) ) + abs ( RV1 ( I ) ) ); end if; for I in reverse A'range ( 2 ) loop if I < N then if G /= 0.0 then for J in A'range ( 2 ) loop V ( J, I ) := ( A ( I, J ) / A ( I, L ) ) / G; end loop; for J in A'range ( 2 ) loop S := 0.0; for K in A'range ( 2 ) loop S := S + A ( I, K ) * V ( K, J ); end loop; for K in A'range ( 2 ) loop V ( K, J ) := V ( K, J ) + S * V ( K, I ); end loop; end loop; end if; for J in A'range ( 2 ) loop V ( I, J ) := 0.0; V ( J, I ) := 0.0; end loop; end if; V ( I, I ) := 1.0; G := RV1 ( I ); L := I; end loop; for I in reverse A'range ( 2 ) loop L := I + 1; G := W ( I ); if I < N then for J in L..N loop A ( I, J ) := 0.0; end loop; end if; if G /= 0.0 then G := 1.0 / G; if I /= N then for J in L..N loop S := 0.0; for K in L..M loop S := S + A ( K, I ) * A ( K, J ); end loop; F := ( S / A ( I, I ) ) * G; for K in I..M loop A ( K, J ) := A ( K, J ) + F * A ( K, I ); end loop; end loop; end if; for J in I..M loop A ( J, I ) := A ( J, I ) * G; end loop; else for J in I..M loop A ( J, I ) := 0.0; end loop; end if; A ( I, I ) := A ( I, I ) + 1.0; end loop; end loop; end Singular_Value_Decomposition; ---------------------------------------------------------------------- ---------------------------------------------------------------------- end DOS_010_Matrix_Solutions;