Skip to content

Commit 780944f

Browse files
committed
Add seq function.
1 parent ce3a106 commit 780944f

File tree

8 files changed

+194
-2
lines changed

8 files changed

+194
-2
lines changed

doc/specs/stdlib_math.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,61 @@ program demo_logspace_rstart_cbase
275275
276276
end program demo_logspace_rstart_cbase
277277
```
278+
## `seq` - Creates an vector of `integer/real` type with evenly spaced values within a given interval.
279+
280+
### Status
281+
282+
Experimental
283+
284+
### Class
285+
286+
Pure function.
287+
288+
### Description
289+
290+
Creates an vector of `integer/real` type with evenly spaced values within a given interval.
291+
292+
### Syntax
293+
294+
`result = [[stdlib_math(module):seq(interface)]](start [, end, by])`
295+
296+
### Arguments
297+
298+
`start`: Shall be an `integer/real` scalar.
299+
This is an `intent(in)` argument.
300+
301+
`end`: Shall be an `integer/real` scalar.
302+
This is an `intent(in)` and `optional` argument.
303+
304+
`by`: Shall be an `integer/real` scalar and large than `0`.
305+
This is an `intent(in)` and `optional` argument.
306+
307+
Warning:
308+
If `by = 0`, the `by` argument will be corrected to `1/1.0` by the internal process of the `seq` function.
309+
If `by < 0`, the `by` argument will be corrected to `abs(by)` by the internal process of the `seq` function.
310+
311+
### Return value
312+
313+
Vector of evenly spaced values.
314+
315+
For floating point arguments, the length of the result is `floor((end - start)/by) + 1`.
316+
317+
### Example
318+
319+
```fortran
320+
program demo_math_seq
321+
use stdlib_math, only: seq
322+
323+
print *, seq(3) !! [1,2,3]
324+
print *, seq(3.0) !! [1.0,2.0,3.0]
325+
print *, seq(-1) !! [1,0,-1]
326+
print *, seq(0,2) !! [0,1,2]
327+
print *, seq(1,-1) !! [1,0,-1]
328+
print *, seq(0, 2, 2) !! [0,2]
329+
print *, (1.0,1.0)*seq(3) !! [(1.0,1.0),(2.0,2.0),[3.0,3.0]]
330+
331+
print *, seq(0.0,2.0,-2.0) !! [0.0,2.0]. Not recommended: `by` argument is negative!
332+
print *, seq(0.0,2.0,0.0) !! [0.0,1.0]. Not recommended: `by` argument is zero!
333+
334+
end program demo_math_seq
335+
```

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ set(fppFiles
3232
stdlib_math.fypp
3333
stdlib_math_linspace.fypp
3434
stdlib_math_logspace.fypp
35+
stdlib_math_seq.fypp
3536
stdlib_string_type.fypp
3637
)
3738

src/Makefile.manual

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ SRCFYPP =\
77
stdlib_linalg.fypp \
88
stdlib_linalg_diag.fypp \
99
stdlib_linalg_outer_product.fypp \
10+
stdlib_math_seq.fypp \
1011
stdlib_optval.fypp \
1112
stdlib_quadrature.fypp \
1213
stdlib_quadrature_trapz.fypp \
@@ -154,4 +155,7 @@ stdlib_math_linspace.o: \
154155
stdlib_math.o
155156
stdlib_math_logspace.o: \
156157
stdlib_math_linspace.o
158+
stdlib_math_seq.o: \
159+
stdlib_math.o \
160+
stdlib_kinds.o
157161
stdlib_linalg_outer_product.o: stdlib_linalg.o

src/stdlib_math.fypp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module stdlib_math
1010
public :: clip, linspace, logspace
1111
public :: EULERS_NUMBER_SP, EULERS_NUMBER_DP, EULERS_NUMBER_QP
1212
public :: DEFAULT_LINSPACE_LENGTH, DEFAULT_LOGSPACE_BASE, DEFAULT_LOGSPACE_LENGTH
13+
public :: seq
1314

1415
integer, parameter :: DEFAULT_LINSPACE_LENGTH = 100
1516
integer, parameter :: DEFAULT_LOGSPACE_LENGTH = 50
@@ -261,6 +262,21 @@ module stdlib_math
261262

262263
end interface
263264

265+
!> Version: experimental
266+
!>
267+
!> `seq` creates an vector of `integer/real` type
268+
!> with evenly spaced values within a given interval.
269+
interface seq
270+
#:set RI_KINDS_TYPES = REAL_KINDS_TYPES + INT_KINDS_TYPES
271+
#:for k1, t1 in RI_KINDS_TYPES
272+
pure module function seq_${t1[0]}$_${k1}$(start, end, by) result(result)
273+
${t1}$, intent(in) :: start
274+
${t1}$, intent(in), optional :: end, by
275+
${t1}$, allocatable :: result(:)
276+
end function seq_${t1[0]}$_${k1}$
277+
#:endfor
278+
end interface seq
279+
264280
contains
265281

266282
#:for k1, t1 in IR_KINDS_TYPES

src/stdlib_math_seq.fypp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#:include "common.fypp"
2+
submodule(stdlib_math) stdlib_math_seq
3+
4+
implicit none
5+
6+
contains
7+
8+
#:for k1, t1 in REAL_KINDS_TYPES
9+
!> `seq` creates an vector of `${t1}$` type
10+
!> with evenly spaced values within a given interval.
11+
pure module function seq_${t1[0]}$_${k1}$(start, end, by) result(result)
12+
13+
${t1}$, intent(in) :: start
14+
${t1}$, intent(in), optional :: end, by
15+
${t1}$, allocatable :: result(:)
16+
17+
${t1}$ :: start_, end_, by_
18+
integer :: i
19+
20+
start_ = merge(start, 1.0_${k1}$, present(end))
21+
end_ = merge(end, start, present(end))
22+
by_ = sign(merge(merge(by, 1.0_${k1}$, by /= 0.0_${k1}$), &
23+
1.0_${k1}$, present(by)), end_ - start_)
24+
25+
allocate(result(floor((end_ - start_)/by_) + 1))
26+
#!TODO: ??
27+
#! floor or ceiling, floor is better.
28+
29+
result = [(start_ + (i - 1)*by_, i=1, size(result), 1)]
30+
31+
end function seq_${t1[0]}$_${k1}$
32+
#:endfor
33+
34+
#:for k1, t1 in INT_KINDS_TYPES
35+
!> `seq` creates an vector of `${t1}$` type
36+
!> with evenly spaced values within a given interval.
37+
pure module function seq_${t1[0]}$_${k1}$(start, end, by) result(result)
38+
39+
${t1}$, intent(in) :: start
40+
${t1}$, intent(in), optional :: end, by
41+
${t1}$, allocatable :: result(:)
42+
43+
${t1}$ :: start_, end_, by_
44+
${t1}$ :: i
45+
46+
start_ = merge(start, 1_${k1}$, present(end))
47+
end_ = merge(end, start, present(end))
48+
by_ = sign(merge(merge(by, 1_${k1}$, by /= 0_${k1}$), &
49+
1_${k1}$, present(by) ), end_ - start_)
50+
51+
allocate(result((end_ - start_)/by_ + 1))
52+
53+
result = [(i, i=start_, end_, by_)]
54+
55+
end function seq_${t1[0]}$_${k1}$
56+
#:endfor
57+
58+
end submodule stdlib_math_seq

src/tests/math/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
ADDTEST(stdlib_math)
22
ADDTEST(linspace)
3-
ADDTEST(logspace)
3+
ADDTEST(logspace)
4+
ADDTEST(math_seq)

src/tests/math/Makefile.manual

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
PROGS_SRC = test_stdlib_math.f90 test_linspace.f90 test_logspace.f90
1+
PROGS_SRC = test_stdlib_math.f90 test_linspace.f90 test_logspace.f90 \
2+
test_math_seq.f90
23

34

45
include ../Makefile.manual.test.mk

src/tests/math/test_math_seq.f90

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
!> SPDX-Identifier: MIT
2+
module test_math_seq
3+
4+
use stdlib_error, only: check
5+
use stdlib_math, only: seq
6+
implicit none
7+
8+
logical, private :: warn = .false.
9+
10+
contains
11+
12+
subroutine test_math_seq_real
13+
!> Normal
14+
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)
15+
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)
16+
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)
17+
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)
18+
call check(all(seq(1.0, 1.0) == [1.0]), msg="all(seq(1.0,1.0) == [1.0]) failed.", warn=warn)
19+
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)
20+
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)
21+
!> Not recommended
22+
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)
23+
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)
24+
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)
25+
end subroutine test_math_seq_real
26+
27+
subroutine test_math_seq_integer
28+
!> Normal
29+
call check(all(seq(3) == [1, 2, 3]), msg="all(seq(3) == [1,2,3]) failed.", warn=warn)
30+
call check(all(seq(-1) == [1, 0, -1]), msg="all(seq(-1) == [1,0,-1]) failed.", warn=warn)
31+
call check(all(seq(0, 2) == [0, 1, 2]), msg="all(seq(0,2) == [0,1,2]) failed.", warn=warn)
32+
call check(all(seq(1, -1) == [1, 0, -1]), msg="all(seq(1,-1) == [1,0,-1]) failed.", warn=warn)
33+
call check(all(seq(1, 1) == [1]), msg="all(seq(1,1) == [1]) failed.", warn=warn)
34+
call check(all(seq(0, 2, 2) == [0, 2]), msg="all(seq(0,2,2) == [0,2]) failed.", warn=warn)
35+
call check(all(seq(1, -1, 2) == [1, -1]), msg="all(seq(1,-1,2) == [1,-1]) failed.", warn=warn)
36+
!> Not recommended
37+
call check(all(seq(0, 2, -2) == [0, 2]), msg="all(seq(0,2,-2) == [0,2]) failed.", warn=warn)
38+
call check(all(seq(1, -1, -2) == [1, -1]), msg="all(seq(1,-1,-2) == [1,-1]) failed.", warn=warn)
39+
call check(all(seq(0, 2, 0) == [0,1,2]), msg="all(seq(0, 2, 0) == [0,1,2]) failed.", warn=warn)
40+
end subroutine test_math_seq_integer
41+
42+
end module test_math_seq
43+
44+
program tester
45+
46+
use test_math_seq
47+
48+
call test_math_seq_real
49+
call test_math_seq_integer
50+
51+
print *, "All tests in `test_math_seq` passed."
52+
53+
end program tester

0 commit comments

Comments
 (0)