Merge "Update doxygen comments" into devel/master
[platform/core/uifw/dali-core.git] / dali / public-api / math / math-utils.h
1 #ifndef __DALI_MATH_UTILS_H__
2 #define __DALI_MATH_UTILS_H__
3
4 /*
5  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // INTERNAL INCLUDES
22 #include <dali/public-api/common/dali-common.h>
23 #include <dali/public-api/common/constants.h>
24
25 namespace Dali
26 {
27 /**
28  * @addtogroup dali_core_math
29  * @{
30  */
31
32 /**
33  * @brief Returns the next power of two.
34  *
35  * In case of numbers which are already a power of two this function returns the original number.
36  * If i is zero returns 1.
37  * @SINCE_1_0.0
38  * @param[in] i Input number
39  * @return The next power of two or i itself in case it's a power of two
40  */
41 inline unsigned int NextPowerOfTwo( unsigned int i )
42 {
43   DALI_ASSERT_ALWAYS(i <= 1u << (sizeof(unsigned) * 8 - 1) && "Return type cannot represent the next power of two greater than the argument.");
44   if(i==0u)
45   {
46     return 1u;
47   }
48
49   i--;
50   i |= i >> 1;
51   i |= i >> 2;
52   i |= i >> 4;
53   i |= i >> 8;
54   i |= i >> 16;
55   i++;
56   return i;
57 }
58
59 /**
60  * @brief Whether a number is power of two.
61  *
62  * @SINCE_1_0.0
63  * @param[in] i Input number
64  * @return    True if i is power of two.
65  */
66 inline bool IsPowerOfTwo( unsigned int i )
67 {
68   return (i != 0u) && ((i & (i - 1u)) == 0u);
69 }
70
71 /**
72  * @brief Clamp a value.
73  *
74  * @SINCE_1_0.0
75  * @param[in] value The value to clamp.
76  * @param[in] min The minimum allowed value.
77  * @param[in] max The maximum allowed value.
78  * @return T the clamped value
79  */
80 template< typename T >
81 inline const T& Clamp( const T& value, const T& min, const T& max )
82 {
83   const T& constrainedUpper = value < max ? value : max;
84   const T& constrainedUpperAndLower = constrainedUpper > min ? constrainedUpper : min;
85   return  constrainedUpperAndLower;
86 }
87
88 /**
89  * @brief Clamp a value directly.
90  *
91  * @SINCE_1_0.0
92  * @param[in,out] value The value that will be clamped.
93  * @param[in] min The minimum allowed value.
94  * @param[in] max The maximum allowed value.
95  */
96 template< typename T >
97 inline void ClampInPlace( T& value, const T& min, const T& max )
98 {
99   const T& constrainedUpper = value < max ? value : max;
100   const T& constrainedUpperAndLower = constrainedUpper > min ? constrainedUpper : min;
101   value = constrainedUpperAndLower;
102 }
103
104
105 /**
106  * @brief Linear interpolation between two values.
107  *
108  * @SINCE_1_0.0
109  * @param[in] offset The offset through the range @p low to @p high.
110  *                   This value is clamped between 0 and 1.
111  * @param[in] low    Lowest value in range
112  * @param[in] high   Highest value in range
113  * @return A value between low and high.
114  */
115 template< typename T >
116 inline const T Lerp( const float offset, const T& low, const T& high )
117 {
118   return low + ((high - low) * Clamp(offset, 0.0f, 1.0f));
119 }
120
121 /**
122  * @brief Get an epsilon that is valid for the given range.
123  *
124  * @SINCE_1_0.0
125  * @param[in] a the first value in the range
126  * @param[in] b the second value in the range.
127  * @return a suitable epsilon
128  */
129 inline float GetRangedEpsilon( float a, float b )
130 {
131   const float absA = fabsf( a );
132   const float absB = fabsf( b );
133   const float absF = absA > absB ? absA : absB;
134   const int absI = absF;
135
136   float epsilon = Math::MACHINE_EPSILON_10000;
137   if (absF < 0.1f)
138   {
139     return Math::MACHINE_EPSILON_0;
140   }
141   else if (absI < 2)
142   {
143     return Math::MACHINE_EPSILON_1;
144   }
145   else if (absI < 20)
146   {
147     return Math::MACHINE_EPSILON_10;
148   }
149   else if (absI < 200)
150   {
151     return Math::MACHINE_EPSILON_100;
152   }
153   else if (absI < 2000)
154   {
155     return Math::MACHINE_EPSILON_1000;
156   }
157   return epsilon;
158 }
159
160 /**
161  * @brief Helper function to compare equality of a floating point value with zero.
162  *
163  * @SINCE_1_0.0
164  * @param[in] value the value to compare
165  * @return true if the value is equal to zero
166  */
167 #pragma GCC diagnostic push
168 #pragma GCC diagnostic ignored "-Wfloat-equal"
169 inline bool EqualsZero( float value )
170 {
171   return value == 0.0f;
172 }
173 #pragma GCC diagnostic pop
174
175 /**
176  * @brief Helper function to compare equality of two floating point values.
177  *
178  * @SINCE_1_0.0
179  * @param[in] a the first value to compare
180  * @param[in] b the second value to compare
181  * @return true if the values are equal within a minimal epsilon for their values
182  */
183 inline bool Equals( float a, float b )
184 {
185   return ( fabsf( a - b ) <= GetRangedEpsilon( a, b ) );
186 }
187
188 /**
189  * @brief Helper function to compare equality of two floating point values.
190  *
191  * @SINCE_1_0.0
192  * @param[in] a the first value to compare
193  * @param[in] b the second value to compare
194  * @param[in] epsilon the minimum epsilon value that will be used to consider the values different
195  * @return true if the difference between the values is less than the epsilon
196  */
197 inline bool Equals( float a, float b, float epsilon )
198 {
199   return ( fabsf( a - b ) <= epsilon );
200 }
201
202 /**
203  * @brief Get an float that is rounded at specified place of decimals.
204  *
205  * @SINCE_1_0.0
206  * @param[in] value float value
207  * @param[in] pos decimal place
208  * @return a rounded float
209  */
210 inline float Round(float value, int pos)
211 {
212   float temp;
213   temp = value * powf( 10, pos );
214   temp = floorf( temp + 0.5 );
215   temp *= powf( 10, -pos );
216   return temp;
217 }
218
219 /**
220  * @brief Wrap x in domain (start) to (end).
221  *
222  * This works like a floating point version
223  * of the % modulo operation. But with an offset (start).
224  *
225  * For instance a domain is specified as:
226  * start: 2
227  * end: 8
228  *
229  * @code
230  *   2                         8
231  * (\ / start)               (\ / end)
232  *   |----x                    |
233  * @endcode
234  *
235  * The value x will be confined to this domain.
236  * If x is below 2 e.g. 0, then it is wraped to 6.
237  * If x is above or equal to 8 e.g. 8.1 then it is
238  * wrapped to 2.1.
239  *
240  * Domain wrapping is useful for various problems from
241  * calculating positions in a space that repeats, to
242  * computing angles that range from 0 to 360.
243  *
244  * @SINCE_1_0.0
245  * @param[in] x the point to be wrapped within the domain
246  * @param[in] start The start of the domain
247  * @param[in] end The end of the domain
248  *
249  * @return the wrapped value over the domain (start) (end)
250  * @note If start = end (i.e. size of domain 0), then wrapping will not occur
251  * and result will always be equal to start.
252  *
253  */
254 inline float WrapInDomain(float x, float start, float end)
255 {
256   float domain = end - start;
257   x -= start;
258
259   if(fabsf(domain) > Math::MACHINE_EPSILON_1)
260   {
261     return start + (x - floorf(x / domain) * domain);
262   }
263
264   return start;
265 }
266
267
268 /**
269  * @brief Find the shortest distance (magnitude) and direction (sign)
270  * from (a) to (b) in domain (start) to (end).
271  *
272  * @code
273  *  (\ / start)               (\ / end)
274  *    |-a                 b<----|
275  * @endcode
276  *
277  * Knowing the shortest distance is useful with wrapped domains
278  * to solve problems such as determing the closest object to
279  * a given point, or determing whether turning left or turning
280  * right is the shortest route to get from angle 10 degrees
281  * to angle 350 degrees (clearly in a 0-360 degree domain, turning
282  * left 20 degrees is quicker than turning right 340 degrees).
283  *
284  * The value returned holds the distance and the direction from
285  * value a to value b. For instance in the above example it would
286  * return -20. i.e. subtract 20 from current value (10) to reach
287  * target wrapped value (350).
288  *
289  * @SINCE_1_0.0
290  * @param a the current value
291  * @param b the target value
292  * @param start the start of the domain
293  * @param end the end of the domain
294  * @return the shortest direction (the sign) and distance (the magnitude)
295  * @note Assumes both (a) and (b) are already within the domain
296  * (start) to (end).
297  *
298  */
299 inline float ShortestDistanceInDomain( float a, float b, float start, float end )
300 {
301   //  (a-start + end-b)
302   float size = end-start;
303   float vect = b-a;
304
305   if(vect > 0)
306   {
307     // +ve vector, let's try perspective 1 domain to the right,
308     // and see if closer.
309     float aRight = a+size;
310     if( aRight-b < vect )
311     {
312       return b-aRight;
313     }
314   }
315   else
316   {
317     // -ve vector, let's try perspective 1 domain to the left,
318     // and see if closer.
319     float aLeft = a-size;
320     if( aLeft-b > vect )
321     {
322       return b-aLeft;
323     }
324   }
325
326   return vect;
327 }
328
329 /**
330  * @brief Extracts the sign of a number
331  *
332  * @SINCE_1_0.0
333  * @param[in] value The value we want to extract the sign
334  * @return -1 for negative values, +1 for positive values and 0 if value is 0
335  */
336 template <typename T>
337 int Sign( T value )
338 {
339   return ( T(0) < value ) - ( value < T(0) );
340 }
341
342 /**
343  * @}
344  */
345 } // namespace Dali
346
347 #endif // __DALI_MATH_UTILS_H__