Embedded Template Library  1.0
scaled_rounding.h
Go to the documentation of this file.
1 
3 /******************************************************************************
4 The MIT License(MIT)
5 
6 Embedded Template Library.
7 https://github.com/ETLCPP/etl
8 https://www.etlcpp.com
9 
10 Copyright(c) 2018 jwellbelove
11 
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files(the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions :
18 
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21 
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29 ******************************************************************************/
30 
31 #ifndef ETL_SCALED_ROUNDING_INCLUDED
32 #define ETL_SCALED_ROUNDING_INCLUDED
33 
34 #include "static_assert.h"
35 #include "type_traits.h"
36 #include "absolute.h"
37 
38 namespace etl
39 {
40 
41  template <typename T>
43  {
44  typedef typename etl::conditional<etl::is_signed<T>::value, int32_t, uint32_t>::type type;
45  };
46 
47  //*****************************************************************************
60  //*****************************************************************************
61 
62  //***************************************************************************
66  //***************************************************************************
67  template <const size_t SCALING, typename T>
69  {
70  ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Type must be an integral");
71  typedef typename scaled_rounding_t<T>::type scale_t;
72 
73  if (value >= 0)
74  {
75  return T((value + scale_t(SCALING)) / scale_t(SCALING));
76  }
77  else
78  {
79  return T(value / scale_t(SCALING));
80  }
81  }
82 
83  //***************************************************************************
87  //***************************************************************************
88  template <const size_t SCALING, typename T>
90  {
91  typedef typename scaled_rounding_t<T>::type scale_t;
92 
93  return round_ceiling_unscaled<SCALING>(value) * scale_t(SCALING);
94  }
95 
96  //***************************************************************************
100  //***************************************************************************
101  template <const size_t SCALING, typename T>
103  {
104  ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Type must be an integral");
105  typedef typename scaled_rounding_t<T>::type scale_t;
106 
107  if (value >= 0)
108  {
109  return T(value / scale_t(SCALING));
110  }
111  else
112  {
113  return T((value - scale_t(SCALING)) / scale_t(SCALING));
114  }
115  }
116 
117  //***************************************************************************
121  //***************************************************************************
122  template <const size_t SCALING, typename T>
124  {
125  typedef typename scaled_rounding_t<T>::type scale_t;
126 
127  return T(round_floor_unscaled<SCALING>(value) * scale_t(SCALING));
128  }
129 
130  //***************************************************************************
135  //***************************************************************************
136  template <const size_t SCALING, typename T>
138  {
139  ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Type must be an integral");
140  ETL_STATIC_ASSERT((((SCALING / 2U) * 2U) == SCALING), "Scaling must be divisible by 2");
141  typedef typename scaled_rounding_t<T>::type scale_t;
142 
143  if (value >= 0)
144  {
145  return T((value + scale_t(SCALING / 2U)) / scale_t(SCALING));
146  }
147  else
148  {
149  return T((value - scale_t(SCALING / 2U)) / scale_t(SCALING));
150  }
151  }
152 
153  //***************************************************************************
158  //***************************************************************************
159  template <const size_t SCALING, typename T>
161  {
162  typedef typename scaled_rounding_t<T>::type scale_t;
163 
164  return T(round_half_up_unscaled<SCALING>(value) * scale_t(SCALING));
165  }
166 
167  //***************************************************************************
172  //***************************************************************************
173  template <const size_t SCALING, typename T>
175  {
176  ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Type must be an integral");
177  ETL_STATIC_ASSERT((((SCALING / 2U) * 2U) == SCALING), "Scaling must be divisible by 2");
178  typedef typename scaled_rounding_t<T>::type scale_t;
179 
180  if (value >= 0)
181  {
182  return T((value + scale_t((SCALING / 2U) - 1U)) / scale_t(SCALING));
183  }
184  else
185  {
186  return T((value - scale_t((SCALING / 2U) - 1U)) / scale_t(SCALING));
187  }
188  }
189 
190  //***************************************************************************
195  //***************************************************************************
196  template <const size_t SCALING, typename T>
198  {
199  typedef typename scaled_rounding_t<T>::type scale_t;
200 
201  return T(round_half_down_unscaled<SCALING>(value) * scale_t(SCALING));
202  }
203 
204  //***************************************************************************
208  //***************************************************************************
209  template <const size_t SCALING, typename T>
211  {
212  ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Type must be an integral");
213  typedef typename scaled_rounding_t<T>::type scale_t;
214 
215  return T(value / scale_t(SCALING));
216  }
217 
218  //***************************************************************************
222  //***************************************************************************
223  template <const size_t SCALING, typename T>
224  T round_zero_scaled(T value)
225  {
226  typedef typename scaled_rounding_t<T>::type scale_t;
227 
228  return T(round_zero_unscaled<SCALING>(value) * scale_t(SCALING));
229  }
230 
231  //***************************************************************************
235  //***************************************************************************
236  template <const size_t SCALING, typename T>
238  {
239  ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Type must be an integral");
240  typedef typename scaled_rounding_t<T>::type scale_t;
241 
242  if (value >= 0)
243  {
244  return T((value + scale_t(SCALING)) / scale_t(SCALING));
245  }
246  else
247  {
248  return T((value - scale_t(SCALING)) / scale_t(SCALING));
249  }
250  }
251 
252  //***************************************************************************
256  //***************************************************************************
257  template <const size_t SCALING, typename T>
259  {
260  typedef typename scaled_rounding_t<T>::type scale_t;
261 
262  return T(round_infinity_unscaled<SCALING>(value) * scale_t(SCALING));
263  }
264 
265  //***************************************************************************
270  //***************************************************************************
271  template <const size_t SCALING, typename T>
273  {
274  ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Type must be an integral");
275  typedef typename scaled_rounding_t<T>::type scale_t;
276 
277  // Half?
278  if ((etl::absolute(value) % scale_t(SCALING)) == scale_t(SCALING / 2U))
279  {
280  // Odd?
281  if ((value / scale_t(SCALING)) & 1U)
282  {
283  return T(round_half_up_unscaled<SCALING>(value));
284  }
285  else
286  {
287  return T(round_half_down_unscaled<SCALING>(value));
288  }
289  }
290  else
291  {
292  return T(round_half_up_unscaled<SCALING>(value));
293  }
294  }
295 
296  //***************************************************************************
301  //***************************************************************************
302  template <const size_t SCALING, typename T>
304  {
305  typedef typename scaled_rounding_t<T>::type scale_t;
306 
307  return T(round_half_even_unscaled<SCALING>(value) * scale_t(SCALING));
308  }
309 
310  //***************************************************************************
315  //***************************************************************************
316  template <const size_t SCALING, typename T>
318  {
319  ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Type must be an integral");
320  typedef typename scaled_rounding_t<T>::type scale_t;
321 
322  // Half?
323  if ((etl::absolute(value) % scale_t(SCALING)) == scale_t(SCALING / 2U))
324  {
325  // Odd?
326  if ((value / scale_t(SCALING)) & 1U)
327  {
328  return T(round_half_down_unscaled<SCALING>(value));
329  }
330  else
331  {
332  return T(round_half_up_unscaled<SCALING>(value));
333  }
334  }
335  else
336  {
337  return T(round_half_up_unscaled<SCALING>(value));
338  }
339  }
340 
341  //***************************************************************************
346  //***************************************************************************
347  template <const size_t SCALING, typename T>
349  {
350  typedef typename scaled_rounding_t<T>::type scale_t;
351 
352  return T(round_half_odd_unscaled<SCALING>(value) * scale_t(SCALING));
353  }
354 }
355 
356 #endif
conditional
Definition: type_traits_generator.h:1202
is_integral
Definition: type_traits_generator.h:941
Definition: absolute.h:37
T round_half_even_unscaled(T value)
Definition: scaled_rounding.h:272
T round_ceiling_scaled(T value)
Definition: scaled_rounding.h:89
T round_infinity_unscaled(T value)
Definition: scaled_rounding.h:237
T round_half_down_scaled(T value)
Definition: scaled_rounding.h:197
T round_half_even_scaled(T value)
Definition: scaled_rounding.h:303
T round_half_odd_scaled(T value)
Definition: scaled_rounding.h:348
T round_half_up_scaled(T value)
Definition: scaled_rounding.h:160
T round_infinity_scaled(T value)
Definition: scaled_rounding.h:258
T round_floor_scaled(T value)
Definition: scaled_rounding.h:123
T round_zero_unscaled(T value)
Definition: scaled_rounding.h:210
T round_ceiling_unscaled(T value)
Definition: scaled_rounding.h:68
T round_half_up_unscaled(T value)
Definition: scaled_rounding.h:137
T round_floor_unscaled(T value)
Definition: scaled_rounding.h:102
T round_half_odd_unscaled(T value)
Definition: scaled_rounding.h:317
T round_zero_scaled(T value)
Definition: scaled_rounding.h:224
T round_half_down_unscaled(T value)
Definition: scaled_rounding.h:174
Definition: scaled_rounding.h:43