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:
vector1
is initialized with the first ten positive real numbers. This is achieved through an array constructor[ (real(i), i=1, v_size) ]
, wherei
runs from 1 tov_size
(10).vector2
is another vector of the same size (v_size
), intended to be the target for copying elements fromvector1
.large_vector
is 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
vector1
using a formatted print statement.
Copying Elements with Different Parameters#
First Copy Operation (
scopy(size(vector1), vector1, 1, vector2, 1)
):Copies the contents of
vector1
directly intovector2
without any scaling or skipping elements (both source and destination increments are 1). The result is thatvector2
becomes an exact copy ofvector1
.
Second Copy Operation (
scopy(size(vector1), vector1, 1, vector2, 2)
):Copies elements from
vector1
intovector2
but with a destination increment of 2. This means every second element invector2
is filled, leaving alternate elements as zero (sincevector2
was reset to 0.0 before this operation).
Third Copy Operation (
scopy(size(vector1), vector1, 2, vector2, 1)
):Copies every second element from
vector1
tovector2
with a source increment of 2 and destination increment of 1. This results invector2
containing every second element ofvector1
, with remaining positions invector2
being 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
vector1
is 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 fromvector1
are 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
vector1
by 3.0 and copying intolarge_vector
starting 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