Fortran notes, Overloading & custom operators & inheriting Module

Reference: Peng Guolun: Fortran 95 programming, 2002, Chapter 11

catalogue

1. overload

2. User defined operator

3. Inherit Module

1. overload

Concept: functions with the same function name but different parameter types and numbers. The program will automatically decide which function to call according to the input parameters.

Implementation: use the interface to define a virtual function (the so-called same function name), and give the implementation method of the virtual function (i.e. the specific implementation of functions with different parameter types and numbers).

Example:

module mod_show
    implicit none
    
    ! Function overloading 
    interface show
        module procedure show_int
        module procedure show_character
    end interface
    
contains

subroutine show_int(n)
    implicit none
    integer :: n
    write(*,*) n
end subroutine show_int
    
subroutine show_character(string)
implicit none
    character(len=*) :: string
    write(*,*) TRIM(string)
end subroutine show_character
    
end module

program case_overload
use mod_show
implicit none
    call show(333)
    call show("666")
stop
end program

Combined with the example analysis, the virtual function is show. It has two versions. One is that the input parameter type is integer and the other is characterer (len = *). In fact, there is no requirement for the function name currently used, as long as it can correspond to the function name in the interface.

Note that Fortran does not encapsulate the specific implementation of overloaded functions. That is to say, it is not allowed to restrict the specific functions through private. In the use module, you can also directly call the specific implementation function (here is show_int())_ character()).

2. User defined operator

The implementation of custom operators is similar to function overloading, which needs to be completed through the interface. The application scenarios of custom operators here are mostly for custom types.

Example:

module time_util
	implicit none

	! Custom time data structure
	type :: time
		integer :: hour, minute
	end type time

	! For custom data structures+of interface
	interface operator(+)
		module procedure add_time
	end interface

	contains

function add_time(a, b)
	implicit none
		! variables
		type(time), intent(in) :: a, b
		!type(time) :: a, b
		type(time) :: add_time
		
		! function body
		add_time%hour = a%hour + b%hour
		add_time%minute = a%minute + b%minute
		add_time%hour = add_time%hour + add_time%minute/60
		add_time%minute = mod(add_time%minute, 60)
		
		return
end function add_time
	
subroutine show_time(a)
    implicit none
        type(time), intent(in) :: a
        
        write(*, "(I2, ':', I2)") a%hour, a%minute
end subroutine

end module


program Chapter11
use time_util
implicit none

    ! Variables
    character(len=20) :: dates, times
    type(time) :: time_mon, time_tue, time_total
	
	time_mon = time(1, 45)
    time_tue = time(2, 18)
    
    time_total = time_mon + time_tue
    call show_time(time_total)
	
	stop
end program

The difference between user-defined operators and function overloading is that the interface is followed by operator (+). Here, take + as an example.

be careful:

For the function to be implemented, the intent of each parameter attribute must be specified.

Function is mostly used here, not subroutine. An unwritten rule in Fortran: for the parameter passed to function, just read its value and don't change its data. This also means that it is usually intent(in)
 

The above only realizes the addition of user-defined types (time), and can also further realize the addition of time and real.

The code is as follows:

module time_util
	implicit none

	! Custom time data structure
	type :: time
		integer :: hour, minute
	end type time

	! For custom data structures+of interface
	interface operator(+)
		module procedure add_time
		module procedure add_real
	end interface

	contains

function add_time(a, b)
	implicit none
		! variables
		type(time), intent(in) :: a, b
		!type(time) :: a, b
		type(time) :: add_time
		
		! function body
		add_time%hour = a%hour + b%hour
		add_time%minute = a%minute + b%minute
		add_time%hour = add_time%hour + add_time%minute/60
		add_time%minute = mod(add_time%minute, 60)
		
		return
end function add_time

function add_real(a, num_real)
    implicit none
        ! variables
        type(time), intent(in) :: a
        real, intent(in) :: num_real   ! integer Can be cast to real???
        type(time) :: b     ! local variable
        
        type(time) :: add_real
        
        ! function body
        ! even if function real2time It's OK to write it at the back
        b = real2time(num_real)
        
        add_real%hour = a%hour + b%hour
        add_real%minute = a%minute + b%minute
        add_real%hour = add_real%hour + add_real%minute/60
        add_real%minute = mod(add_real%minute, 60)
        
        return
end function add_real
    
! take real Convert to time
function real2time(num_real)
implicit none
        ! variables
        real, intent(in) :: num_real
        type(time) :: real2time
        
        ! function body
        ! adopt int()Explicitly cast floating-point type, whether there is rounding
        ! real2time%hour = int(num_real)
        ! time in hour by integer,Implicit conversion
        ! real2time%hour = num_real
        real2time%hour = num_real/1
        
        ! Convert decimals to minutes
        ! If there are decimals, they shall be rounded off and omitted temporarily
        ! ... ...        
        real2time%minute = mod(num_real, 1.0)*60
        
        return
end function
	
subroutine show_time(a)
    implicit none
        type(time), intent(in) :: a
        
        write(*, "(I2, ':', I2)") a%hour, a%minute
end subroutine

end module


program Chapter11
use time_util
implicit none

    ! Variables
    character(len=20) :: dates, times
    type(time) :: time_mon, time_tue, time_total
	
	time_mon = time(1, 45)
    time_tue = time(2, 18)
    
    time_total = time_mon + time_tue
    call show_time(time_total)
	
	time_total = time_tue + 1.5
    call show_time(time_total)
	
	stop
end program

The output result is:

 4: 3
 3:48

In addition, you can also define multiple manipulation symbols in the same interface.

The syntax is as follows:

interface operator(+) or (-) or (*)
	module procedure add_time
	module procedure minus_time
	module procedure multi_time
end interface

Not much. What should we do to realize multiple addition at this time?

3. Inherit Module

Inheritance in Fortran is also very simple. Roughly speaking, it is in mod_ Use mod in B_ a,mod_b inherits mod_a all public variables and functions.

Doubts during the practice:

In mod_ Use mod in B_ a. Use mod in program_ b. Can mod be used in program_ What about the variables or functions disclosed in a?

Answer: Yes! (? Most programming languages that implement inheritance are designed this way?)

Example:

module mod_a
    implicit none
    
    integer :: ma = 10
    
    contains
subroutine mod_a_SoberHi()
        write(*,*) "Sober Hi From mod_a"
end subroutine mod_a_SoberHi

end module mod_a
    
module mod_b
    use mod_a
    implicit none
	
    integer :: mb = 20
    
	contains
subroutine mod_b_SoberHi()
        write(*,*) "Sober Hi From mod_b"
end subroutine mod_b_SoberHi
    
end module mod_b


program case_inherit
    use mod_b
    
    call mod_a_SoberHi()
    call mod_b_SoberHi()
    
    write(*, *) ma
    write(*, *) mb
	
	stop
end program case_inherit

Output result:

 Sober Hi From mod_a
 Sober Hi From mod_b
          10
          20

Keywords: fortran

Added by runawaykinms on Sat, 19 Feb 2022 23:40:09 +0200