Modern OO Features

Salvatore Filippone

School of Aerospace, Transport and Manufacturing, [email protected]

IT4I, Ostrava, April 2016

S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 1 / 25 Preface

Premature optimization is the root of all evil — Donald Knuth Write 80% of your source code with yourself and your fellow programmers in mind, i.e. to make your life easier, not your computers life easier. The CPU will never read your source code without an interpreter or compiler anyway. Arcane or quirky constructs and names to impress upon the CPU the urgency or seriousness of your task might well get lost in the translation.

S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 2 / 25 Preface

Procedural programming is like an N-body problem — Lester Dye

“The overwhelming amount of time spent in maintenance and debugging is on finding bugs and taking the time to avoid unwanted side effects. The actual fix is relatively short!” – Shalloway & Trott, Design Patterns Explained, 2002.

S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 3 / 25 OOP – Recap

By widely held “received wisdom”, Object-Oriented Programming emphasizes the following features: 1 Encapsulation 2 Inheritance 3 Polymorphism All three are supported by Fortran.

S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 4 / 25 OOP nomenclature

Fortran C++ General Extensible derived type Class Abstract data type Component Data member Attribute class Base class pointer Dynamic Polymorphism Type guarding (select type) RTTI (dynamic cast) Type-bound procedure Virtual Member functions Method, operation* Parent type Base class Parent class Extended type Subclass Child class Module Namespace Package Generic interface Function overloading Static polymorphism Final Procedure Destructor Defined operator Overloaded operator Defined assignment Overloaded assignment Deferred procedure binding Pure virtual member function Abstract method Procedure interface Function prototype Procedure signature Intrinsic type/procedure Primitive type/procedure Built-in type procedure

S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 5 / 25 Encapsulation: Type-bound procedures

The first tenet of OOP is encapsulation: Package data, and bring the code (method) close to the data (object)

The Fortran concepts for this are derived types (which we have already seen) and type-bound procedures.

function greet(this) result(message) module astronaut_class class(astronaut), intent(in):: this implicit none character(len=max_string_length):: message private ! Hide everything by default message= this%greeting public:: astronaut ! Expose type & constructor end function integer,parameter:: max_string_length=100 end module type astronaut private program oo_hello_world character(len=max_string_length):: greeting use astronaut_class ,only : astronaut contains type(astronaut) :: pilot procedure:: greet ! Public by default pilot= astronaut(’Hello, world!’) end type print*, pilot%greet() contains end program

S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 6 / 25 Encapsulation: Type-bound procedures

Features of type-bound procedures: The name by which the procedure is invoked; The object on which it is invoked; The visibility; The extensibility (to be further explored later); Generic type-bound procedures

S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 7 / 25 Encapsulation: Type-bound procedures

contains module psb_base_mat_mod type:: psb_base_sparse_mat function psb_base_get_fmt() result(res) !> Row size implicit none integer(psb_ipk_), private::m character(len=5) :: res !> Col size res= ’NULL’ integer(psb_ipk_), private::n end function psb_base_get_fmt !> Matrix state: ! integer(psb_ipk_), private:: state integer(psb_ipk_), private:: duplicate function psb_base_get_nrows(a) result(res) logical, private:: triangle implicit none logical, private:: upper class(psb_base_sparse_mat), intent(in)::a logical, private:: unitd integer(psb_ipk_):: res logical, private:: sorted res= a%m logical, private:: repeatable_updates=.false. end function psb_base_get_nrows

contains function psb_base_get_ncols(a) result(res) implicit none procedure, pass(a):: get_nrows => psb_base_get_nrows class(psb_base_sparse_mat), intent(in)::a procedure, pass(a):: get_ncols => psb_base_get_ncols integer(psb_ipk_):: res procedure, nopass:: get_fmt => psb_base_get_fmt res= a%n end function psb_base_get_ncols end type psb_base_sparse_mat end module psb_base_mat_mod

S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 8 / 25 Encapsulation: Type-bound procedures

Type-bound procedures can be generic

type:: psb_base_sparse_mat ...... contains procedure, pass(a):: transp_1mat => psb_base_transp_1mat procedure, pass(a):: transp_2mat => psb_base_transp_2mat generic, public:: transp => transp_1mat, transp_2mat end type psb_base_sparse_mat

contains

psb_base_transp_1mat(a) class(psb_base_sparse_mat), intent(inout)::a integer(psb_ipk_):: itmp itmp= a%m a%m= a%n a%n= itmp a%triangle= a%triangle a%upper=.not.a%upper end subroutine psb_base_transp_1mat

subroutine psb_base_transp_2mat(a,b) class(psb_base_sparse_mat), intent(in)::a class(psb_base_sparse_mat), intent(out)::b b%m= a%n b%n= a%m b%triangle= a%triangle b%upper=.not.a%upper end subroutine psb_base_transp_2mat

S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 9 / 25 Inheritance: extending types

The second tenet of OOP is inheritance: Embrace and extend existing types

type:: speaker

contains procedure(talk) ,deferred:: speak end type

abstract interface function talk(this) result(message) import:: speaker,msg_max_length class(speaker) ,intent(in):: this !character(:) ,allocatable :: message character(len=msg_max_length):: message end function end interface S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 10 / 25 Inheritance: extending types

