Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 65b74f8

Browse files
authoredOct 1, 2021
Merge pull request #539 from Sideboard/feature/gcd
Add function gcd
2 parents 82f8c8d + 33c25e5 commit 65b74f8

File tree

3 files changed

+98
-3
lines changed

3 files changed

+98
-3
lines changed
 

‎doc/specs/stdlib_math.md

+46-1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,51 @@ program demo_clip_real
9191
end program demo_clip_real
9292
```
9393

94+
### `gcd` function
95+
96+
#### Description
97+
98+
Returns the greatest common divisor of two integers.
99+
100+
#### Syntax
101+
102+
`res = [[stdlib_math(module):gcd(interface)]] (a, b)`
103+
104+
#### Status
105+
106+
Experimental
107+
108+
#### Class
109+
110+
Elemental function.
111+
112+
#### Argument(s)
113+
114+
`a`: One integer with `intent(in)` to get the divisor for.
115+
`b`: Another integer with `intent(in)` to get the divisor for.
116+
117+
Note: All arguments must be integers of the same `kind`.
118+
119+
#### Output value or Result value
120+
121+
Returns an integer of the same `kind` as that of the arguments.
122+
123+
#### Examples
124+
125+
##### Example 1:
126+
127+
```fortran
128+
program demo_gcd
129+
use stdlib_math, only: gcd
130+
implicit none
131+
integer :: a, b, c
132+
133+
a = 48
134+
b = 18
135+
c = gcd(a, b) ! returns 6
136+
end program demo_gcd
137+
```
138+
94139
### `linspace` - Create a linearly spaced rank one array
95140

96141
#### Description
@@ -342,4 +387,4 @@ program demo_math_arange
342387
print *, arange(0.0,2.0,0.0) !! [0.0,1.0,2.0]. Not recommended: `step` argument is zero!
343388
344389
end program demo_math_arange
345-
```
390+
```

‎src/stdlib_math.fypp

+32-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module stdlib_math
88

99
implicit none
1010
private
11-
public :: clip, linspace, logspace
11+
public :: clip, gcd, linspace, logspace
1212
public :: EULERS_NUMBER_SP, EULERS_NUMBER_DP, EULERS_NUMBER_QP
1313
public :: DEFAULT_LINSPACE_LENGTH, DEFAULT_LOGSPACE_BASE, DEFAULT_LOGSPACE_LENGTH
1414
public :: arange
@@ -28,6 +28,16 @@ module stdlib_math
2828
#:endfor
2929
end interface clip
3030

31+
!> Returns the greatest common divisor of two integers
32+
!> ([Specification](../page/specs/stdlib_math.html#gcd))
33+
!>
34+
!> Version: experimental
35+
interface gcd
36+
#:for k1, t1 in INT_KINDS_TYPES
37+
module procedure gcd_${k1}$
38+
#:endfor
39+
end interface gcd
40+
3141
interface linspace
3242
!! Version: Experimental
3343
!!
@@ -292,4 +302,25 @@ contains
292302
end function clip_${k1}$
293303

294304
#:endfor
305+
306+
#:for k1, t1 in INT_KINDS_TYPES
307+
!> Returns the greatest common divisor of two integers of kind ${k1}$
308+
!> using the Euclidean algorithm.
309+
elemental function gcd_${k1}$(a, b) result(res)
310+
${t1}$, intent(in) :: a
311+
${t1}$, intent(in) :: b
312+
${t1}$ :: res
313+
314+
${t1}$ :: rem, tmp
315+
316+
rem = min(abs(a), abs(b))
317+
res = max(abs(a), abs(b))
318+
do while (rem /= 0_${k1}$)
319+
tmp = rem
320+
rem = mod(res, rem)
321+
res = tmp
322+
end do
323+
end function gcd_${k1}$
324+
325+
#:endfor
295326
end module stdlib_math

‎src/tests/math/test_stdlib_math.f90

+20-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
! SPDX-Identifier: MIT
22

33
program test_stdlib_math
4-
use stdlib_math, only: clip
4+
use stdlib_math, only: clip, gcd
55
use stdlib_error, only: check
66
use stdlib_kinds, only: int8, int16, int32, int64, sp, dp, qp
77
implicit none
@@ -95,4 +95,23 @@ program test_stdlib_math
9595
call check(clip(-55891546.2_qp, -689712245.23_qp, -8958133457.23_qp) == -689712245.23_qp, &
9696
'clip_qp failed for invalid case', warn=.true.)
9797

98+
99+
! gcd function
100+
! testing format: check(gcd(a, b) == correct answer)
101+
call check(gcd(0, 0) == 0, 'gcd(0, 0) failed.', warn=.true.)
102+
call check(gcd(2, 0) == 2, 'gcd(2, 0) failed.', warn=.true.)
103+
call check(gcd(0, -2) == 2, 'gcd(0, -2) failed.', warn=.true.)
104+
call check(gcd(3, 3) == 3, 'gcd(3, 3) failed.', warn=.true.)
105+
call check(gcd(9, 6) == 3, 'gcd(9, 6) failed.', warn=.true.)
106+
call check(gcd(6, 9) == 3, 'gcd(6, 9) failed.', warn=.true.)
107+
call check(gcd(-9, 6) == 3, 'gcd(-9, 6) failed.', warn=.true.)
108+
call check(gcd(9, -6) == 3, 'gcd(9, -6) failed.', warn=.true.)
109+
call check(gcd(-9, -6) == 3, 'gcd(-9, -6) failed.', warn=.true.)
110+
call check(gcd(97, 91) == 1, 'gcd(97, 91) failed.', warn=.true.)
111+
112+
call check(gcd(48_int8, 18_int8) == 6_int8, 'gcd(48, 18) failed for int8.', warn=.true.)
113+
call check(gcd(48_int16, 18_int16) == 6_int16, 'gcd(48, 18) failed for int16', warn=.true.)
114+
call check(gcd(48_int32, 18_int32) == 6_int32, 'gcd(48, 18) failed for int32', warn=.true.)
115+
call check(gcd(48_int64, 18_int64) == 6_int64, 'gcd(48, 18) failed for int64', warn=.true.)
116+
98117
end program test_stdlib_math

0 commit comments

Comments
 (0)
Please sign in to comment.