Fortran code for direct inversion of 2×2, 3×3 and 4×4 matrices (native arrays). Actually the generic methods defined are
det(A)
get the determinant of a matrix
inv(A)
invert a matrtix
solve(A,b)
solve the system A*x=b
for b
module mod_array_inv
use mod_common
implicit none
integer, parameter :: wp = real64
interface det
module procedure :: mat_det
end interface
interface inv
module procedure :: mat_inv
end interface
interface solve
module procedure :: mat_solve_vec, mat_solve_mat
end interface
contains
function mat_det(A) result(d)
real(wp), intent(in) :: A(:,:)
real(wp) :: d
integer :: n, m
n = size(A, 1)
m = size(A, 2)
if(n /= m) then
error stop "Expecting square matrix."
end if
select case(n)
case(1)
d = A(1,1)
case(2)
d = mat2_det(A)
case(3)
d = mat3_det(A)
case(4)
d = mat4_det(A)
case default
error stop "Size is not supported."
end select
end function
function mat_inv(A) result(B)
real(wp), intent(in) :: A(:,:)
real(wp) :: B(size(A,1),size(A,2))
integer :: n, m
n = size(A, 1)
m = size(A, 2)
if(n /= m) then
error stop "Expecting square matrix."
end if
select case(n)
case (1)
B = 1/A
case (2)
B = mat2_inv(A)
case (3)
B = mat3_inv(A)
case (4)
B = mat4_inv(A)
case default
error stop "Size is not supported."
end select
end function
function mat_solve_vec(A, b) result(x)
real(wp), intent(in) :: A(:,:), b(:)
real(wp), allocatable :: x(:)
integer :: n,m
n = size(A, 1)
m = size(A, 2)
if(n /= m) then
error stop "Expecting square matrix."
end if
select case(n)
case (1)
x = b/A(1,1)
case (2)
x = mat2_solve_vec(A,b)
case (3)
x = mat3_solve_vec(A,b)
case (4)
x = mat4_solve_vec(A,b)
case default
error stop "Size is not supported."
end select
end function
function mat_solve_mat(A, B) result(X)
real(wp), intent(in) :: A(:,:), B(:,:)
real(wp), allocatable :: X(:,:)
real(wp), allocatable :: A_inv(:,:)
A_inv = mat_inv(A)
X = matmul(A_inv, B)
end function
pure function mat2_det(A) result(d)
implicit real(wp) (T)
real(wp) :: d
real(wp), intent(in) :: A(2,2)
real(wp) :: t2, t5
t2 = A(1,1)*A(2,2)
t5 = A(1,2)*A(2,1)
d = t2-t5
end function
pure function mat2_inv(A) result(B)
real(wp) :: B(2,2), d_inv
real(wp), intent(in) :: A(2,2)
d_inv = 1/mat2_det(A)
B(1,1) = A(2,2)*d_inv
B(1,2) = -A(1,2)*d_inv
B(2,1) = -A(2,1)*d_inv
B(2,2) = A(1,1)*d_inv
end function
pure function mat2_solve_vec(A,b) result(x)
real(wp) :: x(2), d_inv
real(wp), intent(in) :: A(2,2), b(2)
d_inv = 1/mat2_det(A)
x(1) = d_inv*(A(2,2)*b(1) - A(1,2)*b(2))
x(2) = d_inv*(A(1,1)*b(2) - A(2,1)*b(1))
end function
pure function mat3_det(A) result(d)
implicit real(wp) (T)
real(wp) :: d
real(wp), intent(in) :: A(3,3)
real(wp) :: t2, t3, t4, t7, t8, t9
t2 = A(1,1)*A(2,2)*A(3,3)
t3 = A(1,2)*A(2,3)*A(3,1)
t4 = A(1,3)*A(2,1)*A(3,2)
t7 = A(1,1)*A(2,3)*A(3,2)
t8 = A(1,2)*A(2,1)*A(3,3)
t9 = A(1,3)*A(2,2)*A(3,1)
d = t2+t3+t4-t7-t8-t9
end function
pure function mat3_inv(A) result(B)
real(wp) :: B(3,3), d_inv
real(wp), intent(in) :: A(3,3)
d_inv = 1/mat3_det(A)
B(1,1) = d_inv*(A(2,2)*A(3,3)-A(2,3)*A(3,2))
B(1,2) = -d_inv*(A(1,2)*A(3,3)-A(1,3)*A(3,2))
B(1,3) = d_inv*(A(1,2)*A(2,3)-A(1,3)*A(2,2))
B(2,1) = -d_inv*(A(2,1)*A(3,3)-A(2,3)*A(3,1))
B(2,2) = d_inv*(A(1,1)*A(3,3)-A(1,3)*A(3,1))
B(2,3) = -d_inv*(A(1,1)*A(2,3)-A(1,3)*A(2,1))
B(3,1) = d_inv*(A(2,1)*A(3,2)-A(2,2)*A(3,1))
B(3,2) = -d_inv*(A(1,1)*A(3,2)-A(1,2)*A(3,1))
B(3,3) = d_inv*(A(1,1)*A(2,2)-A(1,2)*A(2,1))
end function
pure function mat3_solve_vec(A,b) result(x)
real(wp) :: x(3), d_inv
real(wp), intent(in) :: A(3,3), b(3)
d_inv = 1/mat3_det(A)
x(1) = d_inv*(A(1,2)*(A(2,3)*b(3)-A(3,3)*b(2))+A(1,3)*(A(3,2)*b(2)-A(2,2)*b(3))+b(1)*(A(2,2)*A(3,3)-A(2,3)*A(3,2)))
x(2) = d_inv*(A(1,1)*(A(3,3)*b(2)-A(2,3)*b(3))+A(1,3)*(A(2,1)*b(3)-A(3,1)*b(2))-b(1)*(A(2,1)*A(3,3)-A(2,3)*A(3,1)))
x(3) = d_inv*(A(1,1)*(A(2,2)*b(3)-A(3,2)*b(2))+A(1,2)*(A(3,1)*b(2)-A(2,1)*b(3))+b(1)*(A(2,1)*A(3,2)-A(2,2)*A(3,1)))
end function
pure function mat4_det(A) result(d)
implicit real(wp) (T)
real(wp) :: d
real(wp), intent(in) :: A(4,4)
real(wp) :: t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15
real(wp) :: t16, t17, t18, t19, t20, t21, t22, t23, t24, t25, t26, t27
t2 = A(1,1)*A(2,2)*A(3,3)*A(4,4)
t3 = A(1,1)*A(2,3)*A(3,4)*A(4,2)
t4 = A(1,1)*A(2,4)*A(3,2)*A(4,3)
t5 = A(1,2)*A(2,1)*A(3,4)*A(4,3)
t6 = A(1,2)*A(2,3)*A(3,1)*A(4,4)
t7 = A(1,2)*A(2,4)*A(3,3)*A(4,1)
t8 = A(1,3)*A(2,1)*A(3,2)*A(4,4)
t9 = A(1,3)*A(2,2)*A(3,4)*A(4,1)
t10 = A(1,3)*A(2,4)*A(3,1)*A(4,2)
t11 = A(1,4)*A(2,1)*A(3,3)*A(4,2)
t12 = A(1,4)*A(2,2)*A(3,1)*A(4,3)
t13 = A(1,4)*A(2,3)*A(3,2)*A(4,1)
t16 = A(1,1)*A(2,2)*A(3,4)*A(4,3)
t17 = A(1,1)*A(2,3)*A(3,2)*A(4,4)
t18 = A(1,1)*A(2,4)*A(3,3)*A(4,2)
t19 = A(1,2)*A(2,1)*A(3,3)*A(4,4)
t20 = A(1,2)*A(2,3)*A(3,4)*A(4,1)
t21 = A(1,2)*A(2,4)*A(3,1)*A(4,3)
t22 = A(1,3)*A(2,1)*A(3,4)*A(4,2)
t23 = A(1,3)*A(2,2)*A(3,1)*A(4,4)
t24 = A(1,3)*A(2,4)*A(3,2)*A(4,1)
t25 = A(1,4)*A(2,1)*A(3,2)*A(4,3)
t26 = A(1,4)*A(2,2)*A(3,3)*A(4,1)
t27 = A(1,4)*A(2,3)*A(3,1)*A(4,2)
d = t2+t3+t4+t5+t6+t7+t8+t9+t10+t11+t12+t13-t16-t17-t18-t19-t20-t21-t22-t23-t24-t25-t26-t27
end function
pure function mat4_inv(A) result(B)
real(wp) :: B(4,4), d_inv
real(wp), intent(in) :: A(4,4)
d_inv = 1/mat4_det(A)
B(1,1) = d_inv*(A(2,2)*A(3,3)*A(4,4)-A(2,2)*A(3,4)*A(4,3)-A(2,3)*A(3,2)*A(4,4)+A(2,3)*A(3,4)*A(4,2)+A(2,4)*A(3,2)*A(4,3)-A(2,4)*A(3,3)*A(4,2))
B(1,2) = -d_inv*(A(1,2)*A(3,3)*A(4,4)-A(1,2)*A(3,4)*A(4,3)-A(1,3)*A(3,2)*A(4,4)+A(1,3)*A(3,4)*A(4,2)+A(1,4)*A(3,2)*A(4,3)-A(1,4)*A(3,3)*A(4,2))
B(1,3) = d_inv*(A(1,2)*A(2,3)*A(4,4)-A(1,2)*A(2,4)*A(4,3)-A(1,3)*A(2,2)*A(4,4)+A(1,3)*A(2,4)*A(4,2)+A(1,4)*A(2,2)*A(4,3)-A(1,4)*A(2,3)*A(4,2))
B(1,4) = -d_inv*(A(1,2)*A(2,3)*A(3,4)-A(1,2)*A(2,4)*A(3,3)-A(1,3)*A(2,2)*A(3,4)+A(1,3)*A(2,4)*A(3,2)+A(1,4)*A(2,2)*A(3,3)-A(1,4)*A(2,3)*A(3,2))
B(2,1) = -d_inv*(A(2,1)*A(3,3)*A(4,4)-A(2,1)*A(3,4)*A(4,3)-A(2,3)*A(3,1)*A(4,4)+A(2,3)*A(3,4)*A(4,1)+A(2,4)*A(3,1)*A(4,3)-A(2,4)*A(3,3)*A(4,1))
B(2,2) = d_inv*(A(1,1)*A(3,3)*A(4,4)-A(1,1)*A(3,4)*A(4,3)-A(1,3)*A(3,1)*A(4,4)+A(1,3)*A(3,4)*A(4,1)+A(1,4)*A(3,1)*A(4,3)-A(1,4)*A(3,3)*A(4,1))
B(2,3) = -d_inv*(A(1,1)*A(2,3)*A(4,4)-A(1,1)*A(2,4)*A(4,3)-A(1,3)*A(2,1)*A(4,4)+A(1,3)*A(2,4)*A(4,1)+A(1,4)*A(2,1)*A(4,3)-A(1,4)*A(2,3)*A(4,1))
B(2,4) = d_inv*(A(1,1)*A(2,3)*A(3,4)-A(1,1)*A(2,4)*A(3,3)-A(1,3)*A(2,1)*A(3,4)+A(1,3)*A(2,4)*A(3,1)+A(1,4)*A(2,1)*A(3,3)-A(1,4)*A(2,3)*A(3,1))
B(3,1) = d_inv*(A(2,1)*A(3,2)*A(4,4)-A(2,1)*A(3,4)*A(4,2)-A(2,2)*A(3,1)*A(4,4)+A(2,2)*A(3,4)*A(4,1)+A(2,4)*A(3,1)*A(4,2)-A(2,4)*A(3,2)*A(4,1))
B(3,2) = -d_inv*(A(1,1)*A(3,2)*A(4,4)-A(1,1)*A(3,4)*A(4,2)-A(1,2)*A(3,1)*A(4,4)+A(1,2)*A(3,4)*A(4,1)+A(1,4)*A(3,1)*A(4,2)-A(1,4)*A(3,2)*A(4,1))
B(3,3) = d_inv*(A(1,1)*A(2,2)*A(4,4)-A(1,1)*A(2,4)*A(4,2)-A(1,2)*A(2,1)*A(4,4)+A(1,2)*A(2,4)*A(4,1)+A(1,4)*A(2,1)*A(4,2)-A(1,4)*A(2,2)*A(4,1))
B(3,4) = -d_inv*(A(1,1)*A(2,2)*A(3,4)-A(1,1)*A(2,4)*A(3,2)-A(1,2)*A(2,1)*A(3,4)+A(1,2)*A(2,4)*A(3,1)+A(1,4)*A(2,1)*A(3,2)-A(1,4)*A(2,2)*A(3,1))
B(4,1) = -d_inv*(A(2,1)*A(3,2)*A(4,3)-A(2,1)*A(3,3)*A(4,2)-A(2,2)*A(3,1)*A(4,3)+A(2,2)*A(3,3)*A(4,1)+A(2,3)*A(3,1)*A(4,2)-A(2,3)*A(3,2)*A(4,1))
B(4,2) = d_inv*(A(1,1)*A(3,2)*A(4,3)-A(1,1)*A(3,3)*A(4,2)-A(1,2)*A(3,1)*A(4,3)+A(1,2)*A(3,3)*A(4,1)+A(1,3)*A(3,1)*A(4,2)-A(1,3)*A(3,2)*A(4,1))
B(4,3) = -d_inv*(A(1,1)*A(2,2)*A(4,3)-A(1,1)*A(2,3)*A(4,2)-A(1,2)*A(2,1)*A(4,3)+A(1,2)*A(2,3)*A(4,1)+A(1,3)*A(2,1)*A(4,2)-A(1,3)*A(2,2)*A(4,1))
B(4,4) = d_inv*(A(1,1)*A(2,2)*A(3,3)-A(1,1)*A(2,3)*A(3,2)-A(1,2)*A(2,1)*A(3,3)+A(1,2)*A(2,3)*A(3,1)+A(1,3)*A(2,1)*A(3,2)-A(1,3)*A(2,2)*A(3,1))
end function
pure function mat4_solve_vec(A,b) result(x)
real(wp) :: x(4)
real(wp), intent(in) :: A(4,4), b(4)
x = matmul(mat4_inv(A), b)
end function
end module
and here is some sample output for n=1
all the way up to n=4
Size = 1
A=
0.605321
det(A) = 0.605321032671391
inv(A)=
1.65202
b=
x=
1.55042
max(error)= 0.000000000000000E+000
Size = 2
A=
0.837911 0.753904
0.262199E-01 0.359381
det(A) = 0.281362058913013
inv(A)=
1.27729 -2.67948
-.931892E-01 2.97805
b=
x=
3.43630
-2.86037
max(error)= 2.220446049250313E-016
Size = 3
A=
0.782167 0.695742 0.440628
0.229894 0.439319 0.472592
0.404291 0.615954 0.812874
det(A) = 3.868436784268883E-002
inv(A)=
1.70655 -7.60369 3.49561
0.108292 11.8307 -6.93686
-.930825 -5.18290 4.74802
b=
x=
-7.43101
10.5217
-4.62486
max(error)= 3.330669073875470E-016
Size = 4
A=
0.617587 0.715303 0.951393 0.570026
0.201500 0.369288 0.805236E-01 0.722515
0.594583 0.579624 0.292902 0.664950
0.559947 0.366043E-01 0.914511 0.373112
det(A) = -0.108885730704336
inv(A)=
-1.61248 -2.23499 3.36355 0.797015
1.70799 -.473662 0.294076E-01 -1.74459
1.14364 0.492039 -1.75144 0.421352
-.550738 2.19463 -.757887 0.622449
b=
x=
1.43143
2.01398
-.357357
-2.56754
max(error)= 1.332267629550188E-015