Section: BLAS/LAPACK - Vector Copy#
Adapted from: gjbex/Fortran-MOOC
This program demonstrates copying vectors using BLAS/LAPACK in Fortran.#
The Fortran program copy_test demonstrates the usage of the scopy subroutine, which is typically from the BLAS (Basic Linear Algebra Subprograms) library. The subroutine is used for copying and optionally scaling elements from one vector to another. Here’s a step-by-step explanation of what each part of the program does:
Initialization and Vector Setup#
Vector Initialization:
vector1is initialized with the first ten positive real numbers. This is achieved through an array constructor[ (real(i), i=1, v_size) ], whereiruns from 1 tov_size(10).vector2is another vector of the same size (v_size), intended to be the target for copying elements fromvector1.large_vectoris a vector twice the size ofvector1, used to demonstrate copying with different increments and scaling.
Printing the Original Vector#
Displaying
vector1:The program prints the original content of
vector1using a formatted print statement.
Copying Elements with Different Parameters#
First Copy Operation (
scopy(size(vector1), vector1, 1, vector2, 1)):Copies the contents of
vector1directly intovector2without any scaling or skipping elements (both source and destination increments are 1). The result is thatvector2becomes an exact copy ofvector1.
Second Copy Operation (
scopy(size(vector1), vector1, 1, vector2, 2)):Copies elements from
vector1intovector2but with a destination increment of 2. This means every second element invector2is filled, leaving alternate elements as zero (sincevector2was reset to 0.0 before this operation).
Third Copy Operation (
scopy(size(vector1), vector1, 2, vector2, 1)):Copies every second element from
vector1tovector2with a source increment of 2 and destination increment of 1. This results invector2containing every second element ofvector1, with remaining positions invector2being zero.
Fourth Copy Operation (
scopy(size(vector1), vector1, 2, vector2, 2)):Both source and destination increments are set to 2, which means every second element from
vector1is copied to every second position invector2.
Demonstrating with a Larger Vector#
Fifth Copy Operation (
scopy(size(vector1), vector1, 1, large_vector, 2)):Similar to the second copy operation but targets
large_vector. Elements fromvector1are placed in every second slot oflarge_vector.
Sixth Copy Operation with Scaling (
scopy(size(vector1), 3.0*vector1, 1, large_vector(2), 2)):This operation is more complex as it involves scaling
vector1by 3.0 and copying intolarge_vectorstarting from the second element and skipping every second slot. This demonstrates the ability to combine scaling and non-contiguous memory access in a single operation.
Summary#
The program is a comprehensive demonstration of various capabilities of the scopy subroutine, including element-wise copying with different strides and scaling. Each operation is followed by a print statement to visualize the results of these operations, showcasing how scopy handles different configurations of source and destination vectors. This type of functionality is typically used in numerical and scientific computations where efficient manipulation of large arrays is necessary.
Program Code#
program copy_test
implicit none
integer, parameter :: v_size = 10
integer :: i
real, dimension(v_size) :: vector1 = [ (real(i), i=1, v_size) ], vector2
real, dimension(2*v_size) :: large_vector
interface
subroutine scopy(n, sx, incx, sy, incy)
integer :: n, incx, incy
real, dimension(*) :: sx, sy
end subroutine scopy
end interface
print '(A20, *(F5.1))', 'original: ', vector1
vector2 = 0.0
large_vector = 0.0
call scopy(size(vector1), vector1, 1, vector2, 1)
print '(A20, *(F5.1))', 'copy N 1 1: ', vector2
vector2 = 0.0
call scopy(size(vector1), vector1, 1, vector2, 2)
print '(A20, *(F5.1))', 'copy N 1 2: ', vector2
vector2 = 0.0
call scopy(size(vector1), vector1, 2, vector2, 1)
print '(A20, *(F5.1))', 'copy N 2 1: ', vector2
vector2 = 0.0
call scopy(size(vector1), vector1, 2, vector2, 2)
print '(A20, *(F5.1))', 'copy N 2 2: ', vector2
large_vector = 0.0
call scopy(size(vector1), vector1, 1, large_vector, 2)
print '(A20, *(F5.1))', 'copy N 1 2: ', large_vector
call scopy(size(vector1), 3.0*vector1, 1, large_vector(2), 2)
print '(A20, *(F5.1))', 'shift copy N 1 2: ', large_vector
end program copy_test
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_Copy"
[build]
auto-executables = true
auto-tests = true
auto-examples = true
link = ["blas", "lapack"]
[install]
library = false
[[executable]]
name="Section_BLAS_LAPACK_Copy"
source-dir="app"
main="section_blas_lapack_copy.f90"
code_dir = root_dir + "/" + "Fortran_Code/Section_BLAS_LAPACK_Copy"
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: 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0
copy N 1 1: 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0
copy N 1 2: 1.0 0.0 2.0 0.0 3.0 0.0 4.0 0.0 5.0 0.0
copy N 2 1: 1.0 3.0 5.0 7.0 9.0 0.0 0.0 0.0 0.0 0.0
copy N 2 2: 1.0 0.0 3.0 0.0 5.0 0.0 7.0 0.0 9.0 0.0
copy N 1 2: 1.0 0.0 2.0 0.0 3.0 0.0 4.0 0.0 5.0 0.0 6.0 0.0 7.0 0.0 8.0 0.0 9.0 0.0 10.0 0.0
shift copy N 1 2: 1.0 3.0 2.0 6.0 3.0 9.0 4.0 12.0 5.0 15.0 6.0 18.0 7.0 21.0 8.0 24.0 9.0 27.0 10.0 30.0