Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented Several Numerical Integration Algorithms in maths/ #25

49 changes: 49 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
name: ci

'on':
workflow_dispatch:
push:
branches:
- main
pull_request:

env:
build_path: ${{github.workspace}}/build

jobs:
build_and_test:
runs-on: ${{matrix.os}}
strategy:
fail-fast: false
matrix:
os: [ubuntu-22.04, ubuntu-24.04]

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Display versions
run: |
gfortran --version
cmake --version

- name: Create Build Directory
run: cmake -E make_directory ${{env.build_path}}

- name: Configure CMake
working-directory: ${{env.build_path}}
run: cmake ../

- name: Build
working-directory: ${{env.build_path}}
run: cmake --build .

- name: Test
working-directory: ${{env.build_path}}
run: ctest

- name: Run examples
working-directory: ${{env.build_path}}
run: make run_all_examples
...
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@

.idea/

/build/
50 changes: 50 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
cmake_minimum_required(VERSION 3.16)
project(FortranProject LANGUAGES Fortran)

add_compile_options(-Wall -Wextra -Wpedantic)

function(add_fortran_sources DIR SOURCES)
file(GLOB_RECURSE NEW_SOURCES "${DIR}/*.f90")
list(APPEND ${SOURCES} ${NEW_SOURCES})
set(${SOURCES} ${${SOURCES}} PARENT_SCOPE)
endfunction()

set(MODULE_SOURCES)
add_fortran_sources(${CMAKE_SOURCE_DIR}/modules MODULE_SOURCES)

add_library(modules STATIC ${MODULE_SOURCES})

function(create_unique_name FILE_NAME OUTPUT_NAME)
file(RELATIVE_PATH REL_PATH "${CMAKE_SOURCE_DIR}" "${FILE_NAME}")
get_filename_component(CUR_EXT "${REL_PATH}" LAST_EXT)
string(REPLACE "/" "_" UNIQUE_NAME "${REL_PATH}")
string(REPLACE "${CUR_EXT}" "" UNIQUE_NAME "${UNIQUE_NAME}")
set(${OUTPUT_NAME} ${UNIQUE_NAME} PARENT_SCOPE)
endfunction()


file(GLOB_RECURSE TEST_FILES "${CMAKE_SOURCE_DIR}/tests/*.f90")

foreach(TEST_FILE ${TEST_FILES})
create_unique_name(${TEST_FILE} TEST_NAME)
add_executable(${TEST_NAME} ${TEST_FILE})
target_link_libraries(${TEST_NAME} modules)
add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME})
endforeach()

file(GLOB_RECURSE EXAMPLE_FILES "${CMAKE_SOURCE_DIR}/examples/*.f90")

foreach(EXAMPLE_FILE ${EXAMPLE_FILES})
create_unique_name(${EXAMPLE_FILE} EXAMPLE_NAME)
add_executable(${EXAMPLE_NAME} ${EXAMPLE_FILE})
target_link_libraries(${EXAMPLE_NAME} modules)
list(APPEND EXAMPLE_NAME_LIST run_${EXAMPLE_NAME})
add_custom_target(run_${EXAMPLE_NAME}
COMMAND ${EXAMPLE_NAME}
DEPENDS ${EXAMPLE_NAME}
COMMENT "Running example: ${EXAMPLE_NAME}")
endforeach()

enable_testing()

add_custom_target(run_all_examples DEPENDS ${EXAMPLE_NAME_LIST})
6 changes: 6 additions & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# The Algorithms - Directory of Fortran
## Maths
* numerical_integration
* [trapezoidal_rule](/modules/maths/numerical_integration/trapezoid.f90)
* [simpson_rule](/modules/maths/numerical_integration/simpson.f90)
* [midpoint_rule](/modules/maths/numerical_integration/midpoint.f90)
* [monte_carlo](/modules/maths/numerical_integration/monte_carlo.f90)
* [gauss_legendre](/modules/maths/numerical_integration/gaussian_legendre.f90)
* [euclid_gcd](/modules/maths/euclid_gcd.f90)
* [factorial](/modules/maths/factorial.f90)
* [fibonacci](/modules/maths/fibonacci.f90)
Expand Down
12 changes: 3 additions & 9 deletions examples/maths/euclid_gcd.f90
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,11 @@ program euclid_gcd_program
use gcd_module
implicit none
integer :: a, b, val
character(len=1024) :: msg
integer :: istat

