Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Section: BLAS/LAPACK - SCAL

---
jupytext:
  formats: md:myst
  text_representation:
    extension: .md
    format_name: myst
kernelspec:
  display_name: Python 3
  language: python
  name: python3
---

Section: BLAS/LAPACK - SCAL

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

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:

fpm.toml
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.8237821   0.0533343   0.3678545   0.5416564
   0.6819919   0.9583049   0.4784227   0.6292463
   0.7772520   0.3168976   0.4976013   0.8041315
norm:   1.7866273   2.7479658   2.3958825
row: 1
1/norm(row):    0.5597138
   0.4610822   0.0298519   0.2058933   0.3031726
   0.6819919   0.9583049   0.4784227   0.6292463
   0.7772520   0.3168976   0.4976013   0.8041315
row: 2
1/norm(row):    0.3639056
   0.4610822   0.0298519   0.2058933   0.3031726
   0.2481806   0.3487325   0.1741007   0.2289862
   0.7772520   0.3168976   0.4976013   0.8041315
row: 3
1/norm(row):    0.4173827
   0.4610822   0.0298519   0.2058933   0.3031726
   0.2481806   0.3487325   0.1741007   0.2289862
   0.3244116   0.1322676   0.2076902   0.3356306
row-normalized::
   0.4610822   0.0298519   0.2058933   0.3031726
   0.2481806   0.3487325   0.1741007   0.2289862
   0.3244116   0.1322676   0.2076902   0.3356306
norm:   1.0000000   1.0000000   1.0000000