module forlab_linalg use stdlib_error, only: error_stop use stdlib_kinds, only: sp, dp, qp, & int8, int16, int32, int64 use forlab_sorting, only: argsort use stdlib_optval, only: optval implicit none private public :: is_square, is_symmetric public :: zeros, ones, linspace, logspace, seq public :: eye public :: horzcat, vertcat public :: diag, det, lu, matpow, qr, svd, trace, tril, triu, chol, norm, & diff public :: operator(.i.), operator(.x.), inv, outer, solve, svdsolve interface chol !! chol computes Cholesky's decomposition of a symmetric positive !! definite matrix. module function chol_sp(A) result(L) real(sp), dimension(:, :), intent(in) :: A real(sp), dimension(:, :), allocatable :: L end function module function chol_dp(A) result(L) real(dp), dimension(:, :), intent(in) :: A real(dp), dimension(:, :), allocatable :: L end function !#:for k1,t1 in CMPLX_KINDS_TYPES ! module function chol_cdp (A) result(L) ! real(dp), dimension(:, :), intent(in) :: A ! real(dp), dimension(:, :), allocatable :: L ! end function !#:endfor end interface chol interface det !! det computes the matrix determinant. module function det_sp(A, outL, outU) result(det) real(sp), dimension(:, :), intent(in) :: A real(sp), dimension(:, :), allocatable, intent(inout), optional :: outL, outU real(sp) :: det end function det_sp module function det_dp(A, outL, outU) result(det) real(dp), dimension(:, :), intent(in) :: A real(dp), dimension(:, :), allocatable, intent(inout), optional :: outL, outU real(dp) :: det end function det_dp end interface det interface diag !! diag creates diagonal matrix or get the diagonal of a matrix. module function diag1_sp(A) result(diag) real(sp), dimension(:, :), intent(in) :: A real(sp), dimension(:), allocatable :: diag end function diag1_sp module function diag2_sp(x) result(diag) real(sp), dimension(:), intent(in) :: x real(sp), dimension(:, :), allocatable :: diag end function diag2_sp module function diag1_dp(A) result(diag) real(dp), dimension(:, :), intent(in) :: A real(dp), dimension(:), allocatable :: diag end function diag1_dp module function diag2_dp(x) result(diag) real(dp), dimension(:), intent(in) :: x real(dp), dimension(:, :), allocatable :: diag end function diag2_dp end interface diag !> Version: Experimental !> !> `diff` computes differences of arrays. !> ([Specification](../page/specs/forlab_linalg.html)) interface diff pure module function diff_1_sp(x, n) result(result) real(sp), dimension(:), intent(in) :: x integer, intent(in), optional :: n real(sp), dimension(:), allocatable :: result end function diff_1_sp pure module function diff_2_sp(A, n, dim) result(result) real(sp), dimension(:, :), intent(in) :: A integer, intent(in), optional :: n, dim real(sp), dimension(:, :), allocatable :: result end function diff_2_sp pure module function diff_1_dp(x, n) result(result) real(dp), dimension(:), intent(in) :: x integer, intent(in), optional :: n real(dp), dimension(:), allocatable :: result end function diff_1_dp pure module function diff_2_dp(A, n, dim) result(result) real(dp), dimension(:, :), intent(in) :: A integer, intent(in), optional :: n, dim real(dp), dimension(:, :), allocatable :: result end function diff_2_dp pure module function diff_1_int8(x, n) result(result) integer(int8), dimension(:), intent(in) :: x integer, intent(in), optional :: n integer(int8), dimension(:), allocatable :: result end function diff_1_int8 pure module function diff_2_int8(A, n, dim) result(result) integer(int8), dimension(:, :), intent(in) :: A integer, intent(in), optional :: n, dim integer(int8), dimension(:, :), allocatable :: result end function diff_2_int8 pure module function diff_1_int16(x, n) result(result) integer(int16), dimension(:), intent(in) :: x integer, intent(in), optional :: n integer(int16), dimension(:), allocatable :: result end function diff_1_int16 pure module function diff_2_int16(A, n, dim) result(result) integer(int16), dimension(:, :), intent(in) :: A integer, intent(in), optional :: n, dim integer(int16), dimension(:, :), allocatable :: result end function diff_2_int16 pure module function diff_1_int32(x, n) result(result) integer(int32), dimension(:), intent(in) :: x integer, intent(in), optional :: n integer(int32), dimension(:), allocatable :: result end function diff_1_int32 pure module function diff_2_int32(A, n, dim) result(result) integer(int32), dimension(:, :), intent(in) :: A integer, intent(in), optional :: n, dim integer(int32), dimension(:, :), allocatable :: result end function diff_2_int32 pure module function diff_1_int64(x, n) result(result) integer(int64), dimension(:), intent(in) :: x integer, intent(in), optional :: n integer(int64), dimension(:), allocatable :: result end function diff_1_int64 pure module function diff_2_int64(A, n, dim) result(result) integer(int64), dimension(:, :), intent(in) :: A integer, intent(in), optional :: n, dim integer(int64), dimension(:, :), allocatable :: result end function diff_2_int64 end interface diff interface eig !! eig computes eigenvalues and eigenvectors of symmetric matrix using Jacobi algorithm. module subroutine eig_sp(A, V, d, itermax) real(sp), dimension(:, :), intent(in) :: A real(sp), dimension(:, :), allocatable, intent(out) :: V real(sp), dimension(:), allocatable, intent(out) :: d integer, intent(in), optional :: itermax end subroutine eig_sp module subroutine eig_dp(A, V, d, itermax) real(dp), dimension(:, :), intent(in) :: A real(dp), dimension(:, :), allocatable, intent(out) :: V real(dp), dimension(:), allocatable, intent(out) :: d integer, intent(in), optional :: itermax end subroutine eig_dp end interface eig interface eye module subroutine eye_sp(X) real(sp), intent(out) :: X(:, :) end subroutine eye_sp module subroutine eye_dp(X) real(dp), intent(out) :: X(:, :) end subroutine eye_dp end interface eye interface horzcat module function horzcat_r_1_sp(x1, x2) result(result) real(sp), dimension(:, :), allocatable :: result real(sp), dimension(:), intent(in) :: x1, x2 end function horzcat_r_1_sp module function horzcat_r_2_sp(A1, A2) result(result) real(sp), dimension(:, :), allocatable :: result real(sp), dimension(:, :), intent(in) :: A1, A2 end function horzcat_r_2_sp module function horzcat_r_21_sp(A1, x2) result(result) real(sp), dimension(:, :), allocatable :: result real(sp), dimension(:, :), intent(in) :: A1 real(sp), dimension(:), intent(in) :: x2 end function horzcat_r_21_sp module function horzcat_r_12_sp(x1, A2) result(result) real(sp), dimension(:, :), allocatable :: result real(sp), dimension(:), intent(in) :: x1 real(sp), dimension(:, :), intent(in) :: A2 end function horzcat_r_12_sp module function horzcat_r_1_dp(x1, x2) result(result) real(dp), dimension(:, :), allocatable :: result real(dp), dimension(:), intent(in) :: x1, x2 end function horzcat_r_1_dp module function horzcat_r_2_dp(A1, A2) result(result) real(dp), dimension(:, :), allocatable :: result real(dp), dimension(:, :), intent(in) :: A1, A2 end function horzcat_r_2_dp module function horzcat_r_21_dp(A1, x2) result(result) real(dp), dimension(:, :), allocatable :: result real(dp), dimension(:, :), intent(in) :: A1 real(dp), dimension(:), intent(in) :: x2 end function horzcat_r_21_dp module function horzcat_r_12_dp(x1, A2) result(result) real(dp), dimension(:, :), allocatable :: result real(dp), dimension(:), intent(in) :: x1 real(dp), dimension(:, :), intent(in) :: A2 end function horzcat_r_12_dp module function horzcat_c_1_sp(x1, x2) result(result) complex(sp), dimension(:, :), allocatable :: result complex(sp), dimension(:), intent(in) :: x1, x2 end function horzcat_c_1_sp module function horzcat_c_2_sp(A1, A2) result(result) complex(sp), dimension(:, :), allocatable :: result complex(sp), dimension(:, :), intent(in) :: A1, A2 end function horzcat_c_2_sp module function horzcat_c_21_sp(A1, x2) result(result) complex(sp), dimension(:, :), allocatable :: result complex(sp), dimension(:, :), intent(in) :: A1 complex(sp), dimension(:), intent(in) :: x2 end function horzcat_c_21_sp module function horzcat_c_12_sp(x1, A2) result(result) complex(sp), dimension(:, :), allocatable :: result complex(sp), dimension(:), intent(in) :: x1 complex(sp), dimension(:, :), intent(in) :: A2 end function horzcat_c_12_sp module function horzcat_c_1_dp(x1, x2) result(result) complex(dp), dimension(:, :), allocatable :: result complex(dp), dimension(:), intent(in) :: x1, x2 end function horzcat_c_1_dp module function horzcat_c_2_dp(A1, A2) result(result) complex(dp), dimension(:, :), allocatable :: result complex(dp), dimension(:, :), intent(in) :: A1, A2 end function horzcat_c_2_dp module function horzcat_c_21_dp(A1, x2) result(result) complex(dp), dimension(:, :), allocatable :: result complex(dp), dimension(:, :), intent(in) :: A1 complex(dp), dimension(:), intent(in) :: x2 end function horzcat_c_21_dp module function horzcat_c_12_dp(x1, A2) result(result) complex(dp), dimension(:, :), allocatable :: result complex(dp), dimension(:), intent(in) :: x1 complex(dp), dimension(:, :), intent(in) :: A2 end function horzcat_c_12_dp module function horzcat_i_1_int8(x1, x2) result(result) integer(int8), dimension(:, :), allocatable :: result integer(int8), dimension(:), intent(in) :: x1, x2 end function horzcat_i_1_int8 module function horzcat_i_2_int8(A1, A2) result(result) integer(int8), dimension(:, :), allocatable :: result integer(int8), dimension(:, :), intent(in) :: A1, A2 end function horzcat_i_2_int8 module function horzcat_i_21_int8(A1, x2) result(result) integer(int8), dimension(:, :), allocatable :: result integer(int8), dimension(:, :), intent(in) :: A1 integer(int8), dimension(:), intent(in) :: x2 end function horzcat_i_21_int8 module function horzcat_i_12_int8(x1, A2) result(result) integer(int8), dimension(:, :), allocatable :: result integer(int8), dimension(:), intent(in) :: x1 integer(int8), dimension(:, :), intent(in) :: A2 end function horzcat_i_12_int8 module function horzcat_i_1_int16(x1, x2) result(result) integer(int16), dimension(:, :), allocatable :: result integer(int16), dimension(:), intent(in) :: x1, x2 end function horzcat_i_1_int16 module function horzcat_i_2_int16(A1, A2) result(result) integer(int16), dimension(:, :), allocatable :: result integer(int16), dimension(:, :), intent(in) :: A1, A2 end function horzcat_i_2_int16 module function horzcat_i_21_int16(A1, x2) result(result) integer(int16), dimension(:, :), allocatable :: result integer(int16), dimension(:, :), intent(in) :: A1 integer(int16), dimension(:), intent(in) :: x2 end function horzcat_i_21_int16 module function horzcat_i_12_int16(x1, A2) result(result) integer(int16), dimension(:, :), allocatable :: result integer(int16), dimension(:), intent(in) :: x1 integer(int16), dimension(:, :), intent(in) :: A2 end function horzcat_i_12_int16 module function horzcat_i_1_int32(x1, x2) result(result) integer(int32), dimension(:, :), allocatable :: result integer(int32), dimension(:), intent(in) :: x1, x2 end function horzcat_i_1_int32 module function horzcat_i_2_int32(A1, A2) result(result) integer(int32), dimension(:, :), allocatable :: result integer(int32), dimension(:, :), intent(in) :: A1, A2 end function horzcat_i_2_int32 module function horzcat_i_21_int32(A1, x2) result(result) integer(int32), dimension(:, :), allocatable :: result integer(int32), dimension(:, :), intent(in) :: A1 integer(int32), dimension(:), intent(in) :: x2 end function horzcat_i_21_int32 module function horzcat_i_12_int32(x1, A2) result(result) integer(int32), dimension(:, :), allocatable :: result integer(int32), dimension(:), intent(in) :: x1 integer(int32), dimension(:, :), intent(in) :: A2 end function horzcat_i_12_int32 module function horzcat_i_1_int64(x1, x2) result(result) integer(int64), dimension(:, :), allocatable :: result integer(int64), dimension(:), intent(in) :: x1, x2 end function horzcat_i_1_int64 module function horzcat_i_2_int64(A1, A2) result(result) integer(int64), dimension(:, :), allocatable :: result integer(int64), dimension(:, :), intent(in) :: A1, A2 end function horzcat_i_2_int64 module function horzcat_i_21_int64(A1, x2) result(result) integer(int64), dimension(:, :), allocatable :: result integer(int64), dimension(:, :), intent(in) :: A1 integer(int64), dimension(:), intent(in) :: x2 end function horzcat_i_21_int64 module function horzcat_i_12_int64(x1, A2) result(result) integer(int64), dimension(:, :), allocatable :: result integer(int64), dimension(:), intent(in) :: x1 integer(int64), dimension(:, :), intent(in) :: A2 end function horzcat_i_12_int64 end interface horzcat interface vertcat module function vertcat_r_1_sp(x1, x2) result(result) real(sp), dimension(:, :), allocatable :: result real(sp), dimension(:), intent(in) :: x1, x2 end function vertcat_r_1_sp module function vertcat_r_2_sp(A1, A2) result(result) real(sp), dimension(:, :), allocatable :: result real(sp), dimension(:, :), intent(in) :: A1, A2 end function vertcat_r_2_sp module function vertcat_r_21_sp(A1, x2) result(result) real(sp), dimension(:, :), allocatable :: result real(sp), dimension(:, :), intent(in) :: A1 real(sp), dimension(:), intent(in) :: x2 end function vertcat_r_21_sp module function vertcat_r_12_sp(x1, A2) result(result) real(sp), dimension(:, :), allocatable :: result real(sp), dimension(:), intent(in) :: x1 real(sp), dimension(:, :), intent(in) :: A2 end function vertcat_r_12_sp module function vertcat_r_1_dp(x1, x2) result(result) real(dp), dimension(:, :), allocatable :: result real(dp), dimension(:), intent(in) :: x1, x2 end function vertcat_r_1_dp module function vertcat_r_2_dp(A1, A2) result(result) real(dp), dimension(:, :), allocatable :: result real(dp), dimension(:, :), intent(in) :: A1, A2 end function vertcat_r_2_dp module function vertcat_r_21_dp(A1, x2) result(result) real(dp), dimension(:, :), allocatable :: result real(dp), dimension(:, :), intent(in) :: A1 real(dp), dimension(:), intent(in) :: x2 end function vertcat_r_21_dp module function vertcat_r_12_dp(x1, A2) result(result) real(dp), dimension(:, :), allocatable :: result real(dp), dimension(:), intent(in) :: x1 real(dp), dimension(:, :), intent(in) :: A2 end function vertcat_r_12_dp module function vertcat_c_1_sp(x1, x2) result(result) complex(sp), dimension(:, :), allocatable :: result complex(sp), dimension(:), intent(in) :: x1, x2 end function vertcat_c_1_sp module function vertcat_c_2_sp(A1, A2) result(result) complex(sp), dimension(:, :), allocatable :: result complex(sp), dimension(:, :), intent(in) :: A1, A2 end function vertcat_c_2_sp module function vertcat_c_21_sp(A1, x2) result(result) complex(sp), dimension(:, :), allocatable :: result complex(sp), dimension(:, :), intent(in) :: A1 complex(sp), dimension(:), intent(in) :: x2 end function vertcat_c_21_sp module function vertcat_c_12_sp(x1, A2) result(result) complex(sp), dimension(:, :), allocatable :: result complex(sp), dimension(:), intent(in) :: x1 complex(sp), dimension(:, :), intent(in) :: A2 end function vertcat_c_12_sp module function vertcat_c_1_dp(x1, x2) result(result) complex(dp), dimension(:, :), allocatable :: result complex(dp), dimension(:), intent(in) :: x1, x2 end function vertcat_c_1_dp module function vertcat_c_2_dp(A1, A2) result(result) complex(dp), dimension(:, :), allocatable :: result complex(dp), dimension(:, :), intent(in) :: A1, A2 end function vertcat_c_2_dp module function vertcat_c_21_dp(A1, x2) result(result) complex(dp), dimension(:, :), allocatable :: result complex(dp), dimension(:, :), intent(in) :: A1 complex(dp), dimension(:), intent(in) :: x2 end function vertcat_c_21_dp module function vertcat_c_12_dp(x1, A2) result(result) complex(dp), dimension(:, :), allocatable :: result complex(dp), dimension(:), intent(in) :: x1 complex(dp), dimension(:, :), intent(in) :: A2 end function vertcat_c_12_dp module function vertcat_i_1_int8(x1, x2) result(result) integer(int8), dimension(:, :), allocatable :: result integer(int8), dimension(:), intent(in) :: x1, x2 end function vertcat_i_1_int8 module function vertcat_i_2_int8(A1, A2) result(result) integer(int8), dimension(:, :), allocatable :: result integer(int8), dimension(:, :), intent(in) :: A1, A2 end function vertcat_i_2_int8 module function vertcat_i_21_int8(A1, x2) result(result) integer(int8), dimension(:, :), allocatable :: result integer(int8), dimension(:, :), intent(in) :: A1 integer(int8), dimension(:), intent(in) :: x2 end function vertcat_i_21_int8 module function vertcat_i_12_int8(x1, A2) result(result) integer(int8), dimension(:, :), allocatable :: result integer(int8), dimension(:), intent(in) :: x1 integer(int8), dimension(:, :), intent(in) :: A2 end function vertcat_i_12_int8 module function vertcat_i_1_int16(x1, x2) result(result) integer(int16), dimension(:, :), allocatable :: result integer(int16), dimension(:), intent(in) :: x1, x2 end function vertcat_i_1_int16 module function vertcat_i_2_int16(A1, A2) result(result) integer(int16), dimension(:, :), allocatable :: result integer(int16), dimension(:, :), intent(in) :: A1, A2 end function vertcat_i_2_int16 module function vertcat_i_21_int16(A1, x2) result(result) integer(int16), dimension(:, :), allocatable :: result integer(int16), dimension(:, :), intent(in) :: A1 integer(int16), dimension(:), intent(in) :: x2 end function vertcat_i_21_int16 module function vertcat_i_12_int16(x1, A2) result(result) integer(int16), dimension(:, :), allocatable :: result integer(int16), dimension(:), intent(in) :: x1 integer(int16), dimension(:, :), intent(in) :: A2 end function vertcat_i_12_int16 module function vertcat_i_1_int32(x1, x2) result(result) integer(int32), dimension(:, :), allocatable :: result integer(int32), dimension(:), intent(in) :: x1, x2 end function vertcat_i_1_int32 module function vertcat_i_2_int32(A1, A2) result(result) integer(int32), dimension(:, :), allocatable :: result integer(int32), dimension(:, :), intent(in) :: A1, A2 end function vertcat_i_2_int32 module function vertcat_i_21_int32(A1, x2) result(result) integer(int32), dimension(:, :), allocatable :: result integer(int32), dimension(:, :), intent(in) :: A1 integer(int32), dimension(:), intent(in) :: x2 end function vertcat_i_21_int32 module function vertcat_i_12_int32(x1, A2) result(result) integer(int32), dimension(:, :), allocatable :: result integer(int32), dimension(:), intent(in) :: x1 integer(int32), dimension(:, :), intent(in) :: A2 end function vertcat_i_12_int32 module function vertcat_i_1_int64(x1, x2) result(result) integer(int64), dimension(:, :), allocatable :: result integer(int64), dimension(:), intent(in) :: x1, x2 end function vertcat_i_1_int64 module function vertcat_i_2_int64(A1, A2) result(result) integer(int64), dimension(:, :), allocatable :: result integer(int64), dimension(:, :), intent(in) :: A1, A2 end function vertcat_i_2_int64 module function vertcat_i_21_int64(A1, x2) result(result) integer(int64), dimension(:, :), allocatable :: result integer(int64), dimension(:, :), intent(in) :: A1 integer(int64), dimension(:), intent(in) :: x2 end function vertcat_i_21_int64 module function vertcat_i_12_int64(x1, A2) result(result) integer(int64), dimension(:, :), allocatable :: result integer(int64), dimension(:), intent(in) :: x1 integer(int64), dimension(:, :), intent(in) :: A2 end function vertcat_i_12_int64 end interface vertcat interface inv module function inv_rsp(A) result(inv) real(sp), dimension(:, :), intent(in) :: A real(sp), dimension(:, :), allocatable :: inv end function inv_rsp module function inv_rdp(A) result(inv) real(dp), dimension(:, :), intent(in) :: A real(dp), dimension(:, :), allocatable :: inv end function inv_rdp module function inv_csp(A) result(inv) complex(sp), dimension(:, :), intent(in) :: A complex(sp), dimension(:, :), allocatable :: inv end function inv_csp module function inv_cdp(A) result(inv) complex(dp), dimension(:, :), intent(in) :: A complex(dp), dimension(:, :), allocatable :: inv end function inv_cdp end interface inv interface is_square procedure :: is_square_rsp procedure :: is_square_rdp procedure :: is_square_csp procedure :: is_square_cdp end interface is_square interface is_symmetric procedure :: is_symmetric_rsp procedure :: is_symmetric_rdp procedure :: is_symmetric_csp procedure :: is_symmetric_cdp end interface is_symmetric interface linspace pure module subroutine linspace_sp(X, from, to) real(sp), intent(out) :: X(:) real(sp), intent(in) :: from, to end subroutine linspace_sp pure module subroutine linspace_dp(X, from, to) real(dp), intent(out) :: X(:) real(dp), intent(in) :: from, to end subroutine linspace_dp end interface linspace interface logspace pure module subroutine logspace_sp(X, from, to) real(sp), intent(out) :: X(:) real(sp), intent(in) :: from, to end subroutine logspace_sp pure module subroutine logspace_dp(X, from, to) real(dp), intent(out) :: X(:) real(dp), intent(in) :: from, to end subroutine logspace_dp end interface logspace interface lu !! lu computes the LU matrix factorization. module subroutine lu_sp(A, L, U) real(sp), dimension(:, :), intent(in) :: A real(sp), dimension(:, :), allocatable, intent(out) :: L, U end subroutine lu_sp module subroutine lu_dp(A, L, U) real(dp), dimension(:, :), intent(in) :: A real(dp), dimension(:, :), allocatable, intent(out) :: L, U end subroutine lu_dp end interface lu interface matpow !! Calculat matrix power module function matpow_sp(a, num) result(c) real(sp), dimension(:, :), intent(in) :: a real(sp), allocatable :: c(:, :) integer::num end function matpow_sp module function matpow_dp(a, num) result(c) real(dp), dimension(:, :), intent(in) :: a real(dp), allocatable :: c(:, :) integer::num end function matpow_dp end interface matpow interface norm !! norm computes vector and matrix norms. real(sp) module function norm1_sp(x, p) real(sp), dimension(:), intent(in) :: x real(sp), intent(in), optional :: p end function norm1_sp real(sp) module function norm2_sp(A, p) real(sp), dimension(:, :), intent(in) :: A real(sp), intent(in), optional :: p end function norm2_sp real(dp) module function norm1_dp(x, p) real(dp), dimension(:), intent(in) :: x real(dp), intent(in), optional :: p end function norm1_dp real(dp) module function norm2_dp(A, p) real(dp), dimension(:, :), intent(in) :: A real(dp), intent(in), optional :: p end function norm2_dp end interface norm interface operator(.i.) !! Calculate the inverse of a real matrix. procedure inv_rsp procedure inv_rdp procedure inv_csp procedure inv_cdp end interface operator(.i.) interface operator(.x.) procedure :: rmut_sp procedure :: rmut_dp procedure :: cmut_sp procedure :: cmut_dp procedure :: rcmut_sp procedure :: rcmut_dp procedure :: crmut_sp procedure :: crmut_dp end interface operator(.x.) !> Version: experimental !> !> Creates a rank-1 or rank-2 array filled ones. !> ([Specification](../page/specs/forlab_linalg.html#zerosones)) interface ones procedure :: ones_1_default procedure :: ones_2_default end interface ones interface outer module function outer_int8(x, y) integer(int8), dimension(:, :), allocatable :: outer_int8 integer(int8), dimension(:), intent(in) :: x, y end function module function outer_int16(x, y) integer(int16), dimension(:, :), allocatable :: outer_int16 integer(int16), dimension(:), intent(in) :: x, y end function module function outer_int32(x, y) integer(int32), dimension(:, :), allocatable :: outer_int32 integer(int32), dimension(:), intent(in) :: x, y end function module function outer_int64(x, y) integer(int64), dimension(:, :), allocatable :: outer_int64 integer(int64), dimension(:), intent(in) :: x, y end function module function outer_sp(x, y) real(sp), dimension(:, :), allocatable :: outer_sp real(sp), dimension(:), intent(in) :: x, y end function module function outer_dp(x, y) real(dp), dimension(:, :), allocatable :: outer_dp real(dp), dimension(:), intent(in) :: x, y end function end interface outer interface qr module subroutine qr_sp(a, q, r, l) real(sp), intent(in)::a(:, :) real(sp), allocatable, intent(out) :: q(:, :), r(:, :) integer, optional::l end subroutine qr_sp module subroutine qr_dp(a, q, r, l) real(dp), intent(in)::a(:, :) real(dp), allocatable, intent(out) :: q(:, :), r(:, :) integer, optional::l end subroutine qr_dp end interface qr interface seq !! seq returns evenly spaced vector. module subroutine seq_sp(X, from, to, by) real(sp), dimension(:), allocatable, intent(out) :: X real(sp), intent(in) :: from, to real(sp), optional, intent(in) :: by end subroutine seq_sp module subroutine seq_dp(X, from, to, by) real(dp), dimension(:), allocatable, intent(out) :: X real(dp), intent(in) :: from, to real(dp), optional, intent(in) :: by end subroutine seq_dp module subroutine seq_int8(X, from, to, by) integer(int8), dimension(:), allocatable, intent(out) :: X integer(int8), intent(in) :: from, to integer(int8), optional, intent(in) :: by end subroutine seq_int8 module subroutine seq_int16(X, from, to, by) integer(int16), dimension(:), allocatable, intent(out) :: X integer(int16), intent(in) :: from, to integer(int16), optional, intent(in) :: by end subroutine seq_int16 module subroutine seq_int32(X, from, to, by) integer(int32), dimension(:), allocatable, intent(out) :: X integer(int32), intent(in) :: from, to integer(int32), optional, intent(in) :: by end subroutine seq_int32 module subroutine seq_int64(X, from, to, by) integer(int64), dimension(:), allocatable, intent(out) :: X integer(int64), intent(in) :: from, to integer(int64), optional, intent(in) :: by end subroutine seq_int64 end interface seq interface solve module function solve_sp(A, b) result(x) real(sp), dimension(:, :), intent(in) :: A real(sp), dimension(:), intent(in) :: b real(sp), dimension(:), allocatable :: x end function solve_sp module function solve_dp(A, b) result(x) real(dp), dimension(:, :), intent(in) :: A real(dp), dimension(:), intent(in) :: b real(dp), dimension(:), allocatable :: x end function solve_dp end interface solve interface svd module subroutine svd_sp(a, w, u, v, d, ierr) real(sp), dimension(:, :), intent(in) :: a real(sp), dimension(:), allocatable, intent(out) :: w real(sp), dimension(:, :), allocatable, intent(out), optional :: u, v integer, intent(out), optional :: ierr logical, intent(in), optional ::d end subroutine svd_sp module subroutine svd_dp(a, w, u, v, d, ierr) real(dp), dimension(:, :), intent(in) :: a real(dp), dimension(:), allocatable, intent(out) :: w real(dp), dimension(:, :), allocatable, intent(out), optional :: u, v integer, intent(out), optional :: ierr logical, intent(in), optional ::d end subroutine svd_dp end interface svd interface svdsolve module function svdsolve_sp(A, b, cutoff) result(x) real(sp), dimension(:, :), intent(in) :: A real(sp), dimension(:), intent(in) :: b real(sp), dimension(:), allocatable :: x integer, intent(in), optional :: cutoff end function svdsolve_sp module function svdsolve_dp(A, b, cutoff) result(x) real(dp), dimension(:, :), intent(in) :: A real(dp), dimension(:), intent(in) :: b real(dp), dimension(:), allocatable :: x integer, intent(in), optional :: cutoff end function svdsolve_dp end interface svdsolve interface trace procedure :: trace_sp procedure :: trace_dp end interface trace interface tril module function tril_int8(A, k) integer(int8), dimension(:, :), allocatable :: tril_int8 integer(int8), dimension(:, :), intent(in) :: A integer, intent(in), optional :: k end function tril_int8 module function tril_int16(A, k) integer(int16), dimension(:, :), allocatable :: tril_int16 integer(int16), dimension(:, :), intent(in) :: A integer, intent(in), optional :: k end function tril_int16 module function tril_int32(A, k) integer(int32), dimension(:, :), allocatable :: tril_int32 integer(int32), dimension(:, :), intent(in) :: A integer, intent(in), optional :: k end function tril_int32 module function tril_int64(A, k) integer(int64), dimension(:, :), allocatable :: tril_int64 integer(int64), dimension(:, :), intent(in) :: A integer, intent(in), optional :: k end function tril_int64 module function tril_sp(A, k) real(sp), dimension(:, :), allocatable :: tril_sp real(sp), dimension(:, :), intent(in) :: A integer, intent(in), optional :: k end function tril_sp module function tril_dp(A, k) real(dp), dimension(:, :), allocatable :: tril_dp real(dp), dimension(:, :), intent(in) :: A integer, intent(in), optional :: k end function tril_dp module function tril_csp(A, k) complex(sp), dimension(:, :), allocatable :: tril_csp complex(sp), dimension(:, :), intent(in) :: A integer, intent(in), optional :: k end function tril_csp module function tril_cdp(A, k) complex(dp), dimension(:, :), allocatable :: tril_cdp complex(dp), dimension(:, :), intent(in) :: A integer, intent(in), optional :: k end function tril_cdp end interface tril interface triu module function triu_int8(A, k) integer(int8), dimension(:, :), allocatable :: triu_int8 integer(int8), dimension(:, :), intent(in) :: A integer, intent(in), optional :: k end function triu_int8 module function triu_int16(A, k) integer(int16), dimension(:, :), allocatable :: triu_int16 integer(int16), dimension(:, :), intent(in) :: A integer, intent(in), optional :: k end function triu_int16 module function triu_int32(A, k) integer(int32), dimension(:, :), allocatable :: triu_int32 integer(int32), dimension(:, :), intent(in) :: A integer, intent(in), optional :: k end function triu_int32 module function triu_int64(A, k) integer(int64), dimension(:, :), allocatable :: triu_int64 integer(int64), dimension(:, :), intent(in) :: A integer, intent(in), optional :: k end function triu_int64 module function triu_sp(A, k) real(sp), dimension(:, :), allocatable :: triu_sp real(sp), dimension(:, :), intent(in) :: A integer, intent(in), optional :: k end function triu_sp module function triu_dp(A, k) real(dp), dimension(:, :), allocatable :: triu_dp real(dp), dimension(:, :), intent(in) :: A integer, intent(in), optional :: k end function triu_dp module function triu_csp(A, k) complex(sp), dimension(:, :), allocatable :: triu_csp complex(sp), dimension(:, :), intent(in) :: A integer, intent(in), optional :: k end function triu_csp module function triu_cdp(A, k) complex(dp), dimension(:, :), allocatable :: triu_cdp complex(dp), dimension(:, :), intent(in) :: A integer, intent(in), optional :: k end function triu_cdp end interface triu !> Version: experimental !> !> Creates a rank-1 or rank-2 array filled zeros. !> ([Specification](../page/specs/forlab_linalg.html#zerosones)) interface zeros procedure :: zeros_1_default procedure :: zeros_2_default end interface zeros contains function rmut_sp(m1, m2) result(res) !! complex(dp) matrix multiplication real(sp), intent(in) :: m1(:, :), m2(:, :) real(sp) :: res(size(m1, 1), size(m2, 2)) if (size(m1, 2) == size(m2, 1)) then res = matmul(m1, m2) else call error_stop('Error: size(matrix_1, 2) /= size(matrix_2, 1)') end if end function rmut_sp function rmut_dp(m1, m2) result(res) !! complex(dp) matrix multiplication real(dp), intent(in) :: m1(:, :), m2(:, :) real(dp) :: res(size(m1, 1), size(m2, 2)) if (size(m1, 2) == size(m2, 1)) then res = matmul(m1, m2) else call error_stop('Error: size(matrix_1, 2) /= size(matrix_2, 1)') end if end function rmut_dp function cmut_sp(m1, m2) result(res) !! complex(dp) matrix multiplication complex(sp), intent(in) :: m1(:, :), m2(:, :) complex(sp) :: res(size(m1, 1), size(m2, 2)) if (size(m1, 2) == size(m2, 1)) then res = matmul(m1, m2) else call error_stop('Error: size(matrix_1, 2) /= size(matrix_2, 1)') end if end function cmut_sp function cmut_dp(m1, m2) result(res) !! complex(dp) matrix multiplication complex(dp), intent(in) :: m1(:, :), m2(:, :) complex(dp) :: res(size(m1, 1), size(m2, 2)) if (size(m1, 2) == size(m2, 1)) then res = matmul(m1, m2) else call error_stop('Error: size(matrix_1, 2) /= size(matrix_2, 1)') end if end function cmut_dp function rcmut_sp(m1, m2) result(res) !! complex(dp) matrix multiplication real(sp), intent(in) :: m1(:, :) complex(sp), intent(in) :: m2(:, :) complex(sp) :: res(size(m1, 1), size(m2, 2)) if (size(m1, 2) == size(m2, 1)) then res = matmul(m1, m2) else call error_stop('Error: size(matrix_1, 2) /= size(matrix_2, 1)') end if end function rcmut_sp function rcmut_dp(m1, m2) result(res) !! complex(dp) matrix multiplication real(dp), intent(in) :: m1(:, :) complex(dp), intent(in) :: m2(:, :) complex(dp) :: res(size(m1, 1), size(m2, 2)) if (size(m1, 2) == size(m2, 1)) then res = matmul(m1, m2) else call error_stop('Error: size(matrix_1, 2) /= size(matrix_2, 1)') end if end function rcmut_dp function crmut_sp(m1, m2) result(res) !! complex(dp) matrix multiplication complex(sp), intent(in) :: m1(:, :) real(sp), intent(in) :: m2(:, :) complex(sp) :: res(size(m1, 1), size(m2, 2)) if (size(m1, 2) == size(m2, 1)) then res = matmul(m1, m2) else call error_stop('Error: size(matrix_1, 2) /= size(matrix_2, 1)') end if end function crmut_sp function crmut_dp(m1, m2) result(res) !! complex(dp) matrix multiplication complex(dp), intent(in) :: m1(:, :) real(dp), intent(in) :: m2(:, :) complex(dp) :: res(size(m1, 1), size(m2, 2)) if (size(m1, 2) == size(m2, 1)) then res = matmul(m1, m2) else call error_stop('Error: size(matrix_1, 2) /= size(matrix_2, 1)') end if end function crmut_dp function is_square_rsp(A) result(is_square) !! real(sp) matrix is square or not. real(sp), intent(in) :: A(:, :) logical :: is_square is_square = .false. if (size(A, 1) == size(A, 2)) is_square = .true. return end function is_square_rsp function is_square_rdp(A) result(is_square) !! real(dp) matrix is square or not. real(dp), intent(in) :: A(:, :) logical :: is_square is_square = .false. if (size(A, 1) == size(A, 2)) is_square = .true. return end function is_square_rdp function is_square_csp(A) result(is_square) !! complex(sp) matrix is square or not. complex(sp), intent(in) :: A(:, :) logical :: is_square is_square = .false. if (size(A, 1) == size(A, 2)) is_square = .true. return end function is_square_csp function is_square_cdp(A) result(is_square) !! complex(dp) matrix is square or not. complex(dp), intent(in) :: A(:, :) logical :: is_square is_square = .false. if (size(A, 1) == size(A, 2)) is_square = .true. return end function is_square_cdp function is_symmetric_rsp(A) result(is_symmetric) !! real(sp) matrix is symmetric or not. real(sp), intent(in) :: A(:, :) logical :: is_symmetric integer :: i, j, n is_symmetric = .true. if (.not. is_square(A)) then is_symmetric = .false. return else n = size(A, 1) do i = 1, n do j = 1, n if (A(i, j) .ne. A(j, i)) then is_symmetric = .false. return end if end do end do end if return end function is_symmetric_rsp function is_symmetric_rdp(A) result(is_symmetric) !! real(dp) matrix is symmetric or not. real(dp), intent(in) :: A(:, :) logical :: is_symmetric integer :: i, j, n is_symmetric = .true. if (.not. is_square(A)) then is_symmetric = .false. return else n = size(A, 1) do i = 1, n do j = 1, n if (A(i, j) .ne. A(j, i)) then is_symmetric = .false. return end if end do end do end if return end function is_symmetric_rdp function is_symmetric_csp(A) result(is_symmetric) !! complex(sp) matrix is symmetric or not. complex(sp), intent(in) :: A(:, :) logical :: is_symmetric integer :: i, j, n is_symmetric = .true. if (.not. is_square(A)) then is_symmetric = .false. return else n = size(A, 1) do i = 1, n do j = 1, n if (A(i, j) .ne. A(j, i)) then is_symmetric = .false. return end if end do end do end if return end function is_symmetric_csp function is_symmetric_cdp(A) result(is_symmetric) !! complex(dp) matrix is symmetric or not. complex(dp), intent(in) :: A(:, :) logical :: is_symmetric integer :: i, j, n is_symmetric = .true. if (.not. is_square(A)) then is_symmetric = .false. return else n = size(A, 1) do i = 1, n do j = 1, n if (A(i, j) .ne. A(j, i)) then is_symmetric = .false. return end if end do end do end if return end function is_symmetric_cdp function trace_sp(A) result(trace) real(sp), dimension(:, :), intent(in) :: A real(sp) :: trace trace = sum(diag(A)) end function trace_sp function trace_dp(A) result(trace) real(dp), dimension(:, :), intent(in) :: A real(dp) :: trace trace = sum(diag(A)) end function trace_dp !> `ones` creates a rank-1 array, filled completely with `1` `integer` type values. pure function ones_1_default(dim) result(result) integer, intent(in) :: dim integer(kind=int8), allocatable :: result(:) allocate (result(dim), source=1_int8) end function ones_1_default !> `ones` creates a rank-2 array, filled completely with `1` `integer` type values. pure function ones_2_default(dim1, dim2) result(result) integer, intent(in) :: dim1, dim2 integer(kind=int8), allocatable :: result(:, :) allocate (result(dim1, dim2), source=1_int8) end function ones_2_default !> `zeros` creates a rank-1 array, filled completely with `0` `integer` type values. pure function zeros_1_default(dim) result(result) integer, intent(in) :: dim integer(kind=int8), allocatable :: result(:) allocate (result(dim), source=0_int8) end function zeros_1_default !> `zeros` creates a rank-2 array, filled completely with `0` `integer` type values. pure function zeros_2_default(dim1, dim2) result(result) integer, intent(in) :: dim1, dim2 integer(kind=int8), allocatable :: result(:, :) allocate (result(dim1, dim2), source=0_int8) end function zeros_2_default end module forlab_linalg