Last active
August 16, 2017 13:45
-
-
Save sacko87/b4ce0aa3755bb8b37616d609268628d0 to your computer and use it in GitHub Desktop.
Consolidating my fortran knowledge into to one easily manageable Gist.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
! 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