Skip to content

Instantly share code, notes, and snippets.

@sacko87
Last active August 16, 2017 13:45
Show Gist options
  • Save sacko87/b4ce0aa3755bb8b37616d609268628d0 to your computer and use it in GitHub Desktop.
Save sacko87/b4ce0aa3755bb8b37616d609268628d0 to your computer and use it in GitHub Desktop.
Consolidating my fortran knowledge into to one easily manageable Gist.
program allocate
implicit none
! an allocatable array of integers
integer, allocatable :: numbers(:)
! some variables
integer :: n, err, i = 0
do
! how many elements?
n = howmany()
! a negative integer will exit the program
if (n < 0) then
exit
end if
! allocate n elements
allocate(numbers(n), STAT=err)
! did we succeed in allocation?
if (err == 0) then
! prove the array is the size we wanted
print *, 'array has ', SIZE(numbers), ' elements.'
! loop through them and assign decrementing values
do i = 1, SIZE(numbers)
numbers(i) = SIZE(numbers) - i
end do
! loop through them and print those numbers
do i = 1, SIZE(numbers)
print *, numbers(i)
end do
! deallocate the array
deallocate(numbers)
else
! we couldn't get any space for some reason or another
print *, "couldn't allocate space for ", n, " integers."
end if
end do
! lets define a function
contains
! how many elements?
integer function howmany()
implicit none
! some variables
integer :: n, err
do ! forever...
print *, "how many elements? (-1 to quit)"
! 5 = stdin
read (5, *, iostat=err) n
! did we get a valid integer?
if(err /= 0) then
! no
print *, err
print *, "you haven't given me an integer."
else
! yes
howmany = n
exit ! we may break out of the loop
end if
end do
end function howmany
end program allocate
! create a multiplication module
module multiplication
implicit none
contains
! define a multiple function a -> a -> a
! a pure function is one without side effects
real pure function multiply(x, y)
implicit none
! pure requires us to say that the inputs are 'final'
real, intent(in) :: x, y
multiply = x * y ! the work
end function multiply
! elemental is a pure method that can be applied to an array
! a -> b .OR. (a -> b) -> [ a ] -> [ b ]
real elemental function multiply_(x, y)
implicit none
! pure requires us to say that the inputs are 'final'
real, intent(in) :: x, y
multiply_ = x * y ! the work
end function multiply_
! attempt delegation
real elemental function double(x)
implicit none
! pure requires us to say that the inputs are 'final'
real, intent(in) :: x
double = multiply(x, 2.0) ! the work
end function double
end module multiplication
! create a sub routine
subroutine swap(x, y)
implicit none
! state that x and y will change
! intent(inout) is important, it tells the compiler that
! we will write to the addresses given, so only variables are allowed
real, intent(inout) :: x, y
real :: z ! temporary variable
! the swap
z = x
x = y
y = z
end subroutine swap
! create a function outside of a module
real elemental function divide(x, y)
implicit none
real, intent(in) :: x, y
divide = x / y
end function divide
! create a function that calls another outside of a module
real elemental function half(x)
implicit none
real, intent(in) :: x
! we need to explicitlty define the interface of the
! divide method
interface
real elemental function divide(x, y)
real, intent(in) :: x, y
end function divide
end interface
! delegate
half = divide(x, 2.0)
end function half
! my program
program basic
! using my module
use multiplication
! we don't want implicity
implicit none
! the program
! for the swap
real :: x = 4, y = 10
! for the elemental testing
real, dimension(3) :: z = (/ 1.0, 2.0, 3.0 /), a = (/ 10.0, 20.0, 30.0 /)
! define the functions outside of my module
interface
real elemental function half(x)
real, intent(in) :: x
end function half
real elemental function divide(x, y)
real, intent(in) :: x, y
end function divide
end interface
print *, x, y
call swap(x, y) ! call a subroutine
print *, x, y
! test using a value
print *, double(3.0)
print *, multiply(3.0, 5.0)
print *, half(3.0)
print *, divide(3.0, 3.0)
! test using an array of values
print *, z
print *, double(z)
! use a builtin, PI!
print *, 4.0*atan(1.0)
print *, multiply_(z, a)
print *, multiply_(z, 2.0) ! oh wow, this is cool
! try a recursive function
print *, factorial(4)
print *, factorial(5)
contains
! a recursive function with delegation within a module/program
recursive integer pure function factorial(x) result(y)
integer, intent(in) :: x ! pure again so final
! a conditional
if (x == 1) then
y = 1
else
! casting is needed, both for parameters and then for the return
! factorial returns an integer, but multiply receives and takes reals
y = int(multiply(real(x), real(factorial(x - 1))))
end if
end function factorial
end program basic
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment