From 4bbf07b9f66622dc9776022d63341bc166efcaa0 Mon Sep 17 00:00:00 2001 From: Ivan Girault Date: Wed, 17 Jan 2024 15:57:54 +0100 Subject: [PATCH 1/6] WIP: first proposal WIP: first_proposal --- doc/specs/stdlib_math.md | 56 +++++++++++++ example/math/CMakeLists.txt | 1 + example/math/example_meshgrid.f90 | 37 +++++++++ src/CMakeLists.txt | 1 + src/stdlib_math.fypp | 26 ++++++- src/stdlib_math_meshgrid.fypp | 50 ++++++++++++ test/math/CMakeLists.txt | 2 + test/math/test_meshgrid.fypp | 125 ++++++++++++++++++++++++++++++ 8 files changed, 297 insertions(+), 1 deletion(-) create mode 100644 example/math/example_meshgrid.f90 create mode 100644 src/stdlib_math_meshgrid.fypp create mode 100644 test/math/test_meshgrid.fypp diff --git a/doc/specs/stdlib_math.md b/doc/specs/stdlib_math.md index eb7b7cc2f..1b1611a11 100644 --- a/doc/specs/stdlib_math.md +++ b/doc/specs/stdlib_math.md @@ -554,3 +554,59 @@ When both `prepend` and `append` are not present, the result `y` has one fewer e ```fortran {!example/math/example_diff.f90!} ``` + +### `meshgrid` subroutine + +#### Description + +Computes a list of coordinate matrices from coordinate vectors. + +For $n \geq 1$ coordinate vectors $(x_1, x_2, ..., x_n)$ of sizes $(s_1, s_2, ..., s_n)$, `meshgrid` computes $N$ coordinate matrices $(X_1, X_2, ..., X_n)$ with identical shape corresponding to the selected indexing: +- Cartesian indexing (default behavior): the shape of the coordinate matrices is $(s_2, s_1, s_3, s_4, ... s_n)$. +- matrix indexing: the shape of the coordinate matrices is $(s_1, s_2, s_3, s_4, ... s_n)$. + +#### Syntax + +For a 2D problem in Cartesian indexing: +`call [[stdlib_math(module):meshgrid(interface)]](x, y, xm, ym)` + +For a 3D problem in Cartesian indexing: +`call [[stdlib_math(module):meshgrid(interface)]](x, y, z, xm, ym, zm)` + +For a 3D problem in matrix indexing: +`call [[stdlib_math(module):meshgrid(interface)]](x, y, z, xm, ym, zm, indexing="ij")` + +The subroutine can be called in $n$-dimensional situations, as long as $n$ is inferior to the maximum allowed array rank. + +#### Status + +Experimental. + +#### Class + +Subroutine. + +#### Arguments + +For a `n`-dimensional problem, with `n >= 1`: + +`x1, x2, ..., xn`: The coordinate vectors. +Shall be a `real/integer` and `rank-1` array. +These arguments are `intent(in)`. + +`xm1, xm2, ..., xmn`: The coordinate matrices. +Shall be `real/integer` arrays of adequate shape: +- for Cartesian indexing, the shape of the coordinate matrices must be `[size(x2), size(x1), size(x3), ..., size(xn)]`. +- for matrix indexing, the shape of the coordinate matrices must be `[size(x1), size(x2), size(x3), ..., size(xn)]`. + +These argument are `intent(out)`. + +`indexing`: the selected indexing. +Shall be a `character(len=2)` equal to `"xy"` for Cartesian indexing (default), or `"ij"` for matrix indexing. +This argument is `intent(in)` and `optional`, and is equal to `"xy"` by default. + +#### Example + +```fortran +{!example/math/example_meshgrid.f90!} +``` \ No newline at end of file diff --git a/example/math/CMakeLists.txt b/example/math/CMakeLists.txt index a75f193f4..65225ff85 100644 --- a/example/math/CMakeLists.txt +++ b/example/math/CMakeLists.txt @@ -13,3 +13,4 @@ ADD_EXAMPLE(math_argd) ADD_EXAMPLE(math_arg) ADD_EXAMPLE(math_argpi) ADD_EXAMPLE(math_is_close) +ADD_EXAMPLE(meshgrid) diff --git a/example/math/example_meshgrid.f90 b/example/math/example_meshgrid.f90 new file mode 100644 index 000000000..fe96a5977 --- /dev/null +++ b/example/math/example_meshgrid.f90 @@ -0,0 +1,37 @@ +program example_meshgrid + + use stdlib_math, only: meshgrid, linspace + use stdlib_kinds, only: sp + + implicit none + + integer, parameter :: nx = 3, ny = 2 + real(sp) :: x(nx), y(ny), & + xm_cart(ny, nx), ym_cart(ny, nx), & + xm_mat(nx, ny), ym_mat(nx, ny) + + x = linspace(0_sp, 1_sp, nx) + y = linspace(0_sp, 1_sp, ny) + + call meshgrid(x, y, xm_cart, ym_cart) + print *, "xm_cart = " + call print_2d_array(xm_cart) + print *, "ym_cart = " + call print_2d_array(ym_cart) + + call meshgrid(x, y, xm_mat, ym_mat, indexing="ij") + print *, "xm_mat = " + call print_2d_array(xm_mat) + print *, "ym_mat = " + call print_2d_array(ym_mat) + +contains + subroutine print_2d_array(array) + real(sp), intent(in) :: array(:, :) + integer :: i + + do i = 1, size(array, dim=1) + print *, array(i, :) + end do + end subroutine +end program example_meshgrid diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8a6fe66cc..19ec9e173 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -55,6 +55,7 @@ set(fppFiles stdlib_math_is_close.fypp stdlib_math_all_close.fypp stdlib_math_diff.fypp + stdlib_math_meshgrid.fypp stdlib_string_type.fypp stdlib_string_type_constructor.fypp stdlib_strings_to_string.fypp diff --git a/src/stdlib_math.fypp b/src/stdlib_math.fypp index c75b4d9f5..4cee0387f 100644 --- a/src/stdlib_math.fypp +++ b/src/stdlib_math.fypp @@ -14,7 +14,7 @@ module stdlib_math public :: EULERS_NUMBER_QP #:endif public :: DEFAULT_LINSPACE_LENGTH, DEFAULT_LOGSPACE_BASE, DEFAULT_LOGSPACE_LENGTH - public :: arange, arg, argd, argpi, is_close, all_close, diff + public :: arange, arg, argd, argpi, is_close, all_close, diff, meshgrid integer, parameter :: DEFAULT_LINSPACE_LENGTH = 100 integer, parameter :: DEFAULT_LOGSPACE_LENGTH = 50 @@ -382,6 +382,30 @@ module stdlib_math #:endfor end interface diff + + !> Version: experimental + !> + !> Computes a list of coordinate matrices from coordinate vectors. + !> ([Specification](../page/specs/stdlib_math.html#meshgrid)) + interface meshgrid + #:set RANKS = range(1, MAXRANK + 1) + #:for k1, t1 in IR_KINDS_TYPES + #:for rank in RANKS + #:set RName = rname("meshgrid", rank, t1, k1) + module subroutine ${RName}$(& + ${"".join(f"x{i}, " for i in range(1, rank + 1))}$ & + ${"".join(f"xm{i}, " for i in range(1, rank + 1))}$ & + indexing & + ) + #:for i in range(1, rank + 1) + ${t1}$, intent(in) :: x${i}$(:) + ${t1}$, intent(out) :: xm${i}$ ${ranksuffix(rank)}$ + #:endfor + character(len=2), intent(in), optional :: indexing + end subroutine ${RName}$ + #:endfor + #:endfor + end interface meshgrid contains #:for k1, t1 in IR_KINDS_TYPES diff --git a/src/stdlib_math_meshgrid.fypp b/src/stdlib_math_meshgrid.fypp new file mode 100644 index 000000000..d3c7b2230 --- /dev/null +++ b/src/stdlib_math_meshgrid.fypp @@ -0,0 +1,50 @@ +#:include "common.fypp" +#:set IR_KINDS_TYPES = INT_KINDS_TYPES + REAL_KINDS_TYPES +#:set RANKS = range(1, MAXRANK + 1) + +#:def meshgrid_loop(indices) + #:for j in reversed(indices) + do i${j}$ = 1, size(x${j}$) + #:endfor + #:for j in indices + xm${j}$(${"".join(f"i{j}," for j in indices).removesuffix(",")}$) = & + x${j}$(i${j}$) + #:endfor + #:for j in indices + end do + #:endfor +#:enddef + +submodule(stdlib_math) stdlib_math_meshgrid + +contains + + #:for k1, t1 in IR_KINDS_TYPES + #:for rank in RANKS + #:if rank == 1 + #:set XY_INDICES = [1] + #:set IJ_INDICES = [1] + #:else + #:set XY_INDICES = [2, 1] + [j for j in range(3, rank + 1)] + #:set IJ_INDICES = [1, 2] + [j for j in range(3, rank + 1)] + #:endif + #: set RName = rname("meshgrid", rank, t1, k1) + module procedure ${RName}$ + use stdlib_optval, only: optval + use stdlib_error, only: error_stop + + integer :: ${"".join(f"i{j}," for j in range(1, rank + 1)).removesuffix(",")}$ + + select case (optval(indexing, "xy")) + case ("xy") + $:meshgrid_loop(XY_INDICES) + case ("ij") + $:meshgrid_loop(IJ_INDICES) + case default + call error_stop("ERROR (meshgrid): unexpected indexing.") + end select + end procedure + #:endfor + #:endfor + +end submodule \ No newline at end of file diff --git a/test/math/CMakeLists.txt b/test/math/CMakeLists.txt index 9f9683516..315bb084a 100644 --- a/test/math/CMakeLists.txt +++ b/test/math/CMakeLists.txt @@ -1,9 +1,11 @@ set( fppFiles "test_stdlib_math.fypp" + "test_meshgrid.fypp" ) fypp_f90("${fyppFlags}" "${fppFiles}" outFiles) ADDTEST(stdlib_math) ADDTEST(linspace) ADDTEST(logspace) +ADDTEST(meshgrid) diff --git a/test/math/test_meshgrid.fypp b/test/math/test_meshgrid.fypp new file mode 100644 index 000000000..083596a2d --- /dev/null +++ b/test/math/test_meshgrid.fypp @@ -0,0 +1,125 @@ +! SPDX-Identifier: MIT + +#:include "common.fypp" +#:set IR_KINDS_TYPES = INT_KINDS_TYPES + REAL_KINDS_TYPES +#:set RANKS = range(1, MAXRANK + 1) +#:set INDEXINGS = ["default", "xy", "ij"] + +#:def OPTIONAL_PART_IN_SIGNATURE(indexing) +#:if indexing in ("xy", "ij") + ${f', "{indexing}"'}$ +#:endif +#:enddef + +module test_meshgrid + use testdrive, only : new_unittest, unittest_type, error_type, check + use stdlib_math, only: meshgrid + use stdlib_kinds, only: int8, int16, int32, int64, sp, dp, xdp, qp + implicit none + + public :: collect_meshgrid + + #:for k1 in REAL_KINDS + real(kind=${k1}$), parameter :: PI_${k1}$ = acos(-1.0_${k1}$) + #:endfor + +contains + + !> Collect all exported unit tests + subroutine collect_meshgrid(testsuite) + !> Collection of tests + type(unittest_type), allocatable, intent(out) :: testsuite(:) + + testsuite = [ & + #:for k1, t1 in IR_KINDS_TYPES + #:for rank in RANKS + #:for INDEXING in INDEXINGS + #: set RName = rname(f"meshgrid_{INDEXING}", rank, t1, k1) + new_unittest("${RName}$", test_${RName}$), & + #:endfor + #:endfor + #:endfor + new_unittest("dummy", test_dummy) & + ] + + end subroutine collect_meshgrid + + #:for k1, t1 in IR_KINDS_TYPES + #:for rank in RANKS + #:for INDEXING in INDEXINGS + #:if rank == 1 + #:set INDICES = [1] + #:else + #:if INDEXING in ("default", "xy") + #:set INDICES = [2, 1] + [j for j in range(3, rank + 1)] + #:elif INDEXING == "ij" + #:set INDICES = [1, 2] + [j for j in range(3, rank + 1)] + #:endif + #:endif + #: set RName = rname(f"meshgrid_{INDEXING}", rank, t1, k1) + #: set GRIDSHAPE = "".join("length," for j in range(rank)).removesuffix(",") + subroutine test_${RName}$(error) + !> Error handling + type(error_type), allocatable, intent(out) :: error + integer, parameter :: length = 3 + ${t1}$ :: ${"".join(f"x{j}(length)," for j in range(1, rank + 1)).removesuffix(",")}$ + ${t1}$ :: ${"".join(f"xm{j}({GRIDSHAPE})," for j in range(1, rank + 1)).removesuffix(",")}$ + ${t1}$ :: ${"".join(f"xm{j}_exact({GRIDSHAPE})," for j in range(1, rank + 1)).removesuffix(",")}$ + integer :: i + integer :: ${"".join(f"i{j}," for j in range(1, rank + 1)).removesuffix(",")}$ + ${t1}$, parameter :: ZERO = 0 + ! valid test case + #:for index in range(1, rank + 1) + x${index}$ = [(i, i = length * ${index - 1}$ + 1, length * ${index}$)] + #:endfor + #:for j in range(1, rank + 1) + xm${j}$_exact = reshape( & + [${"".join("(" for dummy in range(rank)) + f"x{j}(i{j})" + "".join(f", i{index} = 1, size(x{index}))" for index in INDICES)}$], & + shape=[${GRIDSHAPE}$] & + ) + #:endfor + call meshgrid( & + ${"".join(f"x{j}," for j in range(1, rank + 1))}$ & + ${"".join(f"xm{j}," for j in range(1, rank + 1)).removesuffix(",")}$ & + ${OPTIONAL_PART_IN_SIGNATURE(INDEXING)}$ ) + #:for j in range(1, rank + 1) + call check(error, abs(maxval(xm${j}$ - xm${j}$_exact)), ZERO) + if (allocated(error)) return + #:endfor + end subroutine test_${RName}$ + #:endfor + #:endfor + #:endfor + + subroutine test_dummy(error) + !> Error handling + type(error_type), allocatable, intent(out) :: error + end subroutine + +end module test_meshgrid + +program tester + use, intrinsic :: iso_fortran_env, only : error_unit + use testdrive, only : run_testsuite, new_testsuite, testsuite_type + use test_meshgrid, only : collect_meshgrid + implicit none + integer :: stat, is + type(testsuite_type), allocatable :: testsuites(:) + character(len=*), parameter :: fmt = '("#", *(1x, a))' + + stat = 0 + + testsuites = [ & + new_testsuite("meshgrid", collect_meshgrid) & + ] + + do is = 1, size(testsuites) + write(error_unit, fmt) "Testing:", testsuites(is)%name + call run_testsuite(testsuites(is)%collect, error_unit, stat) + end do + + if (stat > 0) then + write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" + error stop + end if +end program tester From 44c49ef91587d590f5853bb6323756708af090e0 Mon Sep 17 00:00:00 2001 From: Ivan Girault Date: Fri, 26 Jan 2024 10:42:16 +0100 Subject: [PATCH 2/6] typos in specs; correction of tests --- doc/specs/stdlib_math.md | 2 +- test/math/test_meshgrid.fypp | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/doc/specs/stdlib_math.md b/doc/specs/stdlib_math.md index 1b1611a11..0de8bb89c 100644 --- a/doc/specs/stdlib_math.md +++ b/doc/specs/stdlib_math.md @@ -591,7 +591,7 @@ Subroutine. For a `n`-dimensional problem, with `n >= 1`: `x1, x2, ..., xn`: The coordinate vectors. -Shall be a `real/integer` and `rank-1` array. +Shall be `real/integer` and `rank-1` arrays. These arguments are `intent(in)`. `xm1, xm2, ..., xmn`: The coordinate matrices. diff --git a/test/math/test_meshgrid.fypp b/test/math/test_meshgrid.fypp index 083596a2d..d056ee1b8 100644 --- a/test/math/test_meshgrid.fypp +++ b/test/math/test_meshgrid.fypp @@ -18,10 +18,6 @@ module test_meshgrid implicit none public :: collect_meshgrid - - #:for k1 in REAL_KINDS - real(kind=${k1}$), parameter :: PI_${k1}$ = acos(-1.0_${k1}$) - #:endfor contains @@ -56,8 +52,8 @@ contains #:set INDICES = [1, 2] + [j for j in range(3, rank + 1)] #:endif #:endif - #: set RName = rname(f"meshgrid_{INDEXING}", rank, t1, k1) - #: set GRIDSHAPE = "".join("length," for j in range(rank)).removesuffix(",") + #:set RName = rname(f"meshgrid_{INDEXING}", rank, t1, k1) + #:set GRIDSHAPE = "".join("length," for j in range(rank)).removesuffix(",") subroutine test_${RName}$(error) !> Error handling type(error_type), allocatable, intent(out) :: error @@ -83,7 +79,7 @@ contains ${"".join(f"xm{j}," for j in range(1, rank + 1)).removesuffix(",")}$ & ${OPTIONAL_PART_IN_SIGNATURE(INDEXING)}$ ) #:for j in range(1, rank + 1) - call check(error, abs(maxval(xm${j}$ - xm${j}$_exact)), ZERO) + call check(error, maxval(abs(xm${j}$ - xm${j}$_exact)), ZERO) if (allocated(error)) return #:endfor end subroutine test_${RName}$ From cb3fb2dc7bde745fb2ef138abff4a720761e410e Mon Sep 17 00:00:00 2001 From: Ivan Girault <68321973+Ivanou34@users.noreply.github.com> Date: Fri, 9 Feb 2024 13:19:45 +0100 Subject: [PATCH 3/6] Update doc/specs/stdlib_math.md Co-authored-by: Jeremie Vandenplas --- doc/specs/stdlib_math.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/specs/stdlib_math.md b/doc/specs/stdlib_math.md index 0de8bb89c..e83cd59e2 100644 --- a/doc/specs/stdlib_math.md +++ b/doc/specs/stdlib_math.md @@ -561,7 +561,7 @@ When both `prepend` and `append` are not present, the result `y` has one fewer e Computes a list of coordinate matrices from coordinate vectors. -For $n \geq 1$ coordinate vectors $(x_1, x_2, ..., x_n)$ of sizes $(s_1, s_2, ..., s_n)$, `meshgrid` computes $N$ coordinate matrices $(X_1, X_2, ..., X_n)$ with identical shape corresponding to the selected indexing: +For $n \geq 1$ coordinate vectors $(x_1, x_2, ..., x_n)$ of sizes $(s_1, s_2, ..., s_n)$, `meshgrid` computes $n$ coordinate matrices $(X_1, X_2, ..., X_n)$ with identical shape corresponding to the selected indexing: - Cartesian indexing (default behavior): the shape of the coordinate matrices is $(s_2, s_1, s_3, s_4, ... s_n)$. - matrix indexing: the shape of the coordinate matrices is $(s_1, s_2, s_3, s_4, ... s_n)$. From 3a21a7613ec06b3f00243a6dfd0c3b9871fe2785 Mon Sep 17 00:00:00 2001 From: Ivan Girault <68321973+Ivanou34@users.noreply.github.com> Date: Fri, 9 Feb 2024 13:20:24 +0100 Subject: [PATCH 4/6] Update doc/specs/stdlib_math.md Co-authored-by: Jeremie Vandenplas --- doc/specs/stdlib_math.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/specs/stdlib_math.md b/doc/specs/stdlib_math.md index e83cd59e2..a15e6b29e 100644 --- a/doc/specs/stdlib_math.md +++ b/doc/specs/stdlib_math.md @@ -576,7 +576,7 @@ For a 3D problem in Cartesian indexing: For a 3D problem in matrix indexing: `call [[stdlib_math(module):meshgrid(interface)]](x, y, z, xm, ym, zm, indexing="ij")` -The subroutine can be called in $n$-dimensional situations, as long as $n$ is inferior to the maximum allowed array rank. +The subroutine can be called in `n`-dimensional situations, as long as `n` is inferior to the maximum allowed array rank. #### Status From b7248d975954a11da0cf64f8a2b81fb8a0d62fda Mon Sep 17 00:00:00 2001 From: Ivan Girault <68321973+Ivanou34@users.noreply.github.com> Date: Fri, 9 Feb 2024 13:20:32 +0100 Subject: [PATCH 5/6] Update doc/specs/stdlib_math.md Co-authored-by: Jeremie Vandenplas --- doc/specs/stdlib_math.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/specs/stdlib_math.md b/doc/specs/stdlib_math.md index a15e6b29e..6c21b1cfd 100644 --- a/doc/specs/stdlib_math.md +++ b/doc/specs/stdlib_math.md @@ -595,7 +595,7 @@ Shall be `real/integer` and `rank-1` arrays. These arguments are `intent(in)`. `xm1, xm2, ..., xmn`: The coordinate matrices. -Shall be `real/integer` arrays of adequate shape: +Shall be arrays of type `real` or `integer` of adequate shape: - for Cartesian indexing, the shape of the coordinate matrices must be `[size(x2), size(x1), size(x3), ..., size(xn)]`. - for matrix indexing, the shape of the coordinate matrices must be `[size(x1), size(x2), size(x3), ..., size(xn)]`. From 853035828e6c3c2a0368d7d617beb7e9ae14433a Mon Sep 17 00:00:00 2001 From: Ivan Girault Date: Fri, 9 Feb 2024 16:11:17 +0100 Subject: [PATCH 6/6] modify optional argument; move to the top use statements in stdlib_math_meshgrid.fypp --- doc/specs/stdlib_math.md | 4 ++-- example/math/example_meshgrid.f90 | 4 ++-- src/stdlib_math.fypp | 6 +++++- src/stdlib_math_meshgrid.fypp | 10 +++++----- test/math/test_meshgrid.fypp | 4 ++-- 5 files changed, 16 insertions(+), 12 deletions(-) diff --git a/doc/specs/stdlib_math.md b/doc/specs/stdlib_math.md index 6c21b1cfd..cd31c8ca8 100644 --- a/doc/specs/stdlib_math.md +++ b/doc/specs/stdlib_math.md @@ -602,8 +602,8 @@ Shall be arrays of type `real` or `integer` of adequate shape: These argument are `intent(out)`. `indexing`: the selected indexing. -Shall be a `character(len=2)` equal to `"xy"` for Cartesian indexing (default), or `"ij"` for matrix indexing. -This argument is `intent(in)` and `optional`, and is equal to `"xy"` by default. +Shall be an `integer` equal to `stdlib_meshgrid_xy` for Cartesian indexing (default), or `stdlib_meshgrid_ij` for matrix indexing. `stdlib_meshgrid_xy` and `stdlib_meshgrid_ij` are public constants defined in the module. +This argument is `intent(in)` and `optional`, and is equal to `stdlib_meshgrid_xy` by default. #### Example diff --git a/example/math/example_meshgrid.f90 b/example/math/example_meshgrid.f90 index fe96a5977..7a3360bb9 100644 --- a/example/math/example_meshgrid.f90 +++ b/example/math/example_meshgrid.f90 @@ -1,6 +1,6 @@ program example_meshgrid - use stdlib_math, only: meshgrid, linspace + use stdlib_math, only: meshgrid, linspace, stdlib_meshgrid_ij use stdlib_kinds, only: sp implicit none @@ -19,7 +19,7 @@ program example_meshgrid print *, "ym_cart = " call print_2d_array(ym_cart) - call meshgrid(x, y, xm_mat, ym_mat, indexing="ij") + call meshgrid(x, y, xm_mat, ym_mat, indexing=stdlib_meshgrid_ij) print *, "xm_mat = " call print_2d_array(xm_mat) print *, "ym_mat = " diff --git a/src/stdlib_math.fypp b/src/stdlib_math.fypp index 4cee0387f..aeb988859 100644 --- a/src/stdlib_math.fypp +++ b/src/stdlib_math.fypp @@ -14,6 +14,7 @@ module stdlib_math public :: EULERS_NUMBER_QP #:endif public :: DEFAULT_LINSPACE_LENGTH, DEFAULT_LOGSPACE_BASE, DEFAULT_LOGSPACE_LENGTH + public :: stdlib_meshgrid_ij, stdlib_meshgrid_xy public :: arange, arg, argd, argpi, is_close, all_close, diff, meshgrid integer, parameter :: DEFAULT_LINSPACE_LENGTH = 100 @@ -32,6 +33,9 @@ module stdlib_math real(kind=${k1}$), parameter :: PI_${k1}$ = acos(-1.0_${k1}$) #:endfor + !> Values for optional argument `indexing` of `meshgrid` + integer, parameter :: stdlib_meshgrid_xy = 0, stdlib_meshgrid_ij = 1 + interface clip #:for k1, t1 in IR_KINDS_TYPES module procedure clip_${k1}$ @@ -401,7 +405,7 @@ module stdlib_math ${t1}$, intent(in) :: x${i}$(:) ${t1}$, intent(out) :: xm${i}$ ${ranksuffix(rank)}$ #:endfor - character(len=2), intent(in), optional :: indexing + integer, intent(in), optional :: indexing end subroutine ${RName}$ #:endfor #:endfor diff --git a/src/stdlib_math_meshgrid.fypp b/src/stdlib_math_meshgrid.fypp index d3c7b2230..04879486f 100644 --- a/src/stdlib_math_meshgrid.fypp +++ b/src/stdlib_math_meshgrid.fypp @@ -17,6 +17,8 @@ submodule(stdlib_math) stdlib_math_meshgrid + use stdlib_error, only: error_stop + contains #:for k1, t1 in IR_KINDS_TYPES @@ -30,15 +32,13 @@ contains #:endif #: set RName = rname("meshgrid", rank, t1, k1) module procedure ${RName}$ - use stdlib_optval, only: optval - use stdlib_error, only: error_stop integer :: ${"".join(f"i{j}," for j in range(1, rank + 1)).removesuffix(",")}$ - select case (optval(indexing, "xy")) - case ("xy") + select case (optval(indexing, stdlib_meshgrid_xy)) + case (stdlib_meshgrid_xy) $:meshgrid_loop(XY_INDICES) - case ("ij") + case (stdlib_meshgrid_ij) $:meshgrid_loop(IJ_INDICES) case default call error_stop("ERROR (meshgrid): unexpected indexing.") diff --git a/test/math/test_meshgrid.fypp b/test/math/test_meshgrid.fypp index d056ee1b8..b61b956b7 100644 --- a/test/math/test_meshgrid.fypp +++ b/test/math/test_meshgrid.fypp @@ -7,13 +7,13 @@ #:def OPTIONAL_PART_IN_SIGNATURE(indexing) #:if indexing in ("xy", "ij") - ${f', "{indexing}"'}$ + ${f', stdlib_meshgrid_{indexing}'}$ #:endif #:enddef module test_meshgrid use testdrive, only : new_unittest, unittest_type, error_type, check - use stdlib_math, only: meshgrid + use stdlib_math, only: meshgrid, stdlib_meshgrid_ij, stdlib_meshgrid_xy use stdlib_kinds, only: int8, int16, int32, int64, sp, dp, xdp, qp implicit none