Cry_ValidNumber.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #ifndef CRYINCLUDE_CRYCOMMON_CRY_VALIDNUMBER_H
  9. #define CRYINCLUDE_CRYCOMMON_CRY_VALIDNUMBER_H
  10. #pragma once
  11. //--------------------------------------------------------------------------------
  12. // http://www.psc.edu/general/software/packages/ieee/ieee.html
  13. /*
  14. The IEEE standard for floating point arithmetic
  15. """"""""""""""""""""""""""""""""""""""""""""""""
  16. Single Precision
  17. """""""""""""""""
  18. The IEEE single precision floating point standard representation requires a 32 bit word,
  19. which may be represented as numbered from 0 to 31, left to right.
  20. The first bit is the sign bit, S,
  21. the next eight bits are the exponent bits, 'E',
  22. and the final 23 bits are the fraction 'F':
  23. S EEEEEEEE FFFFFFFFFFFFFFFFFFFFFFF
  24. 0 1 8 9 31
  25. The value V represented by the word may be determined as follows:
  26. * If E=255 and F is nonzero, then V=NaN ("Not a number")
  27. * If E=255 and F is zero and S is 1, then V=-Infinity
  28. * If E=255 and F is zero and S is 0, then V=Infinity
  29. * If 0<E<255 then V=(-1)**S * 2 ** (E-127) * (1.F) where "1.F" is intended to represent the binary number created by prefixing F with an implicit leading 1 and a binary point.
  30. * If E=0 and F is nonzero, then V=(-1)**S * 2 ** (-126) * (0.F) These are "unnormalized" values.
  31. * If E=0 and F is zero and S is 1, then V=-0
  32. * If E=0 and F is zero and S is 0, then V=0
  33. Double Precision
  34. """""""""""""""""
  35. The IEEE double precision floating point standard representation requires a 64 bit word,
  36. which may be represented as numbered from 0 to 63, left to right.
  37. The first bit is the sign bit, S,
  38. the next eleven bits are the exponent bits, 'E',
  39. and the final 52 bits are the fraction 'F':
  40. S EEEEEEEEEEE FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
  41. 0 1 11 12 63
  42. The value V represented by the word may be determined as follows:
  43. * If E=2047 and F is nonzero, then V=NaN ("Not a number")
  44. * If E=2047 and F is zero and S is 1, then V=-Infinity
  45. * If E=2047 and F is zero and S is 0, then V=Infinity
  46. * If 0<E<2047 then V=(-1)**S * 2 ** (E-1023) * (1.F) where "1.F" is intended to represent the binary number created by prefixing F with an implicit leading 1 and a binary point.
  47. * If E=0 and F is nonzero, then V=(-1)**S * 2 ** (-1022) * (0.F) These are "unnormalized" values.
  48. * If E=0 and F is zero and S is 1, then V=-0
  49. * If E=0 and F is zero and S is 0, then V=0
  50. */
  51. //--------------------------------------------------------------------------------
  52. #define FloatU32(x) (alias_cast<uint32, float>(x))
  53. #define FloatU32ExpMask (0xFF << 23)
  54. #define FloatU32FracMask ((1 << 23) - 1)
  55. #define FloatU32SignMask (1 << 31)
  56. #define F32NAN (0x7F800001) // Produces rock solid fp-exceptions.
  57. #define F32NAN_SAFE (FloatU32ExpMask | FloatU32FracMask) // This one is not triggering an fp-exception.
  58. #define DoubleU64(x) (*((uint64*) &(x)))
  59. #define DoubleU64ExpMask ((uint64)255 << 55)
  60. #define DoubleU64FracMask (((uint64)1 << 55) - (uint64)1)
  61. #define DoubleU64SignMask ((uint64)1 << 63)
  62. #if defined(__GNUC__)
  63. #define F64NAN (0x7FF0000000000001ULL) // Produces rock solid fp-exceptions.
  64. #else
  65. #define F64NAN (0x7FF0000000000001) // Produces rock solid fp-exceptions.
  66. #endif
  67. #define F64NAN_SAFE (DoubleU64ExpMask | DoubleU64FracMask) // This one is not triggering an fp-exception.
  68. //--------------------------------------------------------------------------------
  69. ILINE bool NumberValid(const float& x)
  70. {
  71. return ((FloatU32(x) & FloatU32ExpMask) != FloatU32ExpMask);
  72. }
  73. ILINE bool NumberNAN(const float& x)
  74. {
  75. return (((FloatU32(x) & FloatU32ExpMask) == FloatU32ExpMask) &&
  76. ((FloatU32(x) & FloatU32FracMask) != 0));
  77. }
  78. ILINE bool NumberINF(const float& x)
  79. {
  80. return (((FloatU32(x) & FloatU32ExpMask) == FloatU32ExpMask) &&
  81. ((FloatU32(x) & FloatU32FracMask) == 0));
  82. }
  83. ILINE bool NumberDEN(const float& x)
  84. {
  85. return (((FloatU32(x) & FloatU32ExpMask) == 0) &&
  86. ((FloatU32(x) & FloatU32FracMask) != 0));
  87. }
  88. //--------------------------------------------------------------------------------
  89. ILINE bool NumberValid(const double& x)
  90. {
  91. return ((DoubleU64(x) & DoubleU64ExpMask) != DoubleU64ExpMask);
  92. }
  93. ILINE bool NumberNAN(const double& x)
  94. {
  95. return (((DoubleU64(x) & DoubleU64ExpMask) == DoubleU64ExpMask) &&
  96. ((DoubleU64(x) & DoubleU64FracMask) != 0));
  97. }
  98. ILINE bool NumberINF(const double& x)
  99. {
  100. return (((DoubleU64(x) & DoubleU64ExpMask) == DoubleU64ExpMask) &&
  101. ((DoubleU64(x) & DoubleU64FracMask) == 0));
  102. }
  103. ILINE bool NumberDEN(const double& x)
  104. {
  105. return (((DoubleU64(x) & DoubleU64ExpMask) == 0) &&
  106. ((DoubleU64(x) & DoubleU64FracMask) != 0));
  107. }
  108. //--------------------------------------------------------------------------------
  109. ILINE bool NumberValid([[maybe_unused]] const int8 x)
  110. {
  111. return true; //integers are always valid
  112. }
  113. ILINE bool NumberValid([[maybe_unused]] const uint8 x)
  114. {
  115. return true; //integers are always valid
  116. }
  117. ILINE bool NumberValid([[maybe_unused]] const int16 x)
  118. {
  119. return true; //integers are always valid
  120. }
  121. ILINE bool NumberValid([[maybe_unused]] const uint16 x)
  122. {
  123. return true; //integers are always valid
  124. }
  125. ILINE bool NumberValid([[maybe_unused]] const int32 x)
  126. {
  127. return true; //integers are always valid
  128. }
  129. ILINE bool NumberValid([[maybe_unused]] const uint32 x)
  130. {
  131. return true; //integers are always valid
  132. }
  133. ILINE bool NumberValid([[maybe_unused]] const int64 x)
  134. {
  135. return true; //integers are always valid
  136. }
  137. ILINE bool NumberValid([[maybe_unused]] const uint64 x)
  138. {
  139. return true; //integers are always valid
  140. }
  141. #endif // CRYINCLUDE_CRYCOMMON_CRY_VALIDNUMBER_H