File: template_lapack_01.f90

package info (click to toggle)
lfortran 0.45.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 46,332 kB
  • sloc: cpp: 137,068; f90: 51,260; python: 6,444; ansic: 4,277; yacc: 2,285; fortran: 806; sh: 524; makefile: 30; javascript: 15
file content (115 lines) | stat: -rw-r--r-- 3,979 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
module template_lapack_01_m
    implicit none
    private
    public :: test_template

    requirement gemm_r(T, gemm)
        type, deferred :: T
        subroutine gemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
            character, intent(in) :: transa, transb
            integer, intent(in) :: m, n, k, lda, ldb, ldc
            type(T), intent(in) :: alpha, a(lda, *), b(ldb, *), beta
            type(T), intent(out) :: c(ldc, *)
        end subroutine
    end requirement

    requirement cast_r(T, U, cast)
        type, deferred :: T
        type, deferred :: U
        pure elemental function cast(arg) result(res)
            type(T), intent(in) :: arg
            type(U) :: res
        end function
    end requirement

    template external_matmul_t(T, gemm, cast_to_T)
        require :: gemm_r(T, gemm)
        require :: cast_r(real, T, cast_to_T)
        private
    contains
        function nonsimple_external_matmul(a,b) result(c)
            type(T), intent(in) :: a(:,:), b(:,:)
            type(T) :: c(size(a,1), size(b,2))
            integer :: m, n, k
            m = size(a, dim=1)
            n = size(b, dim=2)
            k = size(a, dim=1)
            call gemm('n', 'n', m, n, k, cast_to_T(1.0), a, m, b, k, cast_to_T(0.0), c, m)
        end function
    end template

contains

    subroutine my_gemm_real(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
        character, intent(in) :: transa, transb
        integer, intent(in) :: m, n, k, lda, ldb, ldc
        real, intent(in) :: alpha, a(lda, *), b(ldb, *), beta
        real, intent(out) :: c(ldc, *)
    end subroutine

    subroutine my_gemm_double(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
        integer, parameter :: dp = kind(1.d0)
        character, intent(in) :: transa, transb
        integer, intent(in) :: m, n, k, lda, ldb, ldc
        real(dp), intent(in) :: alpha, a(lda, *), b(ldb, *), beta
        real(dp), intent(out) :: c(ldc, *)
    end subroutine

    pure elemental function my_cast_to_real(a) result(b)
        real, intent(in) :: a
        real :: b
        b = a
    end function

    pure elemental function my_cast_to_double(a) result(b)
        integer, parameter :: dp = kind(1.d0)
        real, intent(in) :: a
        real(dp) :: b
        b = a
    end function

    function my_external_matmul(a, b) result(c)
        real, intent(in) :: a(:,:), b(:,:)
        real :: c(size(a,1), size(b,2))
        integer :: m, n, k
        m = size(a, dim=1)
        n = size(b, dim=2)
        k = size(a, dim=1)
        call my_gemm_real('n', 'n', m, n, k, my_cast_to_real(1.0), a, m, b, k, my_cast_to_real(0.0), c, m)
    end function

    function simple_external_matmul {T, gemm, cast_to_T} (a, b) result(c)
        require :: gemm_r(T, gemm)
        require :: cast_r(real, T, cast_to_T)
        type(T), intent(in) :: a(:,:), b(:,:)
        type(T) :: c(size(a,1), size(b,2))
        integer :: m, n, k
        m = size(a, dim=1)
        n = size(b, dim=2)
        k = size(a, dim=1)
        call gemm('n', 'n', m, n, k, cast_to_T(1.0), a, m, b, k, cast_to_T(0.0), c, m)
    end function

    subroutine test_template()
        integer, parameter :: dp = kind(1.d0)
        instantiate external_matmul_t(real, my_gemm_real, my_cast_to_real), &
            only: nonsimple_external_matmul_real => nonsimple_external_matmul
        instantiate external_matmul_t(real(dp), my_gemm_double, my_cast_to_double), &
            only: nonsimple_external_matmul_double => nonsimple_external_matmul
        
        real :: asp(2,2), bsp(2,2), csp(2,2)
        real(dp) :: adp(2,2), bdp(2,2), cdp(2,2)

        csp = simple_external_matmul {real, my_gemm_real, my_cast_to_real} (asp, bsp)
        cdp = simple_external_matmul {real(dp), my_gemm_double, my_cast_to_double} (adp, bdp)
    end subroutine

end module

program template_lapack_01
use template_lapack_01_m
implicit none

call test_template()

end program