ROMS
Loading...
Searching...
No Matches
round.F
Go to the documentation of this file.
1 MODULE round_mod
2!
3!git $Id$
4!====================================================== H. D. Knoble ===
5! Copyright (c) 2002-2025 The ROMS Group Hernan G. Arango !
6! Licensed under a MIT/X style license !
7! See License_ROMS.md !
8!=======================================================================
9! !
10! Floating point rounding function with a Fuzzy or Tolerant Floor !
11! function. !
12! !
13! On Input: !
14! !
15! X Double precision argument to be operated on. It is !
16! assumed that X is represented with m mantissa bits. !
17! !
18! CT Comparison Tolerance such that 0 < CT <= 3-SQRT(5)/2. !
19! If the relative difference between X and a whole !
20! number is less than CT, then TFLOOR is returned as !
21! this whole number. By treating the floating-point !
22! numbers as a finite ordered set, note that the !
23! heuristic EPS=2.**(-(m-1)) and CT=3*eps causes !
24! arguments of TFLOOR/TCEIL to be treated as whole !
25! numbers if they are exactly whole numbers or are !
26! immediately adjacent to whole number representations.!
27! Since EPS, the "distance" between floating-point !
28! numbers on the unit interval, and m, the number of !
29! bits in X mantissa, exist on every floating-point !
30! computer, TFLOOR/TCEIL are consistently definable !
31! on every floating-point computer. !
32! !
33! Usage: !
34! !
35! CT = 3 * EPSILON(X) That is, CT is about 1 bit on either !
36! side of X mantissa bits. !
37! Y = round(X, CT) !
38! !
39! References: !
40! !
41! P. E. Hagerty, 1978: More on Fuzzy Floor and Ceiling, APL QUOTE !
42! QUAD 8(4):20-24. (The TFLOOR=FL5 took five years of refereed !
43! evolution publication). !
44! !
45! L. M. Breed, 1978: Definitions for Fuzzy Floor and Ceiling, APL !
46! QUOTE QUAD 8(3):16-23. !
47! !
48! Adapted from H.D. Knoble code (Penn State University). !
49! !
50!=======================================================================
51!
52 USE mod_kinds
53!
54 implicit none
55!
56 PUBLIC :: round ! Tolerant round function
57 PUBLIC :: tceil ! Tolerant ceiling function
58 PUBLIC :: tfloor ! Tolerant floor function
59 PRIVATE :: ufloor ! Unfuzzy floor function
60!
61 CONTAINS
62!
63!***********************************************************************
64 FUNCTION round (X, CT) RESULT (Y)
65!***********************************************************************
66!
67! Imported variable declarations.
68!
69 real (dp), intent(in) :: x, ct
70!
71! Local variable declarations.
72!
73 real(dp) :: y
74!
75!------------------------------------------------------------------------
76! Compute tolerant round function.
77!------------------------------------------------------------------------
78!
79 y=tfloor(x+0.5_dp,ct)
80!
81 RETURN
82 END FUNCTION round
83!
84!***********************************************************************
85 FUNCTION tceil (X,CT) RESULT (Y)
86!***********************************************************************
87!
88! Imported variable declarations.
89!
90 real (dp), intent(in) :: x, ct
91!
92! Local variable declarations.
93!
94 real(dp) :: y
95!
96!------------------------------------------------------------------------
97! Compute tolerant ceiling function.
98!------------------------------------------------------------------------
99!
100 y=-tfloor(-x,ct)
101!
102 RETURN
103 END FUNCTION tceil
104!
105!***********************************************************************
106 FUNCTION tfloor (X, CT) RESULT (Y)
107!***********************************************************************
108!
109! Imported variable declarations.
110!
111 real (dp), intent(in) :: x, ct
112!
113! Local variable declarations.
114!
115 real (dp) :: eps5, q, rmax, y
116!
117!------------------------------------------------------------------------
118! Compute tolerant floor function.
119!------------------------------------------------------------------------
120!
121! Hagerty FL5 function
122!
123 q=1.0_dp
124 IF (x.lt.0.0_dp) q=1.0_dp-ct
125 rmax=q/(2.0_dp-ct)
126 eps5=ct/q
127 y=ufloor(x+max(ct,min(rmax,eps5*abs(1.0_dp+ufloor(x)))))
128 IF ((x.le.0.0_dp).or.(y-x).lt.rmax) RETURN
129 y=y-1.0_dp
130!
131 RETURN
132 END FUNCTION tfloor
133!
134!***********************************************************************
135 FUNCTION ufloor (X) RESULT (Y)
136!***********************************************************************
137!
138! Imported variable declarations.
139!
140 real (dp), intent(in) :: x
141!
142! Local variable declarations.
143!
144 real(dp) :: y
145!
146!-----------------------------------------------------------------------
147! Compute the largest integer algebraically less than or equal to X;
148! that is, the unfuzzy Floor Function.
149!-----------------------------------------------------------------------
150!
151 y=x-mod(x,1.0_dp)-mod(2.0_dp+sign(1.0_dp,x),3.0_dp)
152!
153 RETURN
154 END FUNCTION ufloor
155!
156 END MODULE round_mod
157
158
integer, parameter dp
Definition mod_kinds.F:25
real(dp) function, public round(x, ct)
Definition round.F:65
real(dp) function, public tceil(x, ct)
Definition round.F:86
real(dp) function, public tfloor(x, ct)
Definition round.F:107
real(dp) function, private ufloor(x)
Definition round.F:136