llcommonmath.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /**
  2. * @file llcommonmath.h
  3. *
  4. * $LicenseInfo:firstyear=2009&license=viewergpl$
  5. *
  6. * Copyright (c) 2009, Linden Research, Inc.
  7. *
  8. * Second Life Viewer Source Code
  9. * The source code in this file ("Source Code") is provided by Linden Lab
  10. * to you under the terms of the GNU General Public License, version 2.0
  11. * ("GPL"), unless you have obtained a separate licensing agreement
  12. * ("Other License"), formally executed by you and Linden Lab. Terms of
  13. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  14. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  15. *
  16. * There are special exceptions to the terms and conditions of the GPL as
  17. * it is applied to this Source Code. View the full text of the exception
  18. * in the file doc/FLOSS-exception.txt in this software distribution, or
  19. * online at
  20. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  21. *
  22. * By copying, modifying or distributing this software, you acknowledge
  23. * that you have read and understood your obligations described above,
  24. * and agree to abide by those obligations.
  25. *
  26. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  27. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  28. * COMPLETENESS OR PERFORMANCE.
  29. * $/LicenseInfo$
  30. */
  31. #ifndef LL_COMMONMATH_H
  32. #define LL_COMMONMATH_H
  33. #include <cmath>
  34. #include <cstdlib>
  35. #include "llpreprocessor.h"
  36. #include "stdtypes.h"
  37. // Work-around for Windows
  38. #if LL_WINDOWS
  39. # include <float.h>
  40. # define llisnan(val) _isnan(val)
  41. # define llfinite(val) _finite(val)
  42. #else
  43. # define llisnan(val) std::isnan(val)
  44. # define llfinite(val) std::isfinite(val)
  45. #endif
  46. // llsd.cpp uses llisnan() and llsdutil.cpp uses is_approx_equal_fraction(),
  47. // they were moved from llmath.h in llcommon so that llcommon does not depend
  48. // on llmath. HB
  49. // Originally llmath.h contained two complete implementations of
  50. // is_approx_equal_fraction(), with signatures as below, bodies identical save
  51. // where they specifically mentioned F32/F64. Unifying these into a template
  52. // makes sense, but to preserve the compiler's overload-selection behavior, we
  53. // still wrap the template implementation with the specific overloaded
  54. // signatures.
  55. template <typename FTYPE>
  56. LL_INLINE bool is_approx_equal_fraction_impl(FTYPE x, FTYPE y, U32 frac_bits)
  57. {
  58. FTYPE diff = (FTYPE)fabs(x - y);
  59. S32 diff_int = (S32)diff;
  60. S32 frac_tolerance = (S32)((diff - (FTYPE)diff_int) * (1 << frac_bits));
  61. // If integer portion is not equal, not enough bits were used for packing
  62. // so error out since either the use case is not correct OR there is an
  63. // issue with pack/unpack. should fail in either case.
  64. // For decimal portion, make sure that the delta is no more than 1 based on
  65. // the number of bits used for packing decimal portion.
  66. return diff_int == 0 && frac_tolerance <= 1;
  67. }
  68. // F32 flavor
  69. LL_INLINE bool is_approx_equal_fraction(F32 x, F32 y, U32 frac_bits)
  70. {
  71. return is_approx_equal_fraction_impl<F32>(x, y, frac_bits);
  72. }
  73. // F64 flavor
  74. LL_INLINE bool is_approx_equal_fraction(F64 x, F64 y, U32 frac_bits)
  75. {
  76. return is_approx_equal_fraction_impl<F64>(x, y, frac_bits);
  77. }
  78. // Formerly in u64.h - Converts an U64 to the closest F64 value.
  79. LL_INLINE F64 U64_to_F64(U64 value)
  80. {
  81. S64 top_bits = (S64)(value >> 1);
  82. F64 result = (F64)top_bits;
  83. result *= 2.f;
  84. result += (U32)(value & 0x01);
  85. return result;
  86. }
  87. // The functions below used to be in the now removed lldefs.h header and have
  88. // been moved here for coherency (these are math functions, not constants). HB
  89. // Specific inlines for basic types.
  90. //
  91. // defined for all:
  92. // llmin(a, b)
  93. // llmax(a, b)
  94. // llclamp(a, minimum, maximum)
  95. //
  96. // defined for F32, F64:
  97. // llclampf(a) // clamps a to [0.0 .. 1.0]
  98. //
  99. // defined for U16, U32, U64, S16, S32, S64, :
  100. // llclampb(a) // clamps a to [0 .. 255]
  101. template <typename T1, typename T2>
  102. LL_INLINE T1 llmax(T1 d1, T2 d2)
  103. {
  104. return d1 > (T1)d2 ? d1 : (T1)d2;
  105. }
  106. template <typename T1, typename T2, typename T3>
  107. LL_INLINE auto llmax(T1 d1, T2 d2, T3 d3)
  108. {
  109. T1 r = d1 > d2 ? d1 : d2;
  110. return r > d3 ? r : d3;
  111. }
  112. template <typename T1, typename T2, typename T3, typename T4>
  113. LL_INLINE T1 llmax(T1 d1, T2 d2, T3 d3, T4 d4)
  114. {
  115. T1 r1 = d1 > (T1)d2 ? d1 : (T1)d2;
  116. T1 r2 = (T1)d3 > (T1)d4 ? (T1)d3 : (T1)d4;
  117. return r1 > r2 ? r1 : r2;
  118. }
  119. template <typename T1, typename T2>
  120. LL_INLINE T1 llmin(T1 d1, T2 d2)
  121. {
  122. return d1 < (T1)d2 ? d1 : (T1)d2;
  123. }
  124. template <typename T1, typename T2, typename T3>
  125. LL_INLINE T1 llmin(T1 d1, T2 d2, T3 d3)
  126. {
  127. T1 r = d1 < (T1)d2 ? d1 : (T1)d2;
  128. return r < d3 ? r : (T1)d3;
  129. }
  130. template <typename T1, typename T2, typename T3, typename T4>
  131. LL_INLINE T1 llmin(T1 d1, T2 d2, T3 d3, T4 d4)
  132. {
  133. T1 r1 = d1 < (T1)d2 ? d1 : (T1)d2;
  134. T1 r2 = (T1)d3 < (T1)d4 ? (T1)d3 : (T1)d4;
  135. return r1 < r2 ? r1 : r2;
  136. }
  137. template <typename T1, typename T2, typename T3>
  138. LL_INLINE T1 llclamp(T1 a, T2 minval, T3 maxval)
  139. {
  140. if (a < (T1)minval)
  141. {
  142. return (T1)minval;
  143. }
  144. if (a > (T1)maxval)
  145. {
  146. return (T1)maxval;
  147. }
  148. return a;
  149. }
  150. template <class T>
  151. LL_INLINE T llclampf(T a)
  152. {
  153. if (a < (T)0)
  154. {
  155. return (T)0;
  156. }
  157. if (a > (T)1)
  158. {
  159. return (T)1;
  160. }
  161. return a;
  162. }
  163. template <class T>
  164. LL_INLINE T llclampb(T a)
  165. {
  166. if (a < (T)0)
  167. {
  168. return (T)0;
  169. }
  170. if (a > (T)255)
  171. {
  172. return (T)255;
  173. }
  174. return a;
  175. }
  176. #endif // LL_COMMONMATH_H