Compute Library
 21.02
Rounding.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-2021 Arm Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #ifndef ARM_COMPUTE_UTILS_ROUNDING_H
25 #define ARM_COMPUTE_UTILS_ROUNDING_H
26 
27 #include "arm_compute/core/Error.h"
29 #include "support/Requires.h"
31 
32 #include <cmath>
33 
34 namespace arm_compute
35 {
36 namespace utils
37 {
38 namespace rounding
39 {
40 /** Rounding mode */
41 enum class RoundingMode
42 {
43  TO_ZERO, /**< Round towards zero */
44  AWAY_FROM_ZERO, /**< Round away from zero */
45  HALF_TO_ZERO, /**< Round half towards from zero */
46  HALF_AWAY_FROM_ZERO, /**< Round half away from zero */
47  HALF_UP, /**< Round half towards positive infinity */
48  HALF_DOWN, /**< Round half towards negative infinity */
49  HALF_EVEN /**< Round half towards nearest even */
50 };
51 
52 /** Round floating-point value with round to zero
53  *
54  * @tparam T Parameter type. Should be of floating point type.
55  *
56  * @param[in] value floating-point value to be rounded.
57  *
58  * @return Floating-point value of rounded @p value.
59  */
60 template <typename T, ARM_COMPUTE_REQUIRES_TA(traits::is_floating_point<T>::value)>
61 inline T round_to_zero(T value)
62 {
63  T res = std::floor(std::fabs(value));
64  return (value < 0.f) ? -res : res;
65 }
66 
67 /** Round floating-point value with round away from zero
68  *
69  * @tparam T Parameter type. Should be of floating point type.
70  *
71  * @param[in] value floating-point value to be rounded.
72  *
73  * @return Floating-point value of rounded @p value.
74  */
75 template <typename T, ARM_COMPUTE_REQUIRES_TA(traits::is_floating_point<T>::value)>
76 inline T round_away_from_zero(T value)
77 {
78  T res = std::ceil(std::fabs(value));
79  return (value < 0.f) ? -res : res;
80 }
81 
82 /** Round floating-point value with half value rounding towards zero.
83  *
84  * @tparam T Parameter type. Should be of floating point type.
85  *
86  * @param[in] value floating-point value to be rounded.
87  *
88  * @return Floating-point value of rounded @p value.
89  */
90 template <typename T, ARM_COMPUTE_REQUIRES_TA(traits::is_floating_point<T>::value)>
91 inline T round_half_to_zero(T value)
92 {
93  T res = T(std::ceil(std::fabs(value) - 0.5f));
94  return (value < 0.f) ? -res : res;
95 }
96 
97 /** Round floating-point value with half value rounding away from zero.
98  *
99  * @tparam T Parameter type. Should be of floating point type.
100  *
101  * @param[in] value floating-point value to be rounded.
102  *
103  * @return Floating-point value of rounded @p value.
104  */
105 template <typename T, ARM_COMPUTE_REQUIRES_TA(traits::is_floating_point<T>::value)>
106 inline T round_half_away_from_zero(T value)
107 {
108  T res = T(std::floor(std::fabs(value) + 0.5f));
109  return (value < 0.f) ? -res : res;
110 }
111 
112 /** Round floating-point value with half value rounding to positive infinity.
113  *
114  * @tparam T Parameter type. Should be of floating point type.
115  *
116  * @param[in] value floating-point value to be rounded.
117  *
118  * @return Floating-point value of rounded @p value.
119  */
120 template <typename T, ARM_COMPUTE_REQUIRES_TA(traits::is_floating_point<T>::value)>
121 inline T round_half_up(T value)
122 {
123  return std::floor(value + 0.5f);
124 }
125 
126 /** Round floating-point value with half value rounding to negative infinity.
127  *
128  * @tparam T Parameter type. Should be of floating point type.
129  *
130  * @param[in] value floating-point value to be rounded.
131  *
132  * @return Floating-point value of rounded @p value.
133  */
134 template <typename T, ARM_COMPUTE_REQUIRES_TA(traits::is_floating_point<T>::value)>
135 inline T round_half_down(T value)
136 {
137  return std::ceil(value - 0.5f);
138 }
139 
140 /** Round floating-point value with half value rounding to nearest even.
141  *
142  * @tparam T Parameter type. Should be of floating point type.
143  *
144  * @param[in] value floating-point value to be rounded.
145  * @param[in] epsilon precision.
146  *
147  * @return Floating-point value of rounded @p value.
148  */
149 template <typename T, ARM_COMPUTE_REQUIRES_TA(traits::is_floating_point<T>::value)>
151 {
152  T positive_value = std::abs(value);
153  T ipart = 0;
154  std::modf(positive_value, &ipart);
155  // If 'value' is exactly halfway between two integers
156  if(std::abs(positive_value - (ipart + 0.5f)) < epsilon)
157  {
158  // If 'ipart' is even then return 'ipart'
159  if(std::fmod(ipart, 2.f) < epsilon)
160  {
161  return support::cpp11::copysign(ipart, value);
162  }
163  // Else return the nearest even integer
164  return support::cpp11::copysign(std::ceil(ipart + 0.5f), value);
165  }
166  // Otherwise use the usual round to closest
167  return support::cpp11::copysign(support::cpp11::round(positive_value), value);
168 }
169 
170 /** Round floating-point value given a rounding mode
171  *
172  * @tparam T Parameter type. Should be of floating point type.
173  *
174  * @param[in] value floating-point value to be rounded.
175  * @param[in] rounding_mode Rounding mode to use.
176  *
177  * @return Floating-point value of rounded @p value.
178  */
179 template <typename T, ARM_COMPUTE_REQUIRES_TA(traits::is_floating_point<T>::value)>
180 inline T round(T value, RoundingMode rounding_mode)
181 {
182  switch(rounding_mode)
183  {
185  return round_to_zero(value);
187  return round_away_from_zero(value);
189  return round_half_to_zero(value);
191  return round_half_away_from_zero(value);
193  return round_half_up(value);
195  return round_half_down(value);
197  return round_half_even(value);
198  default:
199  ARM_COMPUTE_ERROR("Unsupported rounding mode!");
200  }
201 }
202 } // namespace rounding
203 } // namespace utils
204 } // namespace arm_compute
205 #endif /*ARM_COMPUTE_UTILS_ROUNDING_H */
T round_half_down(T value)
Round floating-point value with half value rounding to negative infinity.
Definition: Rounding.h:135
#define ARM_COMPUTE_ERROR(msg)
Print the given message then throw an std::runtime_error.
Definition: Error.h:352
T copysign(T x, T y)
Composes a floating point value with the magnitude of x and the sign of y.
T round_half_up(T value)
Round floating-point value with half value rounding to positive infinity.
Definition: Rounding.h:121
T round_away_from_zero(T value)
Round floating-point value with round away from zero.
Definition: Rounding.h:76
T round_half_away_from_zero(T value)
Round floating-point value with half value rounding away from zero.
Definition: Rounding.h:106
T round_half_even(T value, T epsilon=std::numeric_limits< T >::epsilon())
Round floating-point value with half value rounding to nearest even.
Definition: Rounding.h:150
Copyright (c) 2017-2021 Arm Limited.
T round_half_to_zero(T value)
Round floating-point value with half value rounding towards zero.
Definition: Rounding.h:91
Round half towards negative infinity.
T round_to_zero(T value)
Round floating-point value with round to zero.
Definition: Rounding.h:61
Round half towards positive infinity.
T round(T value)
Round floating-point value with half value rounding away from zero.
T round(T value, RoundingMode rounding_mode)
Round floating-point value given a rounding mode.
Definition: Rounding.h:180
RoundingMode
Rounding mode.
Definition: Rounding.h:41