Skip to content

Commit 5f3e2f5

Browse files
authored
Merge pull request #355 from Aman-Godara/develop_clip
implemented clip function
2 parents af9efe3 + f4ffaa6 commit 5f3e2f5

9 files changed

+229
-0
lines changed

doc/specs/stdlib_math.md

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
---
2+
title: math
3+
---
4+
5+
# The `stdlib_math` module
6+
7+
[TOC]
8+
9+
## Introduction
10+
11+
`stdlib_math` module provides general purpose mathematical functions.
12+
13+
14+
## Procedures and Methods provided
15+
16+
17+
<!-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -->
18+
### `clip` function
19+
20+
#### Description
21+
22+
Returns a value which lies in the given interval [`xmin`, `xmax`] (interval is `xmin` and `xmax` inclusive) and is closest to the input value `x`.
23+
24+
#### Syntax
25+
26+
`res = [[stdlib_math(module):clip(interface)]] (x, xmin, xmax)`
27+
28+
#### Status
29+
30+
Experimental
31+
32+
#### Class
33+
34+
Elemental function.
35+
36+
#### Argument(s)
37+
38+
`x`: scalar of either `integer` or `real` type. This argument is `intent(in)`.
39+
`xmin`: scalar of either `integer` or `real` type. This argument is `intent(in)`.
40+
`xmax`: scalar of either `integer` or `real` type, which must be greater than or equal to `xmin`. This argument is `intent(in)`.
41+
42+
Note: All arguments must have same `type` and same `kind`.
43+
44+
#### Output value or Result value
45+
46+
The output is a scalar of `type` and `kind` same as to that of the arguments.
47+
48+
#### Examples
49+
50+
##### Example 1:
51+
52+
Here inputs are of type `integer` and kind `int32`
53+
```fortran
54+
program demo_clip_integer
55+
use stdlib_math, only: clip
56+
use stdlib_kinds, only: int32
57+
implicit none
58+
integer(int32) :: x
59+
integer(int32) :: xmin
60+
integer(int32) :: xmax
61+
integer(int32) :: clipped_value
62+
63+
xmin = -5_int32
64+
xmax = 5_int32
65+
x = 12_int32
66+
67+
clipped_value = clip(x, xmin, xmax)
68+
! clipped_value <- 5
69+
end program demo_clip_integer
70+
```
71+
72+
##### Example 2:
73+
74+
Here inputs are of type `real` and kind `sp`
75+
```fortran
76+
program demo_clip_real
77+
use stdlib_math, only: clip
78+
use stdlib_kinds, only: sp
79+
implicit none
80+
real(sp) :: x
81+
real(sp) :: xmin
82+
real(sp) :: xmax
83+
real(sp) :: clipped_value
84+
85+
xmin = -5.769_sp
86+
xmax = 3.025_sp
87+
x = 3.025_sp
88+
89+
clipped_value = clip(x, xmin, xmax)
90+
! clipped_value <- 3.02500010
91+
end program demo_clip_real
92+
```

src/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ set(fppFiles
2323
stdlib_quadrature_trapz.fypp
2424
stdlib_quadrature_simps.fypp
2525
stdlib_stats_distribution_PRNG.fypp
26+
stdlib_math.fypp
2627
stdlib_string_type.fypp
2728
)
2829

src/Makefile.manual

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ SRCFYPP =\
1919
stdlib_stats_moment_mask.fypp \
2020
stdlib_stats_moment_scalar.fypp \
2121
stdlib_stats_var.fypp \
22+
stdlib_math.fypp \
2223
stdlib_stats_distribution_PRNG.fypp \
2324
stdlib_string_type.fypp
2425

src/stdlib_math.fypp

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#:include "common.fypp"
2+
#:set IR_KINDS_TYPES = INT_KINDS_TYPES + REAL_KINDS_TYPES
3+
4+
module stdlib_math
5+
use stdlib_kinds, only: int8, int16, int32, int64, sp, dp, qp
6+
7+
implicit none
8+
private
9+
public :: clip
10+
11+
interface clip
12+
#:for k1, t1 in IR_KINDS_TYPES
13+
module procedure clip_${k1}$
14+
#:endfor
15+
end interface clip
16+
17+
contains
18+
19+
#:for k1, t1 in IR_KINDS_TYPES
20+
elemental function clip_${k1}$(x, xmin, xmax) result(res)
21+
${t1}$, intent(in) :: x
22+
${t1}$, intent(in) :: xmin
23+
${t1}$, intent(in) :: xmax
24+
${t1}$ :: res
25+
26+
res = max(min(x, xmax), xmin)
27+
end function clip_${k1}$
28+
29+
#:endfor
30+
end module stdlib_math

src/tests/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ add_subdirectory(stats)
1616
add_subdirectory(string)
1717
add_subdirectory(system)
1818
add_subdirectory(quadrature)
19+
add_subdirectory(math)
1920

2021
ADDTEST(always_skip)
2122
set_tests_properties(always_skip PROPERTIES SKIP_RETURN_CODE 77)

src/tests/Makefile.manual

+1
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ all test clean:
99
$(MAKE) -f Makefile.manual --directory=quadrature $@
1010
$(MAKE) -f Makefile.manual --directory=stats $@
1111
$(MAKE) -f Makefile.manual --directory=string $@
12+
$(MAKE) -f Makefile.manual --directory=math $@

src/tests/math/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ADDTEST(stdlib_math)

src/tests/math/Makefile.manual

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
PROGS_SRC = test_stdlib_math.f90
2+
3+
4+
include ../Makefile.manual.test.mk