print *, "Enter the two numbers (+ve integers): "
read(*, *, iostat=istat, iomsg=msg) a, b
if (istat /= 0) then
write(*, fmt='(2A)') 'error: ', trim(msg)
stop 1
end if
a = 56
b = 98

val = gcd(a, b)
print *, 'The greatest common divisor is: ', val
print *, 'The greatest common divisor of ', a, ' and ', b, ' is: ', val

end program euclid_gcd_program
4 changes: 2 additions & 2 deletions examples/maths/factorial.f90
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ program factorial_program
use factorial_module
implicit none

Print*, factorial(5)
Print*, recursive_factorial(5)
Print *, factorial(5)
Print *, recursive_factorial(5)

end program factorial_program
9 changes: 2 additions & 7 deletions examples/maths/fibonacci.f90
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,9 @@ program example_fibonacci
implicit none
integer :: n

print *, 'Enter a number: '
read *, n
if (n <= 0) then
print *, 'Number must be a positive integer.'
stop 1
end if
n = 7

print *, 'The Fibonacci number for the specified position is:'
print *, 'The Fibonacci number for the position', n, ' is:'
print *, 'Recursive solution: ', fib_rec(n)
print *, 'Iterative solution: ', fib_itr(n)

Expand Down
45 changes: 45 additions & 0 deletions examples/maths/numerical_integration/gaussian_legendre.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
!> Example Program for Gaussian-Legendre Quadrature Module
!!
!! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed)
!! in Pull Request: #25
!! https://github.com/TheAlgorithms/Fortran/pull/25
!!
!! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request
!! addressing bugs/corrections to this file. Thank you!
!!
!! This program demonstrates the use of Gaussian-Legendre Quadrature Module for numerical integration.
!!
!! It sets the integration limits and the number of quadrature points (n), and calls the
!! gauss_legendre_quadrature subroutine to compute the approximate value of the definite integral
!! of the specified function.
!!
!! Example function: f(x) = exp(-x^2) * cos(2.0_dp * x)

program example_gaussian_quadrature
use gaussian_legendre_quadrature
implicit none

real(dp) :: a, b, integral_result
integer :: n

! Set the integration limits and number of quadrature points
a = -1.0_dp
b = 1.0_dp
n = 5 !! Number of quadrature points

! Call Gaussian quadrature to compute the integral
call gauss_legendre_quadrature(integral_result, a, b, n, func)

write (*, '(A, F12.6)') "Gaussian Quadrature result: ", integral_result !! ≈ 0.858574

contains

function func(x) result(fx)
implicit none
real(dp), intent(in) :: x
real(dp) :: fx

fx = exp(-x**2)*cos(2.0_dp*x) !! Example function to integrate
end function func

end program example_gaussian_quadrature
44 changes: 44 additions & 0 deletions examples/maths/numerical_integration/midpoint.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
!> Example Program for Midpoint Rule
!!
!! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed)
!! in Pull Request: #25
!! https://github.com/TheAlgorithms/Fortran/pull/25
!!
!! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request
!! addressing bugs/corrections to this file. Thank you!
!!
!! This program demonstrates the use of Midpoint Rule for numerical integration.
!!
!! It sets the integration limits and number of subintervals (panels), and calls the
!! midpoint subroutine to compute the approximate value of the definite integral
!! of the specified function.
!!
!! Example function: f(x) = exp(-x^2) * cos(2.0_dp * x)

program example_midpoint
use midpoint_rule
implicit none
real(dp) :: a, b, integral_result
integer :: n

! Set the integration limits and number of panels
a = -1.0_dp
b = 1.0_dp
n = 400 !! Number of subdivisions

! Call the midpoint rule subroutine with the function passed as an argument
call midpoint(integral_result, a, b, n, func)

write (*, '(A, F12.6)') "Midpoint rule yields: ", integral_result !! ≈ 0.858196

contains

function func(x) result(fx)
implicit none
real(dp), intent(in) :: x
real(dp) :: fx

