Skip to content

feat: extend intrinsic matmul #951

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f06f556
add interface and procedures
wassup05 Mar 13, 2025
fed4d73
add implementation for 3,4,5 matrices
wassup05 Mar 13, 2025
27911ae
add very basic example
wassup05 Mar 13, 2025
a7f645c
fix typo
wassup05 Mar 13, 2025
cc77dee
a bit efficient
wassup05 Mar 14, 2025
3958018
refactor algorithm
wassup05 Mar 14, 2025
35a5a28
add new interface
wassup05 Mar 14, 2025
ebf92d7
add helper functions
wassup05 Mar 14, 2025
5f5c5a9
add implementation, refactor select to if clauses
wassup05 Mar 15, 2025
06ce735
slightly better examples
wassup05 Mar 15, 2025
e709f83
replace all matmul's by gemm
wassup05 Mar 20, 2025
cf5f030
add error handling in a better way
wassup05 Apr 4, 2025
b6d07e6
Update src/stdlib_intrinsics_matmul.fypp
perazz Apr 22, 2025
5e3b588
Update src/stdlib_intrinsics_matmul.fypp
perazz Apr 22, 2025
7d2130a
Update src/stdlib_intrinsics_matmul.fypp
perazz Apr 22, 2025
61851fc
Update src/stdlib_intrinsics_matmul.fypp
perazz Apr 22, 2025
ee7da8d
Update src/stdlib_intrinsics_matmul.fypp
perazz Apr 22, 2025
195c57e
Update src/stdlib_intrinsics_matmul.fypp
perazz Apr 22, 2025
e71b9bb
Update src/stdlib_intrinsics_matmul.fypp
perazz Apr 22, 2025
00c4461
Update src/stdlib_intrinsics_matmul.fypp
perazz Apr 22, 2025
5c2bbc5
Update src/stdlib_intrinsics_matmul.fypp
perazz Apr 22, 2025
79113da
Update src/stdlib_intrinsics_matmul.fypp
perazz Apr 22, 2025
72dc641
added specs
wassup05 May 20, 2025
cee5bba
added tests
wassup05 May 20, 2025
a052599
modified example and slight changes
wassup05 May 20, 2025
24c5787
Merge branch 'fortran-lang:master' into matmul
wassup05 May 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion doc/specs/stdlib_intrinsics.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,42 @@ The output is a scalar of the same type and kind as to that of `x` and `y`.