type,extends(speaker):: astronaut private character(len=msg_max_length):: greeting contains procedure:: speak => greet end type contains function greet(this) result(message) class(astronaut) ,intent(in):: this character(len=msg_max_length):: message message= this%greeting end function

S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 11 / 25 Inheritance: extending types

Rules: The extended type implicitly has all the comoponents of the parent type; The extended type implicitly has the parent type as a component; The extended type implicitly gets all of the methods of the parent type; You should only ever override specific procedures, generics work automatically

S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 12 / 25 Polymorphism: static and dynamic

The third tenet of OOP is polymorphism: Object instances may have different types Comes in two main varieties: Static polymorphism: the actual type can be resolved at compile time; Dynamic polymorphism: the actual type can only be resolved at runtime. Static polymorphism corresponds to the resolution of generic interfaces; we have already seen this in Fortran 95.

S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 13 / 25 Morpheus: Greek god of dreams

S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 14 / 25 Polymorphism

Dynamic polymorphism is signalled by the CLASS keyword; a polymorphic entity must be either A dummy argument; A variable with the ALLOCATABLE attribute; A variable with the POINTER attribute; Examples: type point real:: x,y end type point type(point):: vp class(point), pointer:: pp

pp => vp

S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 15 / 25 Polymorphism

A polymorphic variable may get its type by: The actual argument passed to a subroutine; The association between a pointer and a target; Specifying explicitly a type in an ALLOCATE statement. class(base_type), allocatable:: item .... allocate(extended_type:: item) Specifying a SOURCE or MOLD in the ALLOCATE statement. type(extended_type):: foo class(base_type), allocatable:: item .... allocate(item,source=foo)

S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 16 / 25 Polymorphism

Fine points: The CLASS specifier must appear for the passed object in all type-bound procedures (except those marked as FINAL); The CLASS specifier may or may not appear for other variables; Through a polymorphic variable you can only invoke methods of the declared type

S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 17 / 25 Polymorphism

The SELECT TYPE (aka type guard) construct allows fine discrimination among related types subroutine print_particle(p) class(particle)::p

call print_vector(’position’,p%position()) call print_vector(’momentum’,p%momentum())

select type (p) type is (charged_particle) print*,’Charge is:’,p%charge() class is (charged_particle) print*,’Charge is:’,p%charge() print*,’May have other features ’ type is (particle) print*,’Base particle type, nothing special ’ class default print*,’Unknown particle type’ end select end subroutine print_particle S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 18 / 25 Type inquiry functions

extends type of(a,b) True if the type of a is an extension of the type of b same type as(a,b) True if the type of a is an extension of the type of b

S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 19 / 25 The parent type component

type:: psb_base_sparse_mat ...... contains procedure, pass(a):: transp_1mat => psb_base_transp_1mat procedure, pass(a):: transp_2mat => psb_base_transp_2mat generic, public:: transp => transp_1mat, transp_2mat end type psb_base_sparse_mat

type, extends(psb_d_base_sparse_mat):: psb_d_coo_sparse_mat

contains procedure, pass(a):: transp_1mat => d_coo_transp_1mat end type

S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 20 / 25 The parent type component

subroutine d_coo_transp_1mat(a) implicit none class(psb_d_coo_sparse_mat), intent(inout)::a

integer(psb_ipk_), allocatable:: itemp(:) integer(psb_ipk_):: info

call a%psb_d_base_sparse_mat%transp() call move_alloc(a%ia,itemp) call move_alloc(a%ja,a%ia) call move_alloc(itemp,a%ja)

call a%set_sorted(.false.) call a%set_sort_status(psb_unsorted_) return end subroutine d_coo_transp_1mat

S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 21 / 25 abstract and deferred

A type can be defined as abstract, in which case it cannot be instantiated directly type, abstract:: file_handle contains procedure(open_file) , deferred, pass(handle):: open end type file_handle

abstract interface subroutine open_file(handle) import class(file_handle), intent(inout):: handle end subroutine open_file end interface

S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 22 / 25 Finalization If your data type requires specific cleanup upon deallocation, you can define your own method with the final keyword: type, extends(psb_d_ell_sparse_mat):: psb_d_elg_sparse_mat type(c_ptr):: deviceMat= c_null_ptr

contains final:: d_elg_finalize end type psb_d_elg_sparse_mat

......

subroutine d_elg_finalize(a) use elldev_mod implicit none type(psb_d_elg_sparse_mat), intent(inout)::a

if(c_associated(a%deviceMat)) & & call freeEllDevice(a%deviceMat) a%deviceMat= c_null_ptr end subroutine d_elg_finalize

S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 23 / 25 Style guidelines

1 Write code that comments itself: type(gas):: air real, parameter:: viscosity=1.52E-05 ! meters/sec if(.not.readFromDisk(air)) air= constructGas(viscosity) 2 Name all constants; 3 Make constants constant (parameter attribute); 4 Minimize global data; 5 Make global data constant; 6 Provide global type parameters, including precision specification;

S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 24 / 25 Style guidelines

7 Provide (conditional) debugging; 8 Declare INTENT for all arguments; 9 Avoid side effects, especially in FUNCTION 10 Make components PRIVATE 11 Use indentation (consistently) 12 Always prevent implicit typing

S. Filippone (SATM) Modern Fortran OO Features IT4I, Ostrava, 2016 25 / 25