fx = exp(-x**2)*cos(2.0_dp*x) !! Example function to integrate
end function func

end program example_midpoint
45 changes: 45 additions & 0 deletions examples/maths/numerical_integration/monte_carlo.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
!> Example Program for Monte Carlo Integration
!!
!! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed)
!! in Pull Request: #25
!! https://github.com/TheAlgorithms/Fortran/pull/25
!!
!! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request
!! addressing bugs/corrections to this file. Thank you!
!!
!! This program demonstrates the use of Monte Carlo module for numerical integration.
!!
!! It sets the integration limits and number of random samples, and calls the
!! monte_carlo subroutine to compute the approximate value of the definite integral
!! of the specified function.
!!
!! Example function: f(x) = exp(-x^2) * cos(2.0_dp * x)

program example_monte_carlo
use monte_carlo_integration
implicit none

real(dp) :: a, b, integral_result, error_estimate
integer :: n

! Set the integration limits and number of random samples
a = -1.0_dp
b = 1.0_dp
n = 1000000 !! 1E6 Number of random samples

! Call Monte Carlo integration
call monte_carlo(integral_result, error_estimate, a, b, n, func)

write (*, '(A, F12.6, A, F12.6)') "Monte Carlo result: ", integral_result, " +- ", error_estimate !! ≈ 0.858421

contains

function func(x) result(fx)
implicit none
real(dp), intent(in) :: x
real(dp) :: fx

fx = exp(-x**2)*cos(2.0_dp*x) !! Example function to integrate
end function func

end program example_monte_carlo
45 changes: 45 additions & 0 deletions examples/maths/numerical_integration/simpson.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
!> Example Program for Simpson's Rule
!!
!! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed)
!! in Pull Request: #25
!! https://github.com/TheAlgorithms/Fortran/pull/25
!!
!! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request
!! addressing bugs/corrections to this file. Thank you!
!!
!! This program demonstrates the use of Simpson's rule for numerical integration.
!!
!! It sets the integration limits and number of panels, and calls the
!! simpson subroutine to compute the approximate value of the definite integral
!! of the specified function.
!!
!! Example function: f(x) = exp(-x^2) * cos(2.0_dp * x)

program example_simpson
use simpson_rule
implicit none

real(dp) :: a, b, integral_result
integer :: n

! Set the integration limits and number of panels
a = -1.0_dp
b = 1.0_dp
n = 100 !! Number of subdivisions (must be even)

! Call Simpson's rule with the function passed as an argument
call simpson(integral_result, a, b, n, func)

write (*, '(A, F12.8)') "Simpson's rule yields: ", integral_result !! ≈ 0.85819555

contains

function func(x) result(fx)
implicit none
real(dp), intent(in) :: x
real(dp) :: fx

fx = exp(-x**2)*cos(2.0_dp*x) !! Example function to integrate
end function func

end program example_simpson
45 changes: 45 additions & 0 deletions examples/maths/numerical_integration/trapezoid.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
!> Example Program for Trapezoidal Rule
!!
!! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed)
!! in Pull Request: #25
!! https://github.com/TheAlgorithms/Fortran/pull/25
!!
!! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request
!! addressing bugs/corrections to this file. Thank you!
!!
!! This program demonstrates the use of the Trapezoidal rule for numerical integration.
!!
!! It sets the integration limits and number of panels, and calls the
!! trapezoid subroutine to compute the approximate value of the definite integral
!! of the specified function.
!!
!! Example function: f(x) = exp(-x^2) * cos(2.0_dp * x)

program example_tapezoid
use trapezoidal_rule
implicit none

real(dp) :: a, b, integral_result
integer :: n

! Set the integration limits and number of panels
a = -1.0_dp
b = 1.0_dp
n = 1000000 !! 1E6 Number of subdivisions

! Call the trapezoidal rule with the function passed as an argument
call trapezoid(integral_result, a, b, n, func)

write (*, '(A, F12.6)') 'Trapezoidal rule yields: ', integral_result !! ≈ 0.858195

contains

function func(x) result(fx)
implicit none
real(dp), intent(in) :: x
real(dp) :: fx

fx = exp(-x**2)*cos(2.0_dp*x) !! Example function to integrate
end function func

end program example_tapezoid
Loading