src/tests/math/test_stdlib_math.f90

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
! SPDX-Identifier: MIT
2+
3+
program test_stdlib_math
4+
use stdlib_math, only: clip
5+
use stdlib_error, only: check
6+
use stdlib_kinds, only: int8, int16, int32, int64, sp, dp, qp
7+
implicit none
8+
9+
! clip function
10+
! testing format: check(clip(x, xmin, xmax) == correct answer)
11+
! valid case: xmin is not greater than xmax
12+
! invalid case: xmin is greater than xmax
13+
14+
! type: integer(int8), kind: int8
15+
! valid test case
16+
call check(clip(2_int8, -2_int8, 5_int8) == 2_int8, &
17+
'clip_int8 failed for valid case', warn=.true.)
18+
call check(clip(127_int8, -127_int8, 0_int8) == 0_int8, &
19+
'clip_int8 failed for valid case', warn=.true.)
20+
! invalid test case
21+
call check(clip(2_int8, 5_int8, -2_int8) == 5_int8, &
22+
'clip_int8 failed for invalid case', warn=.true.)
23+
call check(clip(127_int8, 0_int8, -127_int8) == 0_int8, &
24+
'clip_int8 failed for invalid case', warn=.true.)
25+
26+
! type: integer(int16), kind: int16
27+
! valid test case
28+
call check(clip(2_int16, -2_int16, 5_int16) == 2_int16, &
29+
'clip_int16 failed for valid case', warn=.true.)
30+
call check(clip(32767_int16, -32767_int16, 0_int16) == 0_int16, &
31+
'clip_int16 failed for valid case', warn=.true.)
32+
! invalid test case
33+
call check(clip(2_int16, 5_int16, -2_int16) == 5_int16, &
34+
'clip_int16 failed for invalid case', warn=.true.)
35+
call check(clip(32767_int16, 0_int16, -32767_int16) == 0_int16, &
36+
'clip_int16 failed for invalid case', warn=.true.)
37+
38+
! type: integer(int32), kind: int32
39+
! valid test case
40+
call check(clip(2_int32, -2_int32, 5_int32) == 2_int32, &
41+
'clip_int32 failed for valid case', warn=.true.)
42+
call check(clip(-2147483647_int32, 0_int32, 2147483647_int32) == 0_int32, &
43+
'clip_int32 failed for valid case', warn=.true.)
44+
! invalid test case
45+
call check(clip(2_int32, 5_int32, -2_int32) == 5_int32, &
46+
'clip_int32 failed for invalid case', warn=.true.)
47+
call check(clip(-2147483647_int32, 2147483647_int32, 0_int32) == 2147483647_int32, &
48+
'clip_int32 failed for invalid case', warn=.true.)
49+
50+
! type: integer(int64), kind: int64
51+
! valid test case
52+
call check(clip(2_int64, -2_int64, 5_int64) == 2_int64, &
53+
'clip_int64 failed for valid case', warn=.true.)
54+
call check(clip(-922337203_int64, -10_int64, 25_int64) == -10_int64, &
55+
'clip_int64 failed for valid case', warn=.true.)
56+
! invalid test case
57+
call check(clip(2_int64, 5_int64, -2_int64) == 5_int64, &
58+
'clip_int64 failed for invalid case', warn=.true.)
59+
call check(clip(-922337203_int64, 25_int64, -10_int64) == 25_int64, &
60+
'clip_int64 failed for invalid case', warn=.true.)
61+
62+
! type: real(sp), kind: sp
63+
! valid test case
64+
call check(clip(3.025_sp, -5.77_sp, 3.025_sp) == 3.025_sp, &
65+
'clip_sp failed for valid case', warn=.true.)
66+
call check(clip(0.0_sp, -1578.025_sp, -59.68_sp) == -59.68_sp, &
67+
'clip_sp failed for valid case', warn=.true.)
68+
! invalid test case
69+
call check(clip(3.025_sp, 3.025_sp, -5.77_sp) == 3.025_sp, &
70+
'clip_sp failed for invalid case', warn=.true.)
71+
call check(clip(0.0_sp, -59.68_sp, -1578.025_sp) == -59.68_sp, &
72+
'clip_sp failed for invalid case', warn=.true.)
73+
74+
! type: real(dp), kind: dp
75+
! valid test case
76+
call check(clip(3.025_dp, -5.77_dp, 3.025_dp) == 3.025_dp, &
77+
'clip_dp failed for valid case', warn=.true.)
78+
call check(clip(-7.0_dp, 0.059668_dp, 1.00268_dp) == 0.059668_dp, &
79+
'clip_dp failed for valid case', warn=.true.)
80+
! invalid test case
81+
call check(clip(3.025_dp, 3.025_dp, -5.77_dp) == 3.025_dp, &
82+
'clip_dp failed for invalid case', warn=.true.)
83+
call check(clip(-7.0_dp, 1.00268_dp, 0.059668_dp) == 1.00268_dp, &
84+
'clip_dp failed for invalid case', warn=.true.)
85+
86+
! type: real(qp), kind: qp
87+
! valid test case
88+
call check(clip(3.025_qp, -5.77_qp, 3.025_qp) == 3.025_qp, &
89+
'clip_qp failed for valid case', warn=.true.)
90+
call check(clip(-55891546.2_qp, -8958133457.23_qp, -689712245.23_qp) == -689712245.23_qp, &
91+
'clip_qp failed for valid case', warn=.true.)
92+
! invalid test case
93+
call check(clip(3.025_qp, 3.025_qp, -5.77_qp) == 3.025_qp, &
94+
'clip_qp failed for invalid case', warn=.true.)
95+
call check(clip(-55891546.2_qp, -689712245.23_qp, -8958133457.23_qp) == -689712245.23_qp, &
96+
'clip_qp failed for invalid case', warn=.true.)
97+
98+
end program test_stdlib_math

0 commit comments

Comments
 (0)