```fortran
{!example/intrinsics/example_dot_product.f90!}
```
```

### `stdlib_matmul` function

#### Description

The extension of the intrinsic function `matmul` to handle more than 2 and less than or equal to 5 matrices, with error handling using `linalg_state_type`.
The optimal parenthesization to minimize the number of scalar multiplications is done using the Algorithm as outlined in Cormen, "Introduction to Algorithms", 4ed, ch-14, section-2.
The actual matrix multiplication is performed using the `gemm` interfaces.
It supports only `real` and `complex` matrices.

#### Syntax

`res = ` [[stdlib_intrinsics(module):stdlib_matmul(interface)]] ` (m1, m2, m3, m4, m5, err)`

#### Status

Experimental

#### Class

Function.

#### Argument(s)

`m1`, `m2`: 2D arrays of the same kind and type. `intent(in)` arguments.
`m3`,`m4`,`m5`: 2D arrays of the same kind and type as the other matrices. `intent(in), optional` arguments.
`err`: `type(linalg_state_type), intent(out), optional` argument. Can be used for elegant error handling. It is assigned `LINALG_VALUE_ERROR`
in case the matrices are not of compatible sizes.

#### Result

The output is a matrix of the appropriate size.

#### Example

```fortran
{!example/intrinsics/example_matmul.f90!}
```
3 changes: 2 additions & 1 deletion example/intrinsics/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
ADD_EXAMPLE(sum)
ADD_EXAMPLE(dot_product)
ADD_EXAMPLE(dot_product)
ADD_EXAMPLE(matmul)
12 changes: 12 additions & 0 deletions example/intrinsics/example_matmul.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
program example_matmul
use stdlib_intrinsics, only: stdlib_matmul
complex :: x(2, 2), y(2, 2), z(2, 2)
x = reshape([(0, 0), (1, 0), (1, 0), (0, 0)], [2, 2])
y = reshape([(0, 0), (0, 1), (0, -1), (0, 0)], [2, 2]) ! pauli y-matrix
z = reshape([(1, 0), (0, 0), (0, 0), (-1, 0)], [2, 2])

print *, stdlib_matmul(x, y) ! should be iota*z
print *, stdlib_matmul(y, z, x) ! should be iota*identity
print *, stdlib_matmul(x, x, z, y) ! should be -iota*x
print *, stdlib_matmul(x, x, z, y, y) ! should be z
end program example_matmul
5 changes: 3 additions & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ set(fppFiles
stdlib_hash_64bit_spookyv2.fypp
stdlib_intrinsics_dot_product.fypp
stdlib_intrinsics_sum.fypp
stdlib_intrinsics_matmul.fypp
stdlib_intrinsics.fypp
stdlib_io.fypp
stdlib_io_npy.fypp
Expand All @@ -32,14 +33,14 @@ set(fppFiles
stdlib_linalg_kronecker.fypp
stdlib_linalg_cross_product.fypp
stdlib_linalg_eigenvalues.fypp
stdlib_linalg_solve.fypp
stdlib_linalg_solve.fypp
stdlib_linalg_determinant.fypp
stdlib_linalg_qr.fypp
stdlib_linalg_inverse.fypp
stdlib_linalg_pinv.fypp
stdlib_linalg_norms.fypp
stdlib_linalg_state.fypp
stdlib_linalg_svd.fypp
stdlib_linalg_svd.fypp
stdlib_linalg_cholesky.fypp
stdlib_linalg_schur.fypp
stdlib_optval.fypp
Expand Down
44 changes: 44 additions & 0 deletions src/stdlib_intrinsics.fypp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module stdlib_intrinsics
!!Alternative implementations of some Fortran intrinsic functions offering either faster and/or more accurate evaluation.
!! ([Specification](../page/specs/stdlib_intrinsics.html))
use stdlib_kinds
use stdlib_linalg_state, only: linalg_state_type
implicit none
private

Expand Down Expand Up @@ -146,6 +147,49 @@ module stdlib_intrinsics
#:endfor
end interface
public :: kahan_kernel

interface stdlib_matmul
!! version: experimental
!!
!!### Summary
!! compute the matrix multiplication of more than two matrices with a single function call.
!! ([Specification](../page/specs/stdlib_intrinsics.html#stdlib_matmul))
!!
!!### Description
!!
!! matrix multiply more than two matrices with a single function call
!! the multiplication with the optimal parenthesization for efficiency of computation is done automatically
!! Supported data types are `real` and `complex`.
!!
!! Note: The matrices must be of compatible shapes to be multiplied
#:for k, t, s in R_KINDS_TYPES + C_KINDS_TYPES
pure module function stdlib_matmul_pure_${s}$ (m1, m2, m3, m4, m5) result(r)
${t}$, intent(in) :: m1(:,:), m2(:,:)
${t}$, intent(in), optional :: m3(:,:), m4(:,:), m5(:,:)
${t}$, allocatable :: r(:,:)
end function stdlib_matmul_pure_${s}$

module function stdlib_matmul_${s}$ (m1, m2, m3, m4, m5, err) result(r)
${t}$, intent(in) :: m1(:,:), m2(:,:)
${t}$, intent(in), optional :: m3(:,:), m4(:,:), m5(:,:)
type(linalg_state_type), intent(out) :: err
${t}$, allocatable :: r(:,:)
end function stdlib_matmul_${s}$
#:endfor
end interface stdlib_matmul
public :: stdlib_matmul

! internal interface
interface stdlib_matmul_sub
#:for k, t, s in R_KINDS_TYPES + C_KINDS_TYPES
pure module subroutine stdlib_matmul_sub_${s}$ (res, m1, m2, m3, m4, m5, err)
${t}$, intent(out), allocatable :: res(:,:)
${t}$, intent(in) :: m1(:,:), m2(:,:)
${t}$, intent(in), optional :: m3(:,:), m4(:,:), m5(:,:)
type(linalg_state_type), intent(out), optional :: err
end subroutine stdlib_matmul_sub_${s}$
#:endfor
end interface stdlib_matmul_sub

contains

Expand Down
Loading
Loading