From 780944f375bb3e06d476ab79222f38ab4f6b58a9 Mon Sep 17 00:00:00 2001 From: zoziha13 <1325686572@qq.com> Date: Sun, 1 Aug 2021 00:48:16 +0800 Subject: [PATCH 1/5] Add seq function. --- doc/specs/stdlib_math.md | 58 ++++++++++++++++++++++++++++++++ src/CMakeLists.txt | 1 + src/Makefile.manual | 4 +++ src/stdlib_math.fypp | 16 +++++++++ src/stdlib_math_seq.fypp | 58 ++++++++++++++++++++++++++++++++ src/tests/math/CMakeLists.txt | 3 +- src/tests/math/Makefile.manual | 3 +- src/tests/math/test_math_seq.f90 | 53 +++++++++++++++++++++++++++++ 8 files changed, 194 insertions(+), 2 deletions(-) create mode 100644 src/stdlib_math_seq.fypp create mode 100644 src/tests/math/test_math_seq.f90 diff --git a/doc/specs/stdlib_math.md b/doc/specs/stdlib_math.md index 2e09796de..ea2cdd0ed 100644 --- a/doc/specs/stdlib_math.md +++ b/doc/specs/stdlib_math.md @@ -275,3 +275,61 @@ program demo_logspace_rstart_cbase end program demo_logspace_rstart_cbase ``` +## `seq` - Creates an vector of `integer/real` type with evenly spaced values within a given interval. + +### Status + +Experimental + +### Class + +Pure function. + +### Description + +Creates an vector of `integer/real` type with evenly spaced values within a given interval. + +### Syntax + +`result = [[stdlib_math(module):seq(interface)]](start [, end, by])` + +### Arguments + +`start`: Shall be an `integer/real` scalar. +This is an `intent(in)` argument. + +`end`: Shall be an `integer/real` scalar. +This is an `intent(in)` and `optional` argument. + +`by`: Shall be an `integer/real` scalar and large than `0`. +This is an `intent(in)` and `optional` argument. + +Warning: +If `by = 0`, the `by` argument will be corrected to `1/1.0` by the internal process of the `seq` function. +If `by < 0`, the `by` argument will be corrected to `abs(by)` by the internal process of the `seq` function. + +### Return value + +Vector of evenly spaced values. + +For floating point arguments, the length of the result is `floor((end - start)/by) + 1`. + +### Example + +```fortran +program demo_math_seq + use stdlib_math, only: seq + + print *, seq(3) !! [1,2,3] + print *, seq(3.0) !! [1.0,2.0,3.0] + print *, seq(-1) !! [1,0,-1] + print *, seq(0,2) !! [0,1,2] + print *, seq(1,-1) !! [1,0,-1] + print *, seq(0, 2, 2) !! [0,2] + print *, (1.0,1.0)*seq(3) !! [(1.0,1.0),(2.0,2.0),[3.0,3.0]] + + print *, seq(0.0,2.0,-2.0) !! [0.0,2.0]. Not recommended: `by` argument is negative! + print *, seq(0.0,2.0,0.0) !! [0.0,1.0]. Not recommended: `by` argument is zero! + +end program demo_math_seq +``` \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c4f6d76e7..69e73afd3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -32,6 +32,7 @@ set(fppFiles stdlib_math.fypp stdlib_math_linspace.fypp stdlib_math_logspace.fypp + stdlib_math_seq.fypp stdlib_string_type.fypp ) diff --git a/src/Makefile.manual b/src/Makefile.manual index a12f81255..89b84e6f8 100644 --- a/src/Makefile.manual +++ b/src/Makefile.manual @@ -7,6 +7,7 @@ SRCFYPP =\ stdlib_linalg.fypp \ stdlib_linalg_diag.fypp \ stdlib_linalg_outer_product.fypp \ + stdlib_math_seq.fypp \ stdlib_optval.fypp \ stdlib_quadrature.fypp \ stdlib_quadrature_trapz.fypp \ @@ -154,4 +155,7 @@ stdlib_math_linspace.o: \ stdlib_math.o stdlib_math_logspace.o: \ stdlib_math_linspace.o +stdlib_math_seq.o: \ + stdlib_math.o \ + stdlib_kinds.o stdlib_linalg_outer_product.o: stdlib_linalg.o diff --git a/src/stdlib_math.fypp b/src/stdlib_math.fypp index 7a3296158..1521c3f17 100644 --- a/src/stdlib_math.fypp +++ b/src/stdlib_math.fypp @@ -10,6 +10,7 @@ module stdlib_math public :: clip, linspace, logspace public :: EULERS_NUMBER_SP, EULERS_NUMBER_DP, EULERS_NUMBER_QP public :: DEFAULT_LINSPACE_LENGTH, DEFAULT_LOGSPACE_BASE, DEFAULT_LOGSPACE_LENGTH + public :: seq integer, parameter :: DEFAULT_LINSPACE_LENGTH = 100 integer, parameter :: DEFAULT_LOGSPACE_LENGTH = 50 @@ -261,6 +262,21 @@ module stdlib_math end interface + !> Version: experimental + !> + !> `seq` creates an vector of `integer/real` type + !> with evenly spaced values within a given interval. + interface seq + #:set RI_KINDS_TYPES = REAL_KINDS_TYPES + INT_KINDS_TYPES + #:for k1, t1 in RI_KINDS_TYPES + pure module function seq_${t1[0]}$_${k1}$(start, end, by) result(result) + ${t1}$, intent(in) :: start + ${t1}$, intent(in), optional :: end, by + ${t1}$, allocatable :: result(:) + end function seq_${t1[0]}$_${k1}$ + #:endfor + end interface seq + contains #:for k1, t1 in IR_KINDS_TYPES diff --git a/src/stdlib_math_seq.fypp b/src/stdlib_math_seq.fypp new file mode 100644 index 000000000..cc5a3fd1a --- /dev/null +++ b/src/stdlib_math_seq.fypp @@ -0,0 +1,58 @@ +#:include "common.fypp" +submodule(stdlib_math) stdlib_math_seq + + implicit none + +contains + + #:for k1, t1 in REAL_KINDS_TYPES + !> `seq` creates an vector of `${t1}$` type + !> with evenly spaced values within a given interval. + pure module function seq_${t1[0]}$_${k1}$(start, end, by) result(result) + + ${t1}$, intent(in) :: start + ${t1}$, intent(in), optional :: end, by + ${t1}$, allocatable :: result(:) + + ${t1}$ :: start_, end_, by_ + integer :: i + + start_ = merge(start, 1.0_${k1}$, present(end)) + end_ = merge(end, start, present(end)) + by_ = sign(merge(merge(by, 1.0_${k1}$, by /= 0.0_${k1}$), & + 1.0_${k1}$, present(by)), end_ - start_) + + allocate(result(floor((end_ - start_)/by_) + 1)) + #!TODO: ?? + #! floor or ceiling, floor is better. + + result = [(start_ + (i - 1)*by_, i=1, size(result), 1)] + + end function seq_${t1[0]}$_${k1}$ + #:endfor + + #:for k1, t1 in INT_KINDS_TYPES + !> `seq` creates an vector of `${t1}$` type + !> with evenly spaced values within a given interval. + pure module function seq_${t1[0]}$_${k1}$(start, end, by) result(result) + + ${t1}$, intent(in) :: start + ${t1}$, intent(in), optional :: end, by + ${t1}$, allocatable :: result(:) + + ${t1}$ :: start_, end_, by_ + ${t1}$ :: i + + start_ = merge(start, 1_${k1}$, present(end)) + end_ = merge(end, start, present(end)) + by_ = sign(merge(merge(by, 1_${k1}$, by /= 0_${k1}$), & + 1_${k1}$, present(by) ), end_ - start_) + + allocate(result((end_ - start_)/by_ + 1)) + + result = [(i, i=start_, end_, by_)] + + end function seq_${t1[0]}$_${k1}$ + #:endfor + +end submodule stdlib_math_seq diff --git a/src/tests/math/CMakeLists.txt b/src/tests/math/CMakeLists.txt index c4335e9ce..6fedb0376 100644 --- a/src/tests/math/CMakeLists.txt +++ b/src/tests/math/CMakeLists.txt @@ -1,3 +1,4 @@ ADDTEST(stdlib_math) ADDTEST(linspace) -ADDTEST(logspace) \ No newline at end of file +ADDTEST(logspace) +ADDTEST(math_seq) \ No newline at end of file diff --git a/src/tests/math/Makefile.manual b/src/tests/math/Makefile.manual index 209990732..ae8acb6a2 100644 --- a/src/tests/math/Makefile.manual +++ b/src/tests/math/Makefile.manual @@ -1,4 +1,5 @@ -PROGS_SRC = test_stdlib_math.f90 test_linspace.f90 test_logspace.f90 +PROGS_SRC = test_stdlib_math.f90 test_linspace.f90 test_logspace.f90 \ + test_math_seq.f90 include ../Makefile.manual.test.mk diff --git a/src/tests/math/test_math_seq.f90 b/src/tests/math/test_math_seq.f90 new file mode 100644 index 000000000..83361979c --- /dev/null +++ b/src/tests/math/test_math_seq.f90 @@ -0,0 +1,53 @@ +!> SPDX-Identifier: MIT +module test_math_seq + + use stdlib_error, only: check + use stdlib_math, only: seq + implicit none + + logical, private :: warn = .false. + +contains + + subroutine test_math_seq_real + !> Normal + call check(all(seq(3.0) == [1.0, 2.0, 3.0]), msg="all(seq(3.0) == [1.0,2.0,3.0]) failed.", warn=warn) + call check(all(seq(-1.0) == [1.0, 0.0, -1.0]), msg="all(seq(-1.0) == [1.0,0.0,-1.0]) failed.", warn=warn) + call check(all(seq(0.0, 2.0) == [0.0, 1.0, 2.0]), msg="all(seq(0.0,2.0) == [0.0,1.0,2.0]) failed.", warn=warn) + call check(all(seq(1.0, -1.0) == [1.0, 0.0, -1.0]), msg="all(seq(1.0,-1.0) == [1.0,0.0,-1.0]) failed.", warn=warn) + call check(all(seq(1.0, 1.0) == [1.0]), msg="all(seq(1.0,1.0) == [1.0]) failed.", warn=warn) + call check(all(seq(0.0, 2.0, 2.0) == [0.0, 2.0]), msg="all(seq(0.0,2.0,2.0) == [0.0,2.0]) failed.", warn=warn) + call check(all(seq(1.0, -1.0, 2.0) == [1.0, -1.0]), msg="all(seq(1.0,-1.0,2.0) == [1.0,-1.0]) failed.", warn=warn) + !> Not recommended + call check(all(seq(0.0, 2.0, -2.0) == [0.0, 2.0]), msg="all(seq(0.0,2.0,-2.0) == [0.0,2.0]) failed.", warn=warn) + call check(all(seq(1.0, -1.0, -2.0) == [1.0, -1.0]),msg="all(seq(1.0,-1.0,-2.0) == [1.0,-1.0]) failed.", warn=warn) + call check(all(seq(0.0, 2.0, 0.0) == [0.0,1.0,2.0]),msg="all(seq(0.0, 2.0, 0.0) == [0.0,1.0,2.0]) failed.", warn=warn) + end subroutine test_math_seq_real + + subroutine test_math_seq_integer + !> Normal + call check(all(seq(3) == [1, 2, 3]), msg="all(seq(3) == [1,2,3]) failed.", warn=warn) + call check(all(seq(-1) == [1, 0, -1]), msg="all(seq(-1) == [1,0,-1]) failed.", warn=warn) + call check(all(seq(0, 2) == [0, 1, 2]), msg="all(seq(0,2) == [0,1,2]) failed.", warn=warn) + call check(all(seq(1, -1) == [1, 0, -1]), msg="all(seq(1,-1) == [1,0,-1]) failed.", warn=warn) + call check(all(seq(1, 1) == [1]), msg="all(seq(1,1) == [1]) failed.", warn=warn) + call check(all(seq(0, 2, 2) == [0, 2]), msg="all(seq(0,2,2) == [0,2]) failed.", warn=warn) + call check(all(seq(1, -1, 2) == [1, -1]), msg="all(seq(1,-1,2) == [1,-1]) failed.", warn=warn) + !> Not recommended + call check(all(seq(0, 2, -2) == [0, 2]), msg="all(seq(0,2,-2) == [0,2]) failed.", warn=warn) + call check(all(seq(1, -1, -2) == [1, -1]), msg="all(seq(1,-1,-2) == [1,-1]) failed.", warn=warn) + call check(all(seq(0, 2, 0) == [0,1,2]), msg="all(seq(0, 2, 0) == [0,1,2]) failed.", warn=warn) + end subroutine test_math_seq_integer + +end module test_math_seq + +program tester + + use test_math_seq + + call test_math_seq_real + call test_math_seq_integer + + print *, "All tests in `test_math_seq` passed." + +end program tester From 0c9036c792c7aab1d348fb32047b0a284aed6634 Mon Sep 17 00:00:00 2001 From: zoziha13 <1325686572@qq.com> Date: Tue, 3 Aug 2021 14:20:30 +0800 Subject: [PATCH 2/5] Rename function `seq` to `arange`. Update related docs. --- doc/specs/stdlib_math.md | 55 +++++++++++-------- src/CMakeLists.txt | 2 +- src/Makefile.manual | 4 +- src/stdlib_math.fypp | 15 +++-- ..._math_seq.fypp => stdlib_math_arange.fypp} | 18 +++--- src/tests/math/CMakeLists.txt | 2 +- src/tests/math/Makefile.manual | 2 +- src/tests/math/test_math_arange.f90 | 53 ++++++++++++++++++ src/tests/math/test_math_seq.f90 | 53 ------------------ 9 files changed, 106 insertions(+), 98 deletions(-) rename src/{stdlib_math_seq.fypp => stdlib_math_arange.fypp} (74%) create mode 100644 src/tests/math/test_math_arange.f90 delete mode 100644 src/tests/math/test_math_seq.f90 diff --git a/doc/specs/stdlib_math.md b/doc/specs/stdlib_math.md index ea2cdd0ed..17a634e4e 100644 --- a/doc/specs/stdlib_math.md +++ b/doc/specs/stdlib_math.md @@ -275,7 +275,7 @@ program demo_logspace_rstart_cbase end program demo_logspace_rstart_cbase ``` -## `seq` - Creates an vector of `integer/real` type with evenly spaced values within a given interval. +## `arange` - Create a vector of the `integer/real` type with evenly spaced values within a given interval. ### Status @@ -287,49 +287,56 @@ Pure function. ### Description -Creates an vector of `integer/real` type with evenly spaced values within a given interval. +Create a vector of the `integer/real` type with evenly spaced values within a given interval. ### Syntax -`result = [[stdlib_math(module):seq(interface)]](start [, end, by])` +`result = [[stdlib_math(module):arange(interface)]](start [, end, by])` ### Arguments `start`: Shall be an `integer/real` scalar. -This is an `intent(in)` argument. +This is an `intent(in)` argument. +The default `start` value is `1`. `end`: Shall be an `integer/real` scalar. -This is an `intent(in)` and `optional` argument. - -`by`: Shall be an `integer/real` scalar and large than `0`. This is an `intent(in)` and `optional` argument. +The default `end` value is the inputted `start` value. + +`by`: Shall be an `integer/real` scalar and large than `0`. +This is an `intent(in)` and `optional` argument. +The default `by` value is `1`. -Warning: -If `by = 0`, the `by` argument will be corrected to `1/1.0` by the internal process of the `seq` function. -If `by < 0`, the `by` argument will be corrected to `abs(by)` by the internal process of the `seq` function. +#### Warning +If `by = 0`, the `by` argument will be corrected to `1/1.0` by the internal process of the `arange` function. +If `by < 0`, the `by` argument will be corrected to `abs(by)` by the internal process of the `arange` function. ### Return value -Vector of evenly spaced values. +Return a vector of evenly spaced values. -For floating point arguments, the length of the result is `floor((end - start)/by) + 1`. +For `real` type arguments, the length of the result vector is `floor((end - start)/by) + 1`. ### Example ```fortran -program demo_math_seq - use stdlib_math, only: seq +program demo_math_arange + use stdlib_math, only: arange + + print *, arange(3) !! [1,2,3] + print *, arange(-1) !! [1,0,-1] + print *, arange(0,2) !! [0,1,2] + print *, arange(1,-1) !! [1,0,-1] + print *, arange(0, 2, 2) !! [0,2] + + print *, arange(3.0) !! [1.0,2.0,3.0] + print *, arange(0.0,5.0) !! [0.0,1.0,2.0,3.0,4.0,5.0] + print *, arange(0.0,5.0,2.0) !! [0.0,2.0,4.0] - print *, seq(3) !! [1,2,3] - print *, seq(3.0) !! [1.0,2.0,3.0] - print *, seq(-1) !! [1,0,-1] - print *, seq(0,2) !! [0,1,2] - print *, seq(1,-1) !! [1,0,-1] - print *, seq(0, 2, 2) !! [0,2] - print *, (1.0,1.0)*seq(3) !! [(1.0,1.0),(2.0,2.0),[3.0,3.0]] + print *, (1.0,1.0)*arange(3) !! [(1.0,1.0),(2.0,2.0),[3.0,3.0]] - print *, seq(0.0,2.0,-2.0) !! [0.0,2.0]. Not recommended: `by` argument is negative! - print *, seq(0.0,2.0,0.0) !! [0.0,1.0]. Not recommended: `by` argument is zero! + print *, arange(0.0,2.0,-2.0) !! [0.0,2.0]. Not recommended: `by` argument is negative! + print *, arange(0.0,2.0,0.0) !! [0.0,1.0,2.0]. Not recommended: `by` argument is zero! -end program demo_math_seq +end program demo_math_arange ``` \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 69e73afd3..c4c6cf858 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -32,7 +32,7 @@ set(fppFiles stdlib_math.fypp stdlib_math_linspace.fypp stdlib_math_logspace.fypp - stdlib_math_seq.fypp + stdlib_math_arange.fypp stdlib_string_type.fypp ) diff --git a/src/Makefile.manual b/src/Makefile.manual index 89b84e6f8..1dad165c2 100644 --- a/src/Makefile.manual +++ b/src/Makefile.manual @@ -7,7 +7,7 @@ SRCFYPP =\ stdlib_linalg.fypp \ stdlib_linalg_diag.fypp \ stdlib_linalg_outer_product.fypp \ - stdlib_math_seq.fypp \ + stdlib_math_arange.fypp \ stdlib_optval.fypp \ stdlib_quadrature.fypp \ stdlib_quadrature_trapz.fypp \ @@ -155,7 +155,7 @@ stdlib_math_linspace.o: \ stdlib_math.o stdlib_math_logspace.o: \ stdlib_math_linspace.o -stdlib_math_seq.o: \ +stdlib_math_arange.o: \ stdlib_math.o \ stdlib_kinds.o stdlib_linalg_outer_product.o: stdlib_linalg.o diff --git a/src/stdlib_math.fypp b/src/stdlib_math.fypp index 1521c3f17..2fcd5afde 100644 --- a/src/stdlib_math.fypp +++ b/src/stdlib_math.fypp @@ -10,7 +10,7 @@ module stdlib_math public :: clip, linspace, logspace public :: EULERS_NUMBER_SP, EULERS_NUMBER_DP, EULERS_NUMBER_QP public :: DEFAULT_LINSPACE_LENGTH, DEFAULT_LOGSPACE_BASE, DEFAULT_LOGSPACE_LENGTH - public :: seq + public :: arange integer, parameter :: DEFAULT_LINSPACE_LENGTH = 100 integer, parameter :: DEFAULT_LOGSPACE_LENGTH = 50 @@ -264,18 +264,21 @@ module stdlib_math !> Version: experimental !> - !> `seq` creates an vector of `integer/real` type + !> `arange` creates a vector of the `integer/real` type !> with evenly spaced values within a given interval. - interface seq + !> ([Specification](../page/specs/stdlib_math.html# + !>arange-create-a-vector-of-the-integerreal-type- + !>with-evenly-spaced-values-within-a-given-interval)) + interface arange #:set RI_KINDS_TYPES = REAL_KINDS_TYPES + INT_KINDS_TYPES #:for k1, t1 in RI_KINDS_TYPES - pure module function seq_${t1[0]}$_${k1}$(start, end, by) result(result) + pure module function arange_${t1[0]}$_${k1}$(start, end, by) result(result) ${t1}$, intent(in) :: start ${t1}$, intent(in), optional :: end, by ${t1}$, allocatable :: result(:) - end function seq_${t1[0]}$_${k1}$ + end function arange_${t1[0]}$_${k1}$ #:endfor - end interface seq + end interface arange contains diff --git a/src/stdlib_math_seq.fypp b/src/stdlib_math_arange.fypp similarity index 74% rename from src/stdlib_math_seq.fypp rename to src/stdlib_math_arange.fypp index cc5a3fd1a..0fddd503f 100644 --- a/src/stdlib_math_seq.fypp +++ b/src/stdlib_math_arange.fypp @@ -1,14 +1,14 @@ #:include "common.fypp" -submodule(stdlib_math) stdlib_math_seq +submodule(stdlib_math) stdlib_math_arange implicit none contains #:for k1, t1 in REAL_KINDS_TYPES - !> `seq` creates an vector of `${t1}$` type + !> `arange` creates a vector of the `${t1}$` type !> with evenly spaced values within a given interval. - pure module function seq_${t1[0]}$_${k1}$(start, end, by) result(result) + pure module function arange_${t1[0]}$_${k1}$(start, end, by) result(result) ${t1}$, intent(in) :: start ${t1}$, intent(in), optional :: end, by @@ -23,18 +23,16 @@ contains 1.0_${k1}$, present(by)), end_ - start_) allocate(result(floor((end_ - start_)/by_) + 1)) - #!TODO: ?? - #! floor or ceiling, floor is better. result = [(start_ + (i - 1)*by_, i=1, size(result), 1)] - end function seq_${t1[0]}$_${k1}$ + end function arange_${t1[0]}$_${k1}$ #:endfor #:for k1, t1 in INT_KINDS_TYPES - !> `seq` creates an vector of `${t1}$` type + !> `arange` creates a vector of the `${t1}$` type !> with evenly spaced values within a given interval. - pure module function seq_${t1[0]}$_${k1}$(start, end, by) result(result) + pure module function arange_${t1[0]}$_${k1}$(start, end, by) result(result) ${t1}$, intent(in) :: start ${t1}$, intent(in), optional :: end, by @@ -52,7 +50,7 @@ contains result = [(i, i=start_, end_, by_)] - end function seq_${t1[0]}$_${k1}$ + end function arange_${t1[0]}$_${k1}$ #:endfor -end submodule stdlib_math_seq +end submodule stdlib_math_arange diff --git a/src/tests/math/CMakeLists.txt b/src/tests/math/CMakeLists.txt index 6fedb0376..0bcaf1e1a 100644 --- a/src/tests/math/CMakeLists.txt +++ b/src/tests/math/CMakeLists.txt @@ -1,4 +1,4 @@ ADDTEST(stdlib_math) ADDTEST(linspace) ADDTEST(logspace) -ADDTEST(math_seq) \ No newline at end of file +ADDTEST(math_arange) \ No newline at end of file diff --git a/src/tests/math/Makefile.manual b/src/tests/math/Makefile.manual index ae8acb6a2..f11cbf7a4 100644 --- a/src/tests/math/Makefile.manual +++ b/src/tests/math/Makefile.manual @@ -1,5 +1,5 @@ PROGS_SRC = test_stdlib_math.f90 test_linspace.f90 test_logspace.f90 \ - test_math_seq.f90 + test_math_arange.f90 include ../Makefile.manual.test.mk diff --git a/src/tests/math/test_math_arange.f90 b/src/tests/math/test_math_arange.f90 new file mode 100644 index 000000000..0da565afe --- /dev/null +++ b/src/tests/math/test_math_arange.f90 @@ -0,0 +1,53 @@ +!> SPDX-Identifier: MIT +module test_math_arange + + use stdlib_error, only: check + use stdlib_math, only: arange + implicit none + + logical, private :: warn = .false. + +contains + + subroutine test_math_arange_real + !> Normal + call check(all(arange(3.0) == [1.0, 2.0, 3.0]), msg="all(arange(3.0) == [1.0,2.0,3.0]) failed.", warn=warn) + call check(all(arange(-1.0) == [1.0, 0.0, -1.0]), msg="all(arange(-1.0) == [1.0,0.0,-1.0]) failed.", warn=warn) + call check(all(arange(0.0, 2.0) == [0.0, 1.0, 2.0]), msg="all(arange(0.0,2.0) == [0.0,1.0,2.0]) failed.", warn=warn) + call check(all(arange(1.0, -1.0) == [1.0, 0.0, -1.0]), msg="all(arange(1.0,-1.0) == [1.0,0.0,-1.0]) failed.", warn=warn) + call check(all(arange(1.0, 1.0) == [1.0]), msg="all(arange(1.0,1.0) == [1.0]) failed.", warn=warn) + call check(all(arange(0.0, 2.0, 2.0) == [0.0, 2.0]), msg="all(arange(0.0,2.0,2.0) == [0.0,2.0]) failed.", warn=warn) + call check(all(arange(1.0, -1.0, 2.0) == [1.0, -1.0]), msg="all(arange(1.0,-1.0,2.0) == [1.0,-1.0]) failed.", warn=warn) + !> Not recommended + call check(all(arange(0.0, 2.0, -2.0) == [0.0, 2.0]), msg="all(arange(0.0,2.0,-2.0) == [0.0,2.0]) failed.", warn=warn) + call check(all(arange(1.0, -1.0, -2.0) == [1.0, -1.0]),msg="all(arange(1.0,-1.0,-2.0) == [1.0,-1.0]) failed.", warn=warn) + call check(all(arange(0.0, 2.0, 0.0) == [0.0,1.0,2.0]),msg="all(arange(0.0, 2.0, 0.0) == [0.0,1.0,2.0]) failed.", warn=warn) + end subroutine test_math_arange_real + + subroutine test_math_arange_integer + !> Normal + call check(all(arange(3) == [1, 2, 3]), msg="all(arange(3) == [1,2,3]) failed.", warn=warn) + call check(all(arange(-1) == [1, 0, -1]), msg="all(arange(-1) == [1,0,-1]) failed.", warn=warn) + call check(all(arange(0, 2) == [0, 1, 2]), msg="all(arange(0,2) == [0,1,2]) failed.", warn=warn) + call check(all(arange(1, -1) == [1, 0, -1]), msg="all(arange(1,-1) == [1,0,-1]) failed.", warn=warn) + call check(all(arange(1, 1) == [1]), msg="all(arange(1,1) == [1]) failed.", warn=warn) + call check(all(arange(0, 2, 2) == [0, 2]), msg="all(arange(0,2,2) == [0,2]) failed.", warn=warn) + call check(all(arange(1, -1, 2) == [1, -1]), msg="all(arange(1,-1,2) == [1,-1]) failed.", warn=warn) + !> Not recommended + call check(all(arange(0, 2, -2) == [0, 2]), msg="all(arange(0,2,-2) == [0,2]) failed.", warn=warn) + call check(all(arange(1, -1, -2) == [1, -1]), msg="all(arange(1,-1,-2) == [1,-1]) failed.", warn=warn) + call check(all(arange(0, 2, 0) == [0,1,2]), msg="all(arange(0, 2, 0) == [0,1,2]) failed.", warn=warn) + end subroutine test_math_arange_integer + +end module test_math_arange + +program tester + + use test_math_arange + + call test_math_arange_real + call test_math_arange_integer + + print *, "All tests in `test_math_arange` passed." + +end program tester diff --git a/src/tests/math/test_math_seq.f90 b/src/tests/math/test_math_seq.f90 deleted file mode 100644 index 83361979c..000000000 --- a/src/tests/math/test_math_seq.f90 +++ /dev/null @@ -1,53 +0,0 @@ -!> SPDX-Identifier: MIT -module test_math_seq - - use stdlib_error, only: check - use stdlib_math, only: seq - implicit none - - logical, private :: warn = .false. - -contains - - subroutine test_math_seq_real - !> Normal - call check(all(seq(3.0) == [1.0, 2.0, 3.0]), msg="all(seq(3.0) == [1.0,2.0,3.0]) failed.", warn=warn) - call check(all(seq(-1.0) == [1.0, 0.0, -1.0]), msg="all(seq(-1.0) == [1.0,0.0,-1.0]) failed.", warn=warn) - call check(all(seq(0.0, 2.0) == [0.0, 1.0, 2.0]), msg="all(seq(0.0,2.0) == [0.0,1.0,2.0]) failed.", warn=warn) - call check(all(seq(1.0, -1.0) == [1.0, 0.0, -1.0]), msg="all(seq(1.0,-1.0) == [1.0,0.0,-1.0]) failed.", warn=warn) - call check(all(seq(1.0, 1.0) == [1.0]), msg="all(seq(1.0,1.0) == [1.0]) failed.", warn=warn) - call check(all(seq(0.0, 2.0, 2.0) == [0.0, 2.0]), msg="all(seq(0.0,2.0,2.0) == [0.0,2.0]) failed.", warn=warn) - call check(all(seq(1.0, -1.0, 2.0) == [1.0, -1.0]), msg="all(seq(1.0,-1.0,2.0) == [1.0,-1.0]) failed.", warn=warn) - !> Not recommended - call check(all(seq(0.0, 2.0, -2.0) == [0.0, 2.0]), msg="all(seq(0.0,2.0,-2.0) == [0.0,2.0]) failed.", warn=warn) - call check(all(seq(1.0, -1.0, -2.0) == [1.0, -1.0]),msg="all(seq(1.0,-1.0,-2.0) == [1.0,-1.0]) failed.", warn=warn) - call check(all(seq(0.0, 2.0, 0.0) == [0.0,1.0,2.0]),msg="all(seq(0.0, 2.0, 0.0) == [0.0,1.0,2.0]) failed.", warn=warn) - end subroutine test_math_seq_real - - subroutine test_math_seq_integer - !> Normal - call check(all(seq(3) == [1, 2, 3]), msg="all(seq(3) == [1,2,3]) failed.", warn=warn) - call check(all(seq(-1) == [1, 0, -1]), msg="all(seq(-1) == [1,0,-1]) failed.", warn=warn) - call check(all(seq(0, 2) == [0, 1, 2]), msg="all(seq(0,2) == [0,1,2]) failed.", warn=warn) - call check(all(seq(1, -1) == [1, 0, -1]), msg="all(seq(1,-1) == [1,0,-1]) failed.", warn=warn) - call check(all(seq(1, 1) == [1]), msg="all(seq(1,1) == [1]) failed.", warn=warn) - call check(all(seq(0, 2, 2) == [0, 2]), msg="all(seq(0,2,2) == [0,2]) failed.", warn=warn) - call check(all(seq(1, -1, 2) == [1, -1]), msg="all(seq(1,-1,2) == [1,-1]) failed.", warn=warn) - !> Not recommended - call check(all(seq(0, 2, -2) == [0, 2]), msg="all(seq(0,2,-2) == [0,2]) failed.", warn=warn) - call check(all(seq(1, -1, -2) == [1, -1]), msg="all(seq(1,-1,-2) == [1,-1]) failed.", warn=warn) - call check(all(seq(0, 2, 0) == [0,1,2]), msg="all(seq(0, 2, 0) == [0,1,2]) failed.", warn=warn) - end subroutine test_math_seq_integer - -end module test_math_seq - -program tester - - use test_math_seq - - call test_math_seq_real - call test_math_seq_integer - - print *, "All tests in `test_math_seq` passed." - -end program tester From 3c7cf6546ba4f90f9b3b4d709e325a619cd23ee4 Mon Sep 17 00:00:00 2001 From: zoziha13 <1325686572@qq.com> Date: Thu, 5 Aug 2021 00:20:37 +0800 Subject: [PATCH 3/5] Improve `arange` func and doc. --- doc/specs/stdlib_math.md | 15 +++++++++++---- src/stdlib_math.fypp | 4 +--- src/stdlib_math_arange.fypp | 2 -- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/doc/specs/stdlib_math.md b/doc/specs/stdlib_math.md index 17a634e4e..2a70a08bb 100644 --- a/doc/specs/stdlib_math.md +++ b/doc/specs/stdlib_math.md @@ -275,7 +275,7 @@ program demo_logspace_rstart_cbase end program demo_logspace_rstart_cbase ``` -## `arange` - Create a vector of the `integer/real` type with evenly spaced values within a given interval. +## `arange` ### Status @@ -287,7 +287,11 @@ Pure function. ### Description -Create a vector of the `integer/real` type with evenly spaced values within a given interval. +Create a vector of the `integer/real` type with given fixed spaced values within a given interval. + +#### Note + +Because of the `i` (`huge(integer :: i) = 2147483647`) index inside the `arange` function , the dimensional maximum length of array created by the `arange` function is `2147483647`. ### Syntax @@ -295,6 +299,8 @@ Create a vector of the `integer/real` type with evenly spaced values within a gi ### Arguments +All arguments should be the same type and kind. + `start`: Shall be an `integer/real` scalar. This is an `intent(in)` argument. The default `start` value is `1`. @@ -313,8 +319,9 @@ If `by < 0`, the `by` argument will be corrected to `abs(by)` by the internal pr ### Return value -Return a vector of evenly spaced values. +Return a vector of fixed spaced spaced values. +For `integer` type arguments, the length of the result vector is `(end - start)/by + 1`. For `real` type arguments, the length of the result vector is `floor((end - start)/by) + 1`. ### Example @@ -331,7 +338,7 @@ program demo_math_arange print *, arange(3.0) !! [1.0,2.0,3.0] print *, arange(0.0,5.0) !! [0.0,1.0,2.0,3.0,4.0,5.0] - print *, arange(0.0,5.0,2.0) !! [0.0,2.0,4.0] + print *, arange(0.0,6.0,2.5) !! [0.0,2.5,5.0] print *, (1.0,1.0)*arange(3) !! [(1.0,1.0),(2.0,2.0),[3.0,3.0]] diff --git a/src/stdlib_math.fypp b/src/stdlib_math.fypp index 2fcd5afde..1ed901d22 100644 --- a/src/stdlib_math.fypp +++ b/src/stdlib_math.fypp @@ -266,9 +266,7 @@ module stdlib_math !> !> `arange` creates a vector of the `integer/real` type !> with evenly spaced values within a given interval. - !> ([Specification](../page/specs/stdlib_math.html# - !>arange-create-a-vector-of-the-integerreal-type- - !>with-evenly-spaced-values-within-a-given-interval)) + !> ([Specification](../page/specs/stdlib_math.html#arange)) interface arange #:set RI_KINDS_TYPES = REAL_KINDS_TYPES + INT_KINDS_TYPES #:for k1, t1 in RI_KINDS_TYPES diff --git a/src/stdlib_math_arange.fypp b/src/stdlib_math_arange.fypp index 0fddd503f..a63cd58c7 100644 --- a/src/stdlib_math_arange.fypp +++ b/src/stdlib_math_arange.fypp @@ -1,8 +1,6 @@ #:include "common.fypp" submodule(stdlib_math) stdlib_math_arange - implicit none - contains #:for k1, t1 in REAL_KINDS_TYPES From bac5e860edab1c4b01f4f841029e08455717c924 Mon Sep 17 00:00:00 2001 From: zoziha13 <1325686572@qq.com> Date: Thu, 5 Aug 2021 11:17:57 +0800 Subject: [PATCH 4/5] Update `arange` func and doc: 1. `merge` -> `optval` inside. 2. `by` -> `step` argument name. --- doc/specs/stdlib_math.md | 18 +++++++++--------- src/Makefile.manual | 6 +++--- src/stdlib_math.fypp | 9 +++++---- src/stdlib_math_arange.fypp | 32 ++++++++++++++++---------------- 4 files changed, 33 insertions(+), 32 deletions(-) diff --git a/doc/specs/stdlib_math.md b/doc/specs/stdlib_math.md index 2a70a08bb..646989d51 100644 --- a/doc/specs/stdlib_math.md +++ b/doc/specs/stdlib_math.md @@ -287,7 +287,7 @@ Pure function. ### Description -Create a vector of the `integer/real` type with given fixed spaced values within a given interval. +Create a one-dimensional `array` of the `integer/real` type with fixed-spaced values of given spacing, within a given interval. #### Note @@ -295,7 +295,7 @@ Because of the `i` (`huge(integer :: i) = 2147483647`) index inside the `arange` ### Syntax -`result = [[stdlib_math(module):arange(interface)]](start [, end, by])` +`result = [[stdlib_math(module):arange(interface)]](start [, end, step])` ### Arguments @@ -309,20 +309,20 @@ The default `start` value is `1`. This is an `intent(in)` and `optional` argument. The default `end` value is the inputted `start` value. -`by`: Shall be an `integer/real` scalar and large than `0`. +`step`: Shall be an `integer/real` scalar and large than `0`. This is an `intent(in)` and `optional` argument. -The default `by` value is `1`. +The default `step` value is `1`. #### Warning -If `by = 0`, the `by` argument will be corrected to `1/1.0` by the internal process of the `arange` function. -If `by < 0`, the `by` argument will be corrected to `abs(by)` by the internal process of the `arange` function. +If `step = 0`, the `step` argument will be corrected to `1/1.0` by the internal process of the `arange` function. +If `step < 0`, the `step` argument will be corrected to `abs(by)` by the internal process of the `arange` function. ### Return value -Return a vector of fixed spaced spaced values. +Return a one-dimensional `array` of fixed-spaced values. -For `integer` type arguments, the length of the result vector is `(end - start)/by + 1`. -For `real` type arguments, the length of the result vector is `floor((end - start)/by) + 1`. +For `integer` type arguments, the length of the result vector is `(end - start)/step + 1`. +For `real` type arguments, the length of the result vector is `floor((end - start)/step) + 1`. ### Example diff --git a/src/Makefile.manual b/src/Makefile.manual index 1dad165c2..9e78df5d8 100644 --- a/src/Makefile.manual +++ b/src/Makefile.manual @@ -150,12 +150,12 @@ 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: \ stdlib_math_linspace.o stdlib_math_arange.o: \ - stdlib_math.o \ - stdlib_kinds.o + stdlib_math.o stdlib_linalg_outer_product.o: stdlib_linalg.o diff --git a/src/stdlib_math.fypp b/src/stdlib_math.fypp index 1ed901d22..2ca0f543d 100644 --- a/src/stdlib_math.fypp +++ b/src/stdlib_math.fypp @@ -4,6 +4,7 @@ module stdlib_math use stdlib_kinds, only: int8, int16, int32, int64, sp, dp, qp + use stdlib_optval, only: optval implicit none private @@ -264,15 +265,15 @@ module stdlib_math !> Version: experimental !> - !> `arange` creates a vector of the `integer/real` type - !> with evenly spaced values within a given interval. + !> `arange` creates a one-dimensional `array` of the `integer/real` type + !> with fixed-spaced values of given spacing, within a given interval. !> ([Specification](../page/specs/stdlib_math.html#arange)) interface arange #:set RI_KINDS_TYPES = REAL_KINDS_TYPES + INT_KINDS_TYPES #:for k1, t1 in RI_KINDS_TYPES - pure module function arange_${t1[0]}$_${k1}$(start, end, by) result(result) + pure module function arange_${t1[0]}$_${k1}$(start, end, step) result(result) ${t1}$, intent(in) :: start - ${t1}$, intent(in), optional :: end, by + ${t1}$, intent(in), optional :: end, step ${t1}$, allocatable :: result(:) end function arange_${t1[0]}$_${k1}$ #:endfor diff --git a/src/stdlib_math_arange.fypp b/src/stdlib_math_arange.fypp index a63cd58c7..075d76f7a 100644 --- a/src/stdlib_math_arange.fypp +++ b/src/stdlib_math_arange.fypp @@ -6,23 +6,23 @@ contains #:for k1, t1 in REAL_KINDS_TYPES !> `arange` creates a vector of the `${t1}$` type !> with evenly spaced values within a given interval. - pure module function arange_${t1[0]}$_${k1}$(start, end, by) result(result) + pure module function arange_${t1[0]}$_${k1}$(start, end, step) result(result) ${t1}$, intent(in) :: start - ${t1}$, intent(in), optional :: end, by + ${t1}$, intent(in), optional :: end, step ${t1}$, allocatable :: result(:) - ${t1}$ :: start_, end_, by_ + ${t1}$ :: start_, end_, step_ integer :: i start_ = merge(start, 1.0_${k1}$, present(end)) - end_ = merge(end, start, present(end)) - by_ = sign(merge(merge(by, 1.0_${k1}$, by /= 0.0_${k1}$), & - 1.0_${k1}$, present(by)), end_ - start_) + end_ = optval(end, start) + step_ = optval(step, 1.0_${k1}$) + step_ = sign(merge(step_, 1.0_${k1}$, step_ /= 0.0_${k1}$), end_ - start_) - allocate(result(floor((end_ - start_)/by_) + 1)) + allocate(result(floor((end_ - start_)/step_) + 1)) - result = [(start_ + (i - 1)*by_, i=1, size(result), 1)] + result = [(start_ + (i - 1)*step_, i=1, size(result), 1)] end function arange_${t1[0]}$_${k1}$ #:endfor @@ -30,23 +30,23 @@ contains #:for k1, t1 in INT_KINDS_TYPES !> `arange` creates a vector of the `${t1}$` type !> with evenly spaced values within a given interval. - pure module function arange_${t1[0]}$_${k1}$(start, end, by) result(result) + pure module function arange_${t1[0]}$_${k1}$(start, end, step) result(result) ${t1}$, intent(in) :: start - ${t1}$, intent(in), optional :: end, by + ${t1}$, intent(in), optional :: end, step ${t1}$, allocatable :: result(:) - ${t1}$ :: start_, end_, by_ + ${t1}$ :: start_, end_, step_ ${t1}$ :: i start_ = merge(start, 1_${k1}$, present(end)) - end_ = merge(end, start, present(end)) - by_ = sign(merge(merge(by, 1_${k1}$, by /= 0_${k1}$), & - 1_${k1}$, present(by) ), end_ - start_) + end_ = optval(end, start) + step_ = optval(step, 1_${k1}$) + step_ = sign(merge(step_, 1_${k1}$, step_ /= 0_${k1}$), end_ - start_) - allocate(result((end_ - start_)/by_ + 1)) + allocate(result((end_ - start_)/step_ + 1)) - result = [(i, i=start_, end_, by_)] + result = [(i, i=start_, end_, step_)] end function arange_${t1[0]}$_${k1}$ #:endfor From 55da7c004b5bde1081ed1d76a648a76c7e34b5f9 Mon Sep 17 00:00:00 2001 From: zoziha13 <1325686572@qq.com> Date: Fri, 6 Aug 2021 21:57:58 +0800 Subject: [PATCH 5/5] Update `arange` doc: Fix some typos. --- doc/specs/stdlib_math.md | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/doc/specs/stdlib_math.md b/doc/specs/stdlib_math.md index 646989d51..8d7fb516b 100644 --- a/doc/specs/stdlib_math.md +++ b/doc/specs/stdlib_math.md @@ -287,11 +287,7 @@ Pure function. ### Description -Create a one-dimensional `array` of the `integer/real` type with fixed-spaced values of given spacing, within a given interval. - -#### Note - -Because of the `i` (`huge(integer :: i) = 2147483647`) index inside the `arange` function , the dimensional maximum length of array created by the `arange` function is `2147483647`. +Creates a one-dimensional `array` of the `integer/real` type with fixed-spaced values of given spacing, within a given interval. ### Syntax @@ -315,11 +311,11 @@ The default `step` value is `1`. #### Warning If `step = 0`, the `step` argument will be corrected to `1/1.0` by the internal process of the `arange` function. -If `step < 0`, the `step` argument will be corrected to `abs(by)` by the internal process of the `arange` function. +If `step < 0`, the `step` argument will be corrected to `abs(step)` by the internal process of the `arange` function. ### Return value -Return a one-dimensional `array` of fixed-spaced values. +Returns a one-dimensional `array` of fixed-spaced values. For `integer` type arguments, the length of the result vector is `(end - start)/step + 1`. For `real` type arguments, the length of the result vector is `floor((end - start)/step) + 1`. @@ -342,8 +338,8 @@ program demo_math_arange print *, (1.0,1.0)*arange(3) !! [(1.0,1.0),(2.0,2.0),[3.0,3.0]] - print *, arange(0.0,2.0,-2.0) !! [0.0,2.0]. Not recommended: `by` argument is negative! - print *, arange(0.0,2.0,0.0) !! [0.0,1.0,2.0]. Not recommended: `by` argument is zero! + print *, arange(0.0,2.0,-2.0) !! [0.0,2.0]. Not recommended: `step` argument is negative! + print *, arange(0.0,2.0,0.0) !! [0.0,1.0,2.0]. Not recommended: `step` argument is zero! end program demo_math_arange ``` \ No newline at end of file