Skip to content

Commit bc2bf5a

Browse files
authored
Merge branch 'fortran-lang:master' into activations
2 parents b137b36 + c663dc1 commit bc2bf5a

File tree

5 files changed

+317
-3
lines changed

5 files changed

+317
-3
lines changed

doc/specs/stdlib_math.md

+35
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,41 @@ Here inputs are of type `real` and kind `sp`
6161
{!example/math/example_clip_real.f90!}
6262
```
6363

64+
<!-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -->
65+
### `swap` subroutine
66+
67+
#### Description
68+
69+
Swaps the values in `lhs` and `rhs`.
70+
71+
#### Syntax
72+
73+
`call` [[stdlib_math(module):swap(interface)]] ` (lhs, rhs)`
74+
75+
#### Status
76+
77+
Experimental
78+
79+
#### Class
80+
81+
Elemental subroutine.
82+
83+
#### Argument(s)
84+
85+
`lhs`: scalar or array of any of the intrinsic types `integer`, `real`, `complex`, `logical`, `character`, `string_type`, `bitset` type. This argument is `intent(inout)`.
86+
`rhs`: scalar or array of any of the intrinsic types `integer`, `real`, `complex`, `logical`, `character`, `string_type`, `bitset` type. This argument is `intent(inout)`.
87+
88+
##### Note
89+
All arguments must have same `type` and same `kind`.
90+
91+
**WARNING**: For fix size characters with different length, the `swap` subroutine will truncate the longest amongst `lhs` and `rhs`. To avoid truncation it is possible to pass a subsection of the string.
92+
93+
#### Examples
94+
95+
```fortran
96+
{!example/math/example_math_swap.f90!}
97+
```
98+
6499
### `gcd` function
65100

66101
#### Description

example/math/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ ADD_EXAMPLE(math_argpi)
1515
ADD_EXAMPLE(math_deg2rad)
1616
ADD_EXAMPLE(math_rad2deg)
1717
ADD_EXAMPLE(math_is_close)
18+
ADD_EXAMPLE(math_swap)
1819
ADD_EXAMPLE(meshgrid)

example/math/example_math_swap.f90

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
program example_math_swap
2+
use stdlib_math, only: swap
3+
implicit none
4+
5+
block
6+
integer :: x, y
7+
x = 9
8+
y = 18
9+
call swap(x,y)
10+
end block
11+
12+
block
13+
real :: x, y
14+
x = 4.0
15+
y = 8.0
16+
call swap(x,y)
17+
end block
18+
19+
block
20+
real :: x(3), y(3)
21+
x = [1.0,2.0,3.0]
22+
y = [4.0,5.0,6.0]
23+
call swap(x,y)
24+
end block
25+
26+
block
27+
character(4) :: x
28+
character(6) :: y
29+
x = 'abcd'
30+
y = 'efghij'
31+
call swap(x,y) ! x=efgh, y=abcd
32+
33+
x = 'abcd'
34+
y = 'efghij'
35+
call swap(x,y(1:4)) ! x=efgh, y=abcdij
36+
end block
37+
38+
block
39+
use stdlib_string_type
40+
type(string_type) :: x, y
41+
x = 'abcde'
42+
y = 'fghij'
43+
call swap(x,y)
44+
end block
45+
46+
block
47+
use stdlib_bitsets
48+
type(bitset_64) :: x, y
49+
call x%from_string('0000')
50+
call y%from_string('1111')
51+
call swap(x,y)
52+
end block
53+
54+
end program example_math_swap

src/stdlib_math.fypp

+56-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
#:include "common.fypp"
22
#:set IR_KINDS_TYPES = INT_KINDS_TYPES + REAL_KINDS_TYPES
33
#:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES
4-
4+
#:set BITSET_KINDS_TYPES = list(zip(BITSET_KINDS, BITSET_TYPES))
55
module stdlib_math
66
use stdlib_kinds, only: int8, int16, int32, int64, sp, dp, xdp, qp
77
use stdlib_optval, only: optval
8+
use stdlib_bitsets, only: bitset_64, bitset_large
89

910
implicit none
1011
private
11-
public :: clip, gcd, linspace, logspace
12+
public :: clip, swap, gcd, linspace, logspace
1213
public :: EULERS_NUMBER_SP, EULERS_NUMBER_DP
1314
#:if WITH_QP
1415
public :: EULERS_NUMBER_QP
@@ -42,6 +43,22 @@ module stdlib_math
4243
#:endfor
4344
end interface clip
4445

46+
!> Swap the values of the lhs and rhs arguments
47+
!> ([Specification](../page/specs/stdlib_math.html#swap_subroutine))
48+
!>
49+
!> Version: experimental
50+
interface swap
51+
#:for k1, t1 in INT_KINDS_TYPES + REAL_KINDS_TYPES + BITSET_KINDS_TYPES
52+
module procedure :: swap_${k1}$
53+
#:endfor
54+
#:for k1, t1 in CMPLX_KINDS_TYPES
55+
module procedure :: swap_c${k1}$
56+
#:endfor
57+
module procedure :: swap_bool
58+
module procedure :: swap_str
59+
module procedure :: swap_stt
60+
end interface
61+
4562
!> Returns the greatest common divisor of two integers
4663
!> ([Specification](../page/specs/stdlib_math.html#gcd))
4764
!>
@@ -509,5 +526,42 @@ contains
509526
end function gcd_${k1}$
510527

511528
#:endfor
529+
530+
#:for k1, t1 in INT_KINDS_TYPES + REAL_KINDS_TYPES + BITSET_KINDS_TYPES
531+
elemental subroutine swap_${k1}$(lhs, rhs)
532+
${t1}$, intent(inout) :: lhs, rhs
533+
${t1}$ :: temp
534+
temp = lhs; lhs = rhs; rhs = temp
535+
end subroutine
536+
537+
#:endfor
538+
539+
#:for k1, t1 in CMPLX_KINDS_TYPES
540+
elemental subroutine swap_c${k1}$(lhs, rhs)
541+
${t1}$, intent(inout) :: lhs, rhs
542+
${t1}$ :: temp
543+
temp = lhs; lhs = rhs; rhs = temp
544+
end subroutine
545+
546+
#:endfor
547+
548+
elemental subroutine swap_bool(lhs, rhs)
549+
logical, intent(inout) :: lhs, rhs
550+
logical :: temp
551+
temp = lhs; lhs = rhs; rhs = temp
552+
end subroutine
553+
554+
elemental subroutine swap_str(lhs,rhs)
555+
character(*), intent(inout) :: lhs, rhs
556+
character(len=max(len(lhs), len(rhs))) :: temp
557+
temp = lhs ; lhs = rhs ; rhs = temp
558+
end subroutine
559+
560+
elemental subroutine swap_stt(lhs,rhs)
561+
use stdlib_string_type, only: string_type
562+
type(string_type), intent(inout) :: lhs, rhs
563+
type(string_type) :: temp
564+
temp = lhs ; lhs = rhs ; rhs = temp
565+
end subroutine
512566

513567
end module stdlib_math

test/math/test_stdlib_math.fypp

+171-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
module test_stdlib_math
66
use testdrive, only : new_unittest, unittest_type, error_type, check, skip_test
7-
use stdlib_math, only: clip, arg, argd, argpi, arange, is_close, all_close, diff, &
7+
use stdlib_math, only: clip, swap, arg, argd, argpi, arange, is_close, all_close, diff, &
88
arange, deg2rad, rad2deg
99
use stdlib_kinds, only: int8, int16, int32, int64, sp, dp, xdp, qp
1010
implicit none
@@ -38,6 +38,16 @@ contains
3838
new_unittest("clip-real-quad", test_clip_rqp), &
3939
new_unittest("clip-real-quad-bounds", test_clip_rqp_bounds) &
4040

41+
!> Tests swap
42+
#:for k1, t1 in INT_KINDS_TYPES + REAL_KINDS_TYPES
43+
, new_unittest("swap_${k1}$", test_swap_${k1}$) &
44+
#:endfor
45+
#:for k1, t1 in CMPLX_KINDS_TYPES
46+
, new_unittest("swap_c${k1}$", test_swap_c${k1}$) &
47+
#:endfor
48+
, new_unittest("swap_str", test_swap_str) &
49+
, new_unittest("swap_stt", test_swap_stt) &
50+
4151
!> Tests for arg/argd/argpi
4252
#:for k1 in CMPLX_KINDS
4353
, new_unittest("arg-cmplx-${k1}$", test_arg_${k1}$) &
@@ -246,6 +256,166 @@ contains
246256

247257
end subroutine test_clip_rqp_bounds
248258

259+
#:for k1, t1 in INT_KINDS_TYPES + REAL_KINDS_TYPES
260+
subroutine test_swap_${k1}$(error)
261+
type(error_type), allocatable, intent(out) :: error
262+
${t1}$ :: x(3), y(3)
263+
264+
x = [${t1}$ :: 1, 2, 3]
265+
y = [${t1}$ :: 4, 5, 6]
266+
267+
call swap(x,y)
268+
269+
call check(error, all( x == [${t1}$ :: 4, 5, 6] ) )
270+
if (allocated(error)) return
271+
call check(error, all( y == [${t1}$ :: 1, 2, 3] ) )
272+
if (allocated(error)) return
273+
274+
! check self swap
275+
call swap(x,x)
276+
277+
call check(error, all( x == [${t1}$ :: 4, 5, 6] ) )
278+
if (allocated(error)) return
279+
end subroutine test_swap_${k1}$
280+
#:endfor
281+
282+
#:for k1, t1 in CMPLX_KINDS_TYPES
283+
subroutine test_swap_c${k1}$(error)
284+
type(error_type), allocatable, intent(out) :: error
285+
${t1}$ :: x(3), y(3)
286+
287+
x = cmplx( [1, 2, 3] , [4, 5, 6] )
288+
y = cmplx( [4, 5, 6] , [1, 2, 3] )
289+
290+
call swap(x,y)
291+
292+
call check(error, all( x == cmplx( [4, 5, 6] , [1, 2, 3] ) ) )
293+
if (allocated(error)) return
294+
call check(error, all( y == cmplx( [1, 2, 3] , [4, 5, 6] ) ) )
295+
if (allocated(error)) return
296+
297+
! check self swap
298+
call swap(x,x)
299+
300+
call check(error, all( x == cmplx( [4, 5, 6] , [1, 2, 3] ) ) )
301+
if (allocated(error)) return
302+
end subroutine test_swap_c${k1}$
303+
#:endfor
304+
305+
subroutine test_swap_str(error)
306+
type(error_type), allocatable, intent(out) :: error
307+
block
308+
character(5) :: x(2), y(2)
309+
310+
x = ['abcde','fghij']
311+
y = ['fghij','abcde']
312+
313+
call swap(x,y)
314+
315+
call check(error, all( x == ['fghij','abcde'] ) )
316+
if (allocated(error)) return
317+
call check(error, all( y == ['abcde','fghij'] ) )
318+
if (allocated(error)) return
319+
320+
! check self swap
321+
call swap(x,x)
322+
323+
call check(error, all( x == ['fghij','abcde'] ) )
324+
if (allocated(error)) return
325+
end block
326+
327+
block
328+
character(4) :: x
329+
character(6) :: y
330+
331+
x = 'abcd'
332+
y = 'efghij'
333+
call swap(x,y)
334+
335+
call check(error, x == 'efgh' )
336+
if (allocated(error)) return
337+
call check(error, y(1:6) == 'abcd ' )
338+
if (allocated(error)) return
339+
340+
x = 'abcd'
341+
y = 'efghij'
342+
call swap(x,y(1:4))
343+
344+
call check(error, x == 'efgh' )
345+
if (allocated(error)) return
346+
call check(error, y == 'abcdij' )
347+
if (allocated(error)) return
348+
end block
349+
end subroutine test_swap_str
350+
351+
subroutine test_swap_stt(error)
352+
use stdlib_string_type
353+
type(error_type), allocatable, intent(out) :: error
354+
type(string_type) :: x(2), y(2)
355+
356+
x = ['abcde','fghij']
357+
y = ['fghij','abcde']
358+
359+
call swap(x,y)
360+
361+
call check(error, all( x == ['fghij','abcde'] ) )
362+
if (allocated(error)) return
363+
call check(error, all( y == ['abcde','fghij'] ) )
364+
if (allocated(error)) return
365+
366+
! check self swap
367+
call swap(x,x)
368+
369+
call check(error, all( x == ['fghij','abcde'] ) )
370+
if (allocated(error)) return
371+
end subroutine test_swap_stt
372+
373+
subroutine test_swap_bitset_64(error)
374+
use stdlib_bitsets
375+
type(error_type), allocatable, intent(out) :: error
376+
type(bitset_64) :: x, y, u, v
377+
378+
x = [.true.,.false.,.true.,.false.]
379+
u = x
380+
y = [.false.,.true.,.false.,.true.]
381+
v = y
382+
call swap(x,y)
383+
384+
call check(error, x == v )
385+
if (allocated(error)) return
386+
call check(error, y == u )
387+
if (allocated(error)) return
388+
389+
! check self swap
390+
call swap(x,x)
391+
392+
call check(error, x == v )
393+
if (allocated(error)) return
394+
end subroutine test_swap_bitset_64
395+
396+
subroutine test_swap_bitset_large(error)
397+
use stdlib_bitsets
398+
type(error_type), allocatable, intent(out) :: error
399+
type(bitset_large) :: x, y, u, v
400+
401+
x = [.true.,.false.,.true.,.false.]
402+
u = x
403+
y = [.false.,.true.,.false.,.true.]
404+
v = y
405+
call swap(x,y)
406+
407+
call check(error, x == v )
408+
if (allocated(error)) return
409+
call check(error, y == u )
410+
if (allocated(error)) return
411+
412+
! check self swap
413+
call swap(x,x)
414+
415+
call check(error, x == v )
416+
if (allocated(error)) return
417+
end subroutine test_swap_bitset_large
418+
249419
#:for k1 in CMPLX_KINDS
250420
subroutine test_arg_${k1}$(error)
251421
type(error_type), allocatable, intent(out) :: error

0 commit comments

Comments
 (0)