float.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /*-------------------------------------------------------------------------
  2. *
  3. * float.h
  4. * Definitions for the built-in floating-point types
  5. *
  6. * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
  7. * Portions Copyright (c) 1994, Regents of the University of California
  8. *
  9. *
  10. * IDENTIFICATION
  11. * src/include/utils/float.h
  12. *
  13. *-------------------------------------------------------------------------
  14. */
  15. #ifndef FLOAT_H
  16. #define FLOAT_H
  17. #include <math.h>
  18. #ifndef M_PI
  19. /* From my RH5.2 gcc math.h file - thomas 2000-04-03 */
  20. #define M_PI 3.14159265358979323846
  21. #endif
  22. /* Radians per degree, a.k.a. PI / 180 */
  23. #define RADIANS_PER_DEGREE 0.0174532925199432957692
  24. /* Visual C++ etc lacks NAN, and won't accept 0.0/0.0. */
  25. #if defined(WIN32) && !defined(NAN)
  26. static const uint32 nan[2] = {0xffffffff, 0x7fffffff};
  27. #define NAN (*(const float8 *) nan)
  28. #endif
  29. extern PGDLLIMPORT int extra_float_digits;
  30. /*
  31. * Utility functions in float.c
  32. */
  33. extern void float_overflow_error(void) pg_attribute_noreturn();
  34. extern void float_underflow_error(void) pg_attribute_noreturn();
  35. extern void float_zero_divide_error(void) pg_attribute_noreturn();
  36. extern int is_infinite(float8 val);
  37. extern float8 float8in_internal(char *num, char **endptr_p,
  38. const char *type_name, const char *orig_string);
  39. extern float8 float8in_internal_opt_error(char *num, char **endptr_p,
  40. const char *type_name, const char *orig_string,
  41. bool *have_error);
  42. extern char *float8out_internal(float8 num);
  43. extern int float4_cmp_internal(float4 a, float4 b);
  44. extern int float8_cmp_internal(float8 a, float8 b);
  45. /*
  46. * Routines to provide reasonably platform-independent handling of
  47. * infinity and NaN
  48. *
  49. * We assume that isinf() and isnan() are available and work per spec.
  50. * (On some platforms, we have to supply our own; see src/port.) However,
  51. * generating an Infinity or NaN in the first place is less well standardized;
  52. * pre-C99 systems tend not to have C99's INFINITY and NaN macros. We
  53. * centralize our workarounds for this here.
  54. */
  55. /*
  56. * The funny placements of the two #pragmas is necessary because of a
  57. * long lived bug in the Microsoft compilers.
  58. * See http://support.microsoft.com/kb/120968/en-us for details
  59. */
  60. #ifdef _MSC_VER
  61. #pragma warning(disable:4756)
  62. #endif
  63. static inline float4
  64. get_float4_infinity(void)
  65. {
  66. #ifdef INFINITY
  67. /* C99 standard way */
  68. return (float4) INFINITY;
  69. #else
  70. #ifdef _MSC_VER
  71. #pragma warning(default:4756)
  72. #endif
  73. /*
  74. * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the
  75. * largest normal float8. We assume forcing an overflow will get us a
  76. * true infinity.
  77. */
  78. return (float4) (HUGE_VAL * HUGE_VAL);
  79. #endif
  80. }
  81. static inline float8
  82. get_float8_infinity(void)
  83. {
  84. #ifdef INFINITY
  85. /* C99 standard way */
  86. return (float8) INFINITY;
  87. #else
  88. /*
  89. * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the
  90. * largest normal float8. We assume forcing an overflow will get us a
  91. * true infinity.
  92. */
  93. return (float8) (HUGE_VAL * HUGE_VAL);
  94. #endif
  95. }
  96. static inline float4
  97. get_float4_nan(void)
  98. {
  99. #ifdef NAN
  100. /* C99 standard way */
  101. return (float4) NAN;
  102. #else
  103. /* Assume we can get a NAN via zero divide */
  104. return (float4) (0.0 / 0.0);
  105. #endif
  106. }
  107. static inline float8
  108. get_float8_nan(void)
  109. {
  110. /* (float8) NAN doesn't work on some NetBSD/MIPS releases */
  111. #if defined(NAN) && !(defined(__NetBSD__) && defined(__mips__))
  112. /* C99 standard way */
  113. return (float8) NAN;
  114. #else
  115. /* Assume we can get a NaN via zero divide */
  116. return (float8) (0.0 / 0.0);
  117. #endif
  118. }
  119. /*
  120. * Floating-point arithmetic with overflow/underflow reported as errors
  121. *
  122. * There isn't any way to check for underflow of addition/subtraction
  123. * because numbers near the underflow value have already been rounded to
  124. * the point where we can't detect that the two values were originally
  125. * different, e.g. on x86, '1e-45'::float4 == '2e-45'::float4 ==
  126. * 1.4013e-45.
  127. */
  128. static inline float4
  129. float4_pl(const float4 val1, const float4 val2)
  130. {
  131. float4 result;
  132. result = val1 + val2;
  133. if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
  134. float_overflow_error();
  135. return result;
  136. }
  137. static inline float8
  138. float8_pl(const float8 val1, const float8 val2)
  139. {
  140. float8 result;
  141. result = val1 + val2;
  142. if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
  143. float_overflow_error();
  144. return result;
  145. }
  146. static inline float4
  147. float4_mi(const float4 val1, const float4 val2)
  148. {
  149. float4 result;
  150. result = val1 - val2;
  151. if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
  152. float_overflow_error();
  153. return result;
  154. }
  155. static inline float8
  156. float8_mi(const float8 val1, const float8 val2)
  157. {
  158. float8 result;
  159. result = val1 - val2;
  160. if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
  161. float_overflow_error();
  162. return result;
  163. }
  164. static inline float4
  165. float4_mul(const float4 val1, const float4 val2)
  166. {
  167. float4 result;
  168. result = val1 * val2;
  169. if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
  170. float_overflow_error();
  171. if (unlikely(result == 0.0f) && val1 != 0.0f && val2 != 0.0f)
  172. float_underflow_error();
  173. return result;
  174. }
  175. static inline float8
  176. float8_mul(const float8 val1, const float8 val2)
  177. {
  178. float8 result;
  179. result = val1 * val2;
  180. if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
  181. float_overflow_error();
  182. if (unlikely(result == 0.0) && val1 != 0.0 && val2 != 0.0)
  183. float_underflow_error();
  184. return result;
  185. }
  186. static inline float4
  187. float4_div(const float4 val1, const float4 val2)
  188. {
  189. float4 result;
  190. if (unlikely(val2 == 0.0f) && !isnan(val1))
  191. float_zero_divide_error();
  192. result = val1 / val2;
  193. if (unlikely(isinf(result)) && !isinf(val1))
  194. float_overflow_error();
  195. if (unlikely(result == 0.0f) && val1 != 0.0f && !isinf(val2))
  196. float_underflow_error();
  197. return result;
  198. }
  199. static inline float8
  200. float8_div(const float8 val1, const float8 val2)
  201. {
  202. float8 result;
  203. if (unlikely(val2 == 0.0) && !isnan(val1))
  204. float_zero_divide_error();
  205. result = val1 / val2;
  206. if (unlikely(isinf(result)) && !isinf(val1))
  207. float_overflow_error();
  208. if (unlikely(result == 0.0) && val1 != 0.0 && !isinf(val2))
  209. float_underflow_error();
  210. return result;
  211. }
  212. /*
  213. * Routines for NaN-aware comparisons
  214. *
  215. * We consider all NaNs to be equal and larger than any non-NaN. This is
  216. * somewhat arbitrary; the important thing is to have a consistent sort
  217. * order.
  218. */
  219. static inline bool
  220. float4_eq(const float4 val1, const float4 val2)
  221. {
  222. return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
  223. }
  224. static inline bool
  225. float8_eq(const float8 val1, const float8 val2)
  226. {
  227. return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
  228. }
  229. static inline bool
  230. float4_ne(const float4 val1, const float4 val2)
  231. {
  232. return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
  233. }
  234. static inline bool
  235. float8_ne(const float8 val1, const float8 val2)
  236. {
  237. return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
  238. }
  239. static inline bool
  240. float4_lt(const float4 val1, const float4 val2)
  241. {
  242. return !isnan(val1) && (isnan(val2) || val1 < val2);
  243. }
  244. static inline bool
  245. float8_lt(const float8 val1, const float8 val2)
  246. {
  247. return !isnan(val1) && (isnan(val2) || val1 < val2);
  248. }
  249. static inline bool
  250. float4_le(const float4 val1, const float4 val2)
  251. {
  252. return isnan(val2) || (!isnan(val1) && val1 <= val2);
  253. }
  254. static inline bool
  255. float8_le(const float8 val1, const float8 val2)
  256. {
  257. return isnan(val2) || (!isnan(val1) && val1 <= val2);
  258. }
  259. static inline bool
  260. float4_gt(const float4 val1, const float4 val2)
  261. {
  262. return !isnan(val2) && (isnan(val1) || val1 > val2);
  263. }
  264. static inline bool
  265. float8_gt(const float8 val1, const float8 val2)
  266. {
  267. return !isnan(val2) && (isnan(val1) || val1 > val2);
  268. }
  269. static inline bool
  270. float4_ge(const float4 val1, const float4 val2)
  271. {
  272. return isnan(val1) || (!isnan(val2) && val1 >= val2);
  273. }
  274. static inline bool
  275. float8_ge(const float8 val1, const float8 val2)
  276. {
  277. return isnan(val1) || (!isnan(val2) && val1 >= val2);
  278. }
  279. static inline float4
  280. float4_min(const float4 val1, const float4 val2)
  281. {
  282. return float4_lt(val1, val2) ? val1 : val2;
  283. }
  284. static inline float8
  285. float8_min(const float8 val1, const float8 val2)
  286. {
  287. return float8_lt(val1, val2) ? val1 : val2;
  288. }
  289. static inline float4
  290. float4_max(const float4 val1, const float4 val2)
  291. {
  292. return float4_gt(val1, val2) ? val1 : val2;
  293. }
  294. static inline float8
  295. float8_max(const float8 val1, const float8 val2)
  296. {
  297. return float8_gt(val1, val2) ? val1 : val2;
  298. }
  299. #endif /* FLOAT_H */