From ebc61cd15278e270988341664856b873ba07c3a3 Mon Sep 17 00:00:00 2001 From: zoziha13 <1325686572@qq.com> Date: Sun, 1 Aug 2021 21:52:58 +0800 Subject: [PATCH 1/5] Update eye function. --- doc/specs/stdlib_linalg.md | 19 ++++++++++++---- src/stdlib_linalg.fypp | 37 ++++++++++++++++++++------------ src/tests/Makefile.manual | 1 + src/tests/linalg/Makefile.manual | 4 ++++ src/tests/linalg/test_linalg.f90 | 7 ++++++ 5 files changed, 50 insertions(+), 18 deletions(-) create mode 100644 src/tests/linalg/Makefile.manual diff --git a/doc/specs/stdlib_linalg.md b/doc/specs/stdlib_linalg.md index cab16279c..b1a42e067 100644 --- a/doc/specs/stdlib_linalg.md +++ b/doc/specs/stdlib_linalg.md @@ -101,21 +101,29 @@ end program demo_diag5 Experimental +### Class + +Pure function. + ### Description -Construct the identity matrix +Construct the identity matrix. ### Syntax -`I = [[stdlib_linalg(module):eye(function)]](n)` +`I = [[stdlib_linalg(module):eye(function)]](dim1 [, dim2])` ### Arguments -`n`: Shall be a scalar of default type `integer`. +`dim1`: Shall be a scalar of default type `integer`. +This is an `intent(in)` argument. + +`dim2`: Shall be a scalar of default type `integer`. +This is an `intent(in)` and `optional` argument. ### Return value -Returns the identity matrix, i.e. a square matrix with ones on the main diagonal and zeros elsewhere. The return value is of type `integer(int8)`. +Returns the identity matrix, i.e. a square matrix with ones on the main diagonal and zeros elsewhere. The return value is of type `integer`. ### Example @@ -124,7 +132,10 @@ program demo_eye1 use stdlib_linalg, only: eye implicit none real :: a(3,3) + real :: b(3,4) A = eye(3) + A = eye(3,3) + B = eye(3,4) end program demo_eye1 ``` diff --git a/src/stdlib_linalg.fypp b/src/stdlib_linalg.fypp index 5e0388c0b..ed4fd6fe8 100644 --- a/src/stdlib_linalg.fypp +++ b/src/stdlib_linalg.fypp @@ -82,20 +82,28 @@ module stdlib_linalg contains - function eye(n) result(res) - !! version: experimental - !! - !! Constructs the identity matrix - !! ([Specification](../page/specs/stdlib_linalg.html#description_1)) - integer, intent(in) :: n - integer(int8) :: res(n, n) - integer :: i - res = 0 - do i = 1, n - res(i, i) = 1 - end do - end function eye + !> Version: experimental + !> + !> Constructs the identity matrix. + !> ([Specification](../page/specs/stdlib_linalg.html#eye-construct-the-identity-matrix)) + pure function eye(dim1, dim2) result(result) + + integer, intent(in) :: dim1 + integer, intent(in), optional :: dim2 + integer, allocatable :: result(:, :) + + integer :: dim2_ + integer :: i + dim2_ = merge(dim2, dim1, present(dim2)) + allocate(result(dim1, dim2_)) + + result = 0 + do i = 1, min(dim1, dim2_) + result(i, i) = 1 + end do + + end function eye #:for k1, t1 in RCI_KINDS_TYPES function trace_${t1[0]}$${k1}$(A) result(res) @@ -108,4 +116,5 @@ contains end do end function trace_${t1[0]}$${k1}$ #:endfor -end module + +end module stdlib_linalg diff --git a/src/tests/Makefile.manual b/src/tests/Makefile.manual index 7ab184016..c29170e24 100644 --- a/src/tests/Makefile.manual +++ b/src/tests/Makefile.manual @@ -11,3 +11,4 @@ all test clean: $(MAKE) -f Makefile.manual --directory=stats $@ $(MAKE) -f Makefile.manual --directory=string $@ $(MAKE) -f Makefile.manual --directory=math $@ + $(MAKE) -f Makefile.manual --directory=linalg $@ diff --git a/src/tests/linalg/Makefile.manual b/src/tests/linalg/Makefile.manual new file mode 100644 index 000000000..a95f600c7 --- /dev/null +++ b/src/tests/linalg/Makefile.manual @@ -0,0 +1,4 @@ +PROGS_SRC = test_linalg.f90 + + +include ../Makefile.manual.test.mk diff --git a/src/tests/linalg/test_linalg.f90 b/src/tests/linalg/test_linalg.f90 index cc8d0db68..599dbd35a 100644 --- a/src/tests/linalg/test_linalg.f90 +++ b/src/tests/linalg/test_linalg.f90 @@ -81,6 +81,13 @@ subroutine test_eye integer :: i write(*,*) "test_eye" + call check(all(eye(3,3) == diag([(1,i=1,3)])), & + msg="all(eye(3,3) == diag([(1,i=1,3)])) failed.",warn=warn) + + rye = eye(3,4) + call check(sum(rye(:,1:3) - diag([(1.0_sp,i=1,3)])) < sptol, & + msg="sum(rye(:,1:3) - diag([(1.0_sp,i=1,3)])) < sptol", warn=warn) + call check(all(eye(5) == diag([(1,i=1,5)])), & msg="all(eye(5) == diag([(1,i=1,5)] failed.",warn=warn) From 8745725a6e9df846d961e7f5aa37cfd0a23e845e Mon Sep 17 00:00:00 2001 From: zoziha13 <1325686572@qq.com> Date: Tue, 3 Aug 2021 16:59:46 +0800 Subject: [PATCH 2/5] Improve `eye` function help docs. --- doc/specs/stdlib_linalg.md | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/doc/specs/stdlib_linalg.md b/doc/specs/stdlib_linalg.md index b1a42e067..800defc3c 100644 --- a/doc/specs/stdlib_linalg.md +++ b/doc/specs/stdlib_linalg.md @@ -121,9 +121,26 @@ This is an `intent(in)` argument. `dim2`: Shall be a scalar of default type `integer`. This is an `intent(in)` and `optional` argument. +#### Note + +Because of `huge(integer :: i) = 2147483647`, the dimensional maximum length of array created by the `eye` function is `2147483647`. + ### Return value -Returns the identity matrix, i.e. a square matrix with ones on the main diagonal and zeros elsewhere. The return value is of type `integer`. +Return the identity matrix, i.e. a square matrix with ones on the main diagonal and zeros elsewhere. The return value is of type `integer`. + +#### Warning + +If the array that receives the return value of the `eye` function is of `real/complex` type, conversion from `integer` type to `real/complex` type will occur. + +Just as `Fortran` is a strongly typed statically compiled language, be careful with the following statements: +```fortran +real :: A(:,:) +!> Be careful +A = eye(2,2)/2 !! A == 0.0 +!> Recommend +A = eye(2,2)/2.0 !! A == diag([0.5, 0.5]) +``` ### Example @@ -131,11 +148,16 @@ Returns the identity matrix, i.e. a square matrix with ones on the main diagonal program demo_eye1 use stdlib_linalg, only: eye implicit none + integer :: i(2,2) real :: a(3,3) - real :: b(3,4) - A = eye(3) - A = eye(3,3) - B = eye(3,4) + real :: b(2,3) !! Matrix is non-square. + complex :: c(2,2) + I = eye(2) !! [1,0; 0,1] + A = eye(3) !! [1.0,0.0,0.0; 0.0,1.0,0.0; 0.0,0.0,1.0] + A = eye(3,3) !! [1.0,0.0,0.0; 0.0,1.0,0.0; 0.0,0.0,1.0] + B = eye(2,3) !! [1.0,0.0,0.0; 0.0,1.0,0.0] + C = eye(2,2) !! [(1.0,0.0),(0.0,0.0); (0.0,0.0),(1.0,0.0)] + C = (1.0,1.0)*eye(2,2) !! [(1.0,1.0),(0.0,0.0); (0.0,0.0),(1.0,1.0)] end program demo_eye1 ``` From c2f0abf9f35157887b850b7135d179336b83b2b9 Mon Sep 17 00:00:00 2001 From: zoziha13 <1325686572@qq.com> Date: Thu, 5 Aug 2021 11:33:38 +0800 Subject: [PATCH 3/5] Update `eye` func: 1. `merge` -> `optval` inside. --- src/Makefile.manual | 3 ++- src/stdlib_linalg.fypp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Makefile.manual b/src/Makefile.manual index a12f81255..ecfc92c7a 100644 --- a/src/Makefile.manual +++ b/src/Makefile.manual @@ -149,7 +149,8 @@ stdlib_string_type.o: stdlib_ascii.o \ stdlib_strings.o: stdlib_ascii.o \ stdlib_string_type.o \ stdlib_optval.o -stdlib_math.o: stdlib_kinds.o +stdlib_math.o: stdlib_kinds.o \ + stdlib_optval.o stdlib_math_linspace.o: \ stdlib_math.o stdlib_math_logspace.o: \ diff --git a/src/stdlib_linalg.fypp b/src/stdlib_linalg.fypp index ed4fd6fe8..4a687fb0d 100644 --- a/src/stdlib_linalg.fypp +++ b/src/stdlib_linalg.fypp @@ -5,6 +5,7 @@ module stdlib_linalg !! ([Specification](../page/specs/stdlib_linalg.html)) use stdlib_kinds, only: sp, dp, qp, & int8, int16, int32, int64 + use stdlib_optval, only: optval implicit none private @@ -95,7 +96,7 @@ contains integer :: dim2_ integer :: i - dim2_ = merge(dim2, dim1, present(dim2)) + dim2_ = optval(dim2, dim1) allocate(result(dim1, dim2_)) result = 0 From c20f69f059126d17d8d731f024d83ef3c2392d42 Mon Sep 17 00:00:00 2001 From: zoziha13 <1325686572@qq.com> Date: Fri, 6 Aug 2021 13:12:29 +0800 Subject: [PATCH 4/5] Improve `eye` func test and doc. --- doc/specs/stdlib_linalg.md | 10 ++-------- src/tests/linalg/test_linalg.f90 | 8 ++++---- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/doc/specs/stdlib_linalg.md b/doc/specs/stdlib_linalg.md index 800defc3c..2fc45dfb2 100644 --- a/doc/specs/stdlib_linalg.md +++ b/doc/specs/stdlib_linalg.md @@ -121,19 +121,13 @@ This is an `intent(in)` argument. `dim2`: Shall be a scalar of default type `integer`. This is an `intent(in)` and `optional` argument. -#### Note - -Because of `huge(integer :: i) = 2147483647`, the dimensional maximum length of array created by the `eye` function is `2147483647`. - ### Return value -Return the identity matrix, i.e. a square matrix with ones on the main diagonal and zeros elsewhere. The return value is of type `integer`. +Return the identity matrix, i.e. a matrix with ones on the main diagonal and zeros elsewhere. The return value is of type `integer`. #### Warning -If the array that receives the return value of the `eye` function is of `real/complex` type, conversion from `integer` type to `real/complex` type will occur. - -Just as `Fortran` is a strongly typed statically compiled language, be careful with the following statements: +Since the result of `eye` is of `integer` type, one should be careful about using it in arithmetic expressions. For example: ```fortran real :: A(:,:) !> Be careful diff --git a/src/tests/linalg/test_linalg.f90 b/src/tests/linalg/test_linalg.f90 index 599dbd35a..7583f0585 100644 --- a/src/tests/linalg/test_linalg.f90 +++ b/src/tests/linalg/test_linalg.f90 @@ -85,15 +85,15 @@ subroutine test_eye msg="all(eye(3,3) == diag([(1,i=1,3)])) failed.",warn=warn) rye = eye(3,4) - call check(sum(rye(:,1:3) - diag([(1.0_sp,i=1,3)])) < sptol, & - msg="sum(rye(:,1:3) - diag([(1.0_sp,i=1,3)])) < sptol", warn=warn) + call check(sum(abs(rye(:,1:3) - diag([(1.0_sp,i=1,3)]))) < sptol, & + msg="sum(abs(rye(:,1:3) - diag([(1.0_sp,i=1,3)]))) < sptol failed", warn=warn) call check(all(eye(5) == diag([(1,i=1,5)])), & msg="all(eye(5) == diag([(1,i=1,5)] failed.",warn=warn) rye = eye(6) - call check(sum(rye - diag([(1.0_sp,i=1,6)])) < sptol, & - msg="sum(rye - diag([(1.0_sp,i=1,6)])) < sptol failed.",warn=warn) + call check(sum(abs(rye - diag([(1.0_sp,i=1,6)]))) < sptol, & + msg="sum(abs(rye - diag([(1.0_sp,i=1,6)]))) < sptol failed.",warn=warn) cye = eye(7) call check(abs(trace(cye) - cmplx(7.0_sp,0.0_sp,kind=sp)) < sptol, & From c326353f0410b14aec100f6ba6a8586bd274193e Mon Sep 17 00:00:00 2001 From: zoziha13 <1325686572@qq.com> Date: Sun, 22 Aug 2021 00:43:39 +0800 Subject: [PATCH 5/5] Update `eye` func: `integer(int8)` --- doc/specs/stdlib_linalg.md | 5 +++-- src/stdlib_linalg.fypp | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/doc/specs/stdlib_linalg.md b/doc/specs/stdlib_linalg.md index 2fc45dfb2..7ca3b9198 100644 --- a/doc/specs/stdlib_linalg.md +++ b/doc/specs/stdlib_linalg.md @@ -123,11 +123,12 @@ This is an `intent(in)` and `optional` argument. ### Return value -Return the identity matrix, i.e. a matrix with ones on the main diagonal and zeros elsewhere. The return value is of type `integer`. +Return the identity matrix, i.e. a matrix with ones on the main diagonal and zeros elsewhere. The return value is of type `integer(int8)`. +The use of `int8` was suggested to save storage. #### Warning -Since the result of `eye` is of `integer` type, one should be careful about using it in arithmetic expressions. For example: +Since the result of `eye` is of `integer(int8)` type, one should be careful about using it in arithmetic expressions. For example: ```fortran real :: A(:,:) !> Be careful diff --git a/src/stdlib_linalg.fypp b/src/stdlib_linalg.fypp index 4a687fb0d..3faaeb9af 100644 --- a/src/stdlib_linalg.fypp +++ b/src/stdlib_linalg.fypp @@ -91,7 +91,7 @@ contains integer, intent(in) :: dim1 integer, intent(in), optional :: dim2 - integer, allocatable :: result(:, :) + integer(int8), allocatable :: result(:, :) integer :: dim2_ integer :: i @@ -99,9 +99,9 @@ contains dim2_ = optval(dim2, dim1) allocate(result(dim1, dim2_)) - result = 0 + result = 0_int8 do i = 1, min(dim1, dim2_) - result(i, i) = 1 + result(i, i) = 1_int8 end do end function eye