Direct-BT  2.3.1
Direct-BT - Direct Bluetooth Programming.
int_math.hpp
Go to the documentation of this file.
1 /*
2  * Author: Sven Gothel <sgothel@jausoft.com>
3  * Copyright (c) 2020 Gothel Software e.K.
4  * Copyright (c) 2020 ZAFENA AB
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 
26 #ifndef JAU_BASIC_INT_MATH_HPP_
27 #define JAU_BASIC_INT_MATH_HPP_
28 
29 #include <cstdint>
30 #include <cmath>
31 
32 #include <jau/int_types.hpp>
33 
34 namespace jau {
35 
36  /**
37  // *************************************************
38  // *************************************************
39  // *************************************************
40  */
41 
42  /**
43  * Returns the value of the sign function.
44  * <pre>
45  * -1 for x < 0
46  * 0 for x = 0
47  * 1 for x > 0
48  * </pre>
49  * Implementation is type safe.
50  * @tparam T an integral number type
51  * @param x the integral number
52  * @return function result
53  */
54  template <typename T>
55  constexpr snsize_t sign(const T x) noexcept
56  {
57  return (T(0) < x) - (x < T(0));
58  }
59 
60  /**
61  * Safely inverts the sign of an integral number.
62  * <p>
63  * Implementation takes special care to have T_MIN, i.e. std::numeric_limits<T>::min(),
64  * converted to T_MAX, i.e. std::numeric_limits<T>::max().<br>
65  * This is necessary since <code>T_MAX < | -T_MIN |</code> and the result would
66  * not fit in the return type T otherwise.
67  * </p>
68  * Hence for the extreme minimum case:
69  * <pre>
70  * jau::invert_sign<int32_t>(INT32_MIN) = | INT32_MIN | - 1 = INT32_MAX
71  * </pre>
72  * Otherwise with x < 0:
73  * <pre>
74  * jau::invert_sign<int32_t>(x) = | x | = -x
75  * </pre>
76  * and x >= 0:
77  * <pre>
78  * jau::invert_sign<int32_t>(x) = -x
79  * </pre>
80  * @tparam T
81  * @param x
82  * @return
83  */
84  template <typename T>
85  constexpr T invert_sign(const T x) noexcept
86  {
87  return std::numeric_limits<T>::min() == x ? std::numeric_limits<T>::max() : -x;
88  }
89 
90  /**
91  * Returns the absolute value of an integral number
92  * <p>
93  * Implementation uses jau::invert_sign() to have a safe absolute value conversion, if required.
94  * </p>
95  * @tparam T an integral number type
96  * @param x the integral number
97  * @return function result
98  */
99  template <typename T>
100  constexpr T abs(const T x) noexcept
101  {
102  return sign(x) < 0 ? invert_sign<T>( x ) : x;
103  }
104 
105  /**
106  * Returns the number of decimal digits of the given integral value number using std::log10<T>().<br>
107  * If sign_is_digit == true (default), treats a potential negative sign as a digit.
108  * <pre>
109  * x < 0: 1 + (int) ( log10( -x ) ) + ( sign_is_digit ? 1 : 0 )
110  * x = 0: 1
111  * x > 0: 1 + (int) ( log10( x ) )
112  * </pre>
113  * Implementation uses jau::invert_sign() to have a safe absolute value conversion, if required.
114  * <p>
115  * Convenience method, reusing precomputed sign of value to avoid redundant computations.
116  * </p>
117  * @tparam T an integral integer type
118  * @param x the integral integer
119  * @param x_sign the pre-determined sign of the given value x
120  * @param sign_is_digit if true and value is negative, adds one to result for sign. Defaults to true.
121  * @return digit count
122  */
123  template<typename T>
124  constexpr nsize_t digits10(const T x, const snsize_t x_sign, const bool sign_is_digit=true) noexcept
125  {
126  if( x_sign == 0 ) {
127  return 1;
128  }
129  if( x_sign < 0 ) {
130  return 1 + static_cast<nsize_t>( std::log10<T>( invert_sign<T>( x ) ) ) + ( sign_is_digit ? 1 : 0 );
131  } else {
132  return 1 + static_cast<nsize_t>( std::log10<T>( x ) );
133  }
134  }
135 
136  /**
137  * Returns the number of decimal digits of the given integral value number using std::log10<T>().
138  * If sign_is_digit == true (default), treats a potential negative sign as a digit.
139  * <pre>
140  * x < 0: 1 + (int) ( log10( -x ) ) + ( sign_is_digit ? 1 : 0 )
141  * x = 0: 1
142  * x > 0: 1 + (int) ( log10( x ) )
143  * </pre>
144  * Implementation uses jau::invert_sign() to have a safe absolute value conversion, if required.
145  * @tparam T an integral integer type
146  * @param x the integral integer
147  * @param sign_is_digit if true and value is negative, adds one to result for sign. Defaults to true.
148  * @return digit count
149  */
150  template<typename T>
151  constexpr nsize_t digits10(const T x, const bool sign_is_digit=true) noexcept
152  {
153  return digits10<T>(x, jau::sign<T>(x), sign_is_digit);
154  }
155 
156 } // namespace jau
157 
158 #endif /* JAU_BASIC_INT_MATH_HPP_ */
jau::sign
constexpr snsize_t sign(const T x) noexcept
Returns the value of the sign function.
Definition: int_math.hpp:55
jau::abs
constexpr T abs(const T x) noexcept
Returns the absolute value of an integral number.
Definition: int_math.hpp:100
jau::invert_sign
constexpr T invert_sign(const T x) noexcept
Safely inverts the sign of an integral number.
Definition: int_math.hpp:85
jau
Definition: basic_algos.hpp:34
jau::snsize_t
int_fast32_t snsize_t
Natural 'ssize_t' alternative using int_fast32_t as its natural sized type.
Definition: int_types.hpp:56
jau::nsize_t
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
Definition: int_types.hpp:44
int_types.hpp
jau::digits10
constexpr nsize_t digits10(const T x, const snsize_t x_sign, const bool sign_is_digit=true) noexcept
Returns the number of decimal digits of the given integral value number using std::log10<T>().
Definition: int_math.hpp:124