Section: BLAS/LAPACK - SCAL#

Adapted from: gjbex/Fortran-MOOC

This program demonstrates using the SCAL BLAS/LAPACK subroutine to scale a vector by a constant in Fortran.#

In file section_blas_lapack_scal.f90

program scal
  use, intrinsic :: iso_fortran_env, only : error_unit, DP => REAL64
  implicit none
  integer, parameter :: rows = 3, cols = 4
  real(kind=DP), dimension(rows, cols) :: matrix
  real(kind=DP), dimension(rows) :: norm
  integer :: row

  ! Define the explicit interface for the BLAS subroutine dscal
  interface
      subroutine dscal(n, da, dx, incx)
          import :: DP
          integer :: n, incx
          real(kind=DP) :: da
          real(kind=DP), dimension(*) :: dx
      end subroutine dscal
  end interface

  ! Initialize matrix with random numbers
  call random_number(matrix)
  
  ! Print original matrix
  print '(A)', 'original:'

  ! Print matrix
  call print_matrix(matrix)

  ! Normalize along each column
  norm = sum(matrix, dim=2)
  print '(A, *(F12.7))', 'norm:', norm

  ! Loop over rows
  do row = 1, rows
      print '(A, I0)', 'row: ', row
      print '(A, F12.7)', '1/norm(row): ', 1.0_DP/norm(row)

      ! In Fortran, the function call for dscal is:
      ! call dscal(n, da, dx, incx)
      ! where:
      ! n is the number of elements in the vector
      ! da is the scalar
      ! dx is the vector
      ! incx is the increment between elements of the vector
      call dscal(cols, 1.0_DP/norm(row), matrix(row, :), 1)
      
      ! Print the matrix
      call print_matrix(matrix)
  end do
  print '(A)', 'row-normalized::'
  ! Print matrix
  call print_matrix(matrix)

  ! Normalize along each column
  norm = sum(matrix, dim=2)
  print '(A, *(F12.7))', 'norm:', norm

contains

  subroutine print_matrix(matrix)
      implicit none
      real(kind=DP), dimension(:, :), intent(in) :: matrix
      integer :: row

      do row = 1, size(matrix, 1)
          print '(*(F12.7))', matrix(row, :)
      end do
  end subroutine print_matrix

end program scal

The above program is compiled and run using Fortran Package Manager (fpm):

Build the Program using FPM (Fortran Package Manager)#

import os
root_dir = ""
root_dir = os.getcwd()

Since the code makes use of the LAPACK library, the following FPM configuration file (fpm.toml) was used:

name = "Section_BLAS_LAPACK_Scal"

[build]
auto-executables = true
auto-tests = true
auto-examples = true
link = ["blas", "lapack"]

[install]
library = false

[[executable]]
name="Section_BLAS_LAPACK_Scal"
source-dir="app"
main="section_blas_lapack_scal.f90"
code_dir = root_dir + "/" + "Fortran_Code/Section_BLAS_LAPACK_Scal"
os.chdir(code_dir)
build_status = os.system("fpm build 2>/dev/null")

Run the Program using FPM (Fortran Package Manager)#

exec_status = \
    os.system("fpm run 2>/dev/null")
original:
   0.6484231   0.7699479   0.0408001   0.9845512
   0.8282905   0.2951749   0.0316558   0.7883060
   0.0588210   0.1357320   0.8372485   0.4022821
norm:   2.4437222   1.9434273   1.4340835
row: 1
1/norm(row):    0.4092118
   0.2653424   0.3150718   0.0166959   0.4028900
   0.8282905   0.2951749   0.0316558   0.7883060
   0.0588210   0.1357320   0.8372485   0.4022821
row: 2
1/norm(row):    0.5145549
   0.2653424   0.3150718   0.0166959   0.4028900
   0.4262009   0.1518837   0.0162886   0.4056267
   0.0588210   0.1357320   0.8372485   0.4022821
row: 3
1/norm(row):    0.6973095
   0.2653424   0.3150718   0.0166959   0.4028900
   0.4262009   0.1518837   0.0162886   0.4056267
   0.0410164   0.0946472   0.5838213   0.2805151
row-normalized::
   0.2653424   0.3150718   0.0166959   0.4028900
   0.4262009   0.1518837   0.0162886   0.4056267
   0.0410164   0.0946472   0.5838213   0.2805151
norm:   1.0000000   1.0000000   1.0000000