LCOV - code coverage report
Current view: top level - src/include/utils - float.h (source / functions) Hit Total Coverage
Test: PostgreSQL 12beta2 Lines: 84 86 97.7 %
Date: 2019-06-19 14:06:47 Functions: 28 28 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * float.h
       4             :  *    Definitions for the built-in floating-point types
       5             :  *
       6             :  * Portions Copyright (c) 1996-2019, 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             : 
      18             : #include <math.h>
      19             : 
      20             : #ifndef M_PI
      21             : /* From my RH5.2 gcc math.h file - thomas 2000-04-03 */
      22             : #define M_PI 3.14159265358979323846
      23             : #endif
      24             : 
      25             : /* Radians per degree, a.k.a. PI / 180 */
      26             : #define RADIANS_PER_DEGREE 0.0174532925199432957692
      27             : 
      28             : /* Visual C++ etc lacks NAN, and won't accept 0.0/0.0. */
      29             : #if defined(WIN32) && !defined(NAN)
      30             : static const uint32 nan[2] = {0xffffffff, 0x7fffffff};
      31             : 
      32             : #define NAN (*(const float8 *) nan)
      33             : #endif
      34             : 
      35             : extern PGDLLIMPORT int extra_float_digits;
      36             : 
      37             : /*
      38             :  * Utility functions in float.c
      39             :  */
      40             : extern int  is_infinite(float8 val);
      41             : extern float8 float8in_internal(char *num, char **endptr_p,
      42             :                                 const char *type_name, const char *orig_string);
      43             : extern float8 float8in_internal_opt_error(char *num, char **endptr_p,
      44             :                                           const char *type_name, const char *orig_string,
      45             :                                           bool *have_error);
      46             : extern char *float8out_internal(float8 num);
      47             : extern int  float4_cmp_internal(float4 a, float4 b);
      48             : extern int  float8_cmp_internal(float8 a, float8 b);
      49             : 
      50             : /*
      51             :  * Routines to provide reasonably platform-independent handling of
      52             :  * infinity and NaN
      53             :  *
      54             :  * We assume that isinf() and isnan() are available and work per spec.
      55             :  * (On some platforms, we have to supply our own; see src/port.)  However,
      56             :  * generating an Infinity or NaN in the first place is less well standardized;
      57             :  * pre-C99 systems tend not to have C99's INFINITY and NaN macros.  We
      58             :  * centralize our workarounds for this here.
      59             :  */
      60             : 
      61             : /*
      62             :  * The funny placements of the two #pragmas is necessary because of a
      63             :  * long lived bug in the Microsoft compilers.
      64             :  * See http://support.microsoft.com/kb/120968/en-us for details
      65             :  */
      66             : #if (_MSC_VER >= 1800)
      67             : #pragma warning(disable:4756)
      68             : #endif
      69             : static inline float4
      70      201944 : get_float4_infinity(void)
      71             : {
      72             : #ifdef INFINITY
      73             :     /* C99 standard way */
      74      201944 :     return (float4) INFINITY;
      75             : #else
      76             : #if (_MSC_VER >= 1800)
      77             : #pragma warning(default:4756)
      78             : #endif
      79             : 
      80             :     /*
      81             :      * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the
      82             :      * largest normal float8.  We assume forcing an overflow will get us a
      83             :      * true infinity.
      84             :      */
      85             :     return (float4) (HUGE_VAL * HUGE_VAL);
      86             : #endif
      87             : }
      88             : 
      89             : static inline float8
      90        5018 : get_float8_infinity(void)
      91             : {
      92             : #ifdef INFINITY
      93             :     /* C99 standard way */
      94        5018 :     return (float8) INFINITY;
      95             : #else
      96             : 
      97             :     /*
      98             :      * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the
      99             :      * largest normal float8.  We assume forcing an overflow will get us a
     100             :      * true infinity.
     101             :      */
     102             :     return (float8) (HUGE_VAL * HUGE_VAL);
     103             : #endif
     104             : }
     105             : 
     106             : static inline float4
     107           4 : get_float4_nan(void)
     108             : {
     109             : #ifdef NAN
     110             :     /* C99 standard way */
     111           4 :     return (float4) NAN;
     112             : #else
     113             :     /* Assume we can get a NAN via zero divide */
     114             :     return (float4) (0.0 / 0.0);
     115             : #endif
     116             : }
     117             : 
     118             : static inline float8
     119       11728 : get_float8_nan(void)
     120             : {
     121             :     /* (float8) NAN doesn't work on some NetBSD/MIPS releases */
     122             : #if defined(NAN) && !(defined(__NetBSD__) && defined(__mips__))
     123             :     /* C99 standard way */
     124       11728 :     return (float8) NAN;
     125             : #else
     126             :     /* Assume we can get a NaN via zero divide */
     127             :     return (float8) (0.0 / 0.0);
     128             : #endif
     129             : }
     130             : 
     131             : /*
     132             :  * Checks to see if a float4/8 val has underflowed or overflowed
     133             :  */
     134             : 
     135             : static inline void
     136     3880108 : check_float4_val(const float4 val, const bool inf_is_valid,
     137             :                  const bool zero_is_valid)
     138             : {
     139     3880108 :     if (!inf_is_valid && unlikely(isinf(val)))
     140           0 :         ereport(ERROR,
     141             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     142             :                  errmsg("value out of range: overflow")));
     143             : 
     144     3880108 :     if (!zero_is_valid && unlikely(val == 0.0))
     145           0 :         ereport(ERROR,
     146             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     147             :                  errmsg("value out of range: underflow")));
     148     3880108 : }
     149             : 
     150             : static inline void
     151   239445116 : check_float8_val(const float8 val, const bool inf_is_valid,
     152             :                  const bool zero_is_valid)
     153             : {
     154   239445116 :     if (!inf_is_valid && unlikely(isinf(val)))
     155          16 :         ereport(ERROR,
     156             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     157             :                  errmsg("value out of range: overflow")));
     158             : 
     159   239445100 :     if (!zero_is_valid && unlikely(val == 0.0))
     160           8 :         ereport(ERROR,
     161             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     162             :                  errmsg("value out of range: underflow")));
     163   239445092 : }
     164             : 
     165             : /*
     166             :  * Routines for operations with the checks above
     167             :  *
     168             :  * There isn't any way to check for underflow of addition/subtraction
     169             :  * because numbers near the underflow value have already been rounded to
     170             :  * the point where we can't detect that the two values were originally
     171             :  * different, e.g. on x86, '1e-45'::float4 == '2e-45'::float4 ==
     172             :  * 1.4013e-45.
     173             :  */
     174             : 
     175             : static inline float4
     176          36 : float4_pl(const float4 val1, const float4 val2)
     177             : {
     178             :     float4      result;
     179             : 
     180          36 :     result = val1 + val2;
     181          36 :     check_float4_val(result, isinf(val1) || isinf(val2), true);
     182             : 
     183          36 :     return result;
     184             : }
     185             : 
     186             : static inline float8
     187     2451144 : float8_pl(const float8 val1, const float8 val2)
     188             : {
     189             :     float8      result;
     190             : 
     191     2451144 :     result = val1 + val2;
     192     2451144 :     check_float8_val(result, isinf(val1) || isinf(val2), true);
     193             : 
     194     2451144 :     return result;
     195             : }
     196             : 
     197             : static inline float4
     198          12 : float4_mi(const float4 val1, const float4 val2)
     199             : {
     200             :     float4      result;
     201             : 
     202          12 :     result = val1 - val2;
     203          12 :     check_float4_val(result, isinf(val1) || isinf(val2), true);
     204             : 
     205          12 :     return result;
     206             : }
     207             : 
     208             : static inline float8
     209   156803520 : float8_mi(const float8 val1, const float8 val2)
     210             : {
     211             :     float8      result;
     212             : 
     213   156803520 :     result = val1 - val2;
     214   156803520 :     check_float8_val(result, isinf(val1) || isinf(val2), true);
     215             : 
     216   156803520 :     return result;
     217             : }
     218             : 
     219             : static inline float4
     220          24 : float4_mul(const float4 val1, const float4 val2)
     221             : {
     222             :     float4      result;
     223             : 
     224          24 :     result = val1 * val2;
     225          24 :     check_float4_val(result, isinf(val1) || isinf(val2),
     226          24 :                      val1 == 0.0f || val2 == 0.0f);
     227             : 
     228          24 :     return result;
     229             : }
     230             : 
     231             : static inline float8
     232    64144986 : float8_mul(const float8 val1, const float8 val2)
     233             : {
     234             :     float8      result;
     235             : 
     236    64144986 :     result = val1 * val2;
     237    64144986 :     check_float8_val(result, isinf(val1) || isinf(val2),
     238    64144986 :                      val1 == 0.0 || val2 == 0.0);
     239             : 
     240    64144970 :     return result;
     241             : }
     242             : 
     243             : static inline float4
     244     3880040 : float4_div(const float4 val1, const float4 val2)
     245             : {
     246             :     float4      result;
     247             : 
     248     3880040 :     if (val2 == 0.0f)
     249           4 :         ereport(ERROR,
     250             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
     251             :                  errmsg("division by zero")));
     252             : 
     253     3880036 :     result = val1 / val2;
     254     3880036 :     check_float4_val(result, isinf(val1) || isinf(val2), val1 == 0.0f);
     255             : 
     256     3880036 :     return result;
     257             : }
     258             : 
     259             : static inline float8
     260     8804928 : float8_div(const float8 val1, const float8 val2)
     261             : {
     262             :     float8      result;
     263             : 
     264     8804928 :     if (val2 == 0.0)
     265          40 :         ereport(ERROR,
     266             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
     267             :                  errmsg("division by zero")));
     268             : 
     269     8804888 :     result = val1 / val2;
     270     8804888 :     check_float8_val(result, isinf(val1) || isinf(val2), val1 == 0.0);
     271             : 
     272     8804888 :     return result;
     273             : }
     274             : 
     275             : /*
     276             :  * Routines for NaN-aware comparisons
     277             :  *
     278             :  * We consider all NaNs to be equal and larger than any non-NaN. This is
     279             :  * somewhat arbitrary; the important thing is to have a consistent sort
     280             :  * order.
     281             :  */
     282             : 
     283             : static inline bool
     284       40436 : float4_eq(const float4 val1, const float4 val2)
     285             : {
     286       40436 :     return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
     287             : }
     288             : 
     289             : static inline bool
     290    10212964 : float8_eq(const float8 val1, const float8 val2)
     291             : {
     292    10212964 :     return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
     293             : }
     294             : 
     295             : static inline bool
     296          20 : float4_ne(const float4 val1, const float4 val2)
     297             : {
     298          20 :     return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
     299             : }
     300             : 
     301             : static inline bool
     302       11796 : float8_ne(const float8 val1, const float8 val2)
     303             : {
     304       11796 :     return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
     305             : }
     306             : 
     307             : static inline bool
     308    26372586 : float4_lt(const float4 val1, const float4 val2)
     309             : {
     310    26372586 :     return !isnan(val1) && (isnan(val2) || val1 < val2);
     311             : }
     312             : 
     313             : static inline bool
     314    76311606 : float8_lt(const float8 val1, const float8 val2)
     315             : {
     316    76311606 :     return !isnan(val1) && (isnan(val2) || val1 < val2);
     317             : }
     318             : 
     319             : static inline bool
     320        1620 : float4_le(const float4 val1, const float4 val2)
     321             : {
     322        1620 :     return isnan(val2) || (!isnan(val1) && val1 <= val2);
     323             : }
     324             : 
     325             : static inline bool
     326   105600376 : float8_le(const float8 val1, const float8 val2)
     327             : {
     328   105600376 :     return isnan(val2) || (!isnan(val1) && val1 <= val2);
     329             : }
     330             : 
     331             : static inline bool
     332    27034578 : float4_gt(const float4 val1, const float4 val2)
     333             : {
     334    27034578 :     return !isnan(val2) && (isnan(val1) || val1 > val2);
     335             : }
     336             : 
     337             : static inline bool
     338    82044418 : float8_gt(const float8 val1, const float8 val2)
     339             : {
     340    82044418 :     return !isnan(val2) && (isnan(val1) || val1 > val2);
     341             : }
     342             : 
     343             : static inline bool
     344        1620 : float4_ge(const float4 val1, const float4 val2)
     345             : {
     346        1620 :     return isnan(val1) || (!isnan(val2) && val1 >= val2);
     347             : }
     348             : 
     349             : static inline bool
     350     4330714 : float8_ge(const float8 val1, const float8 val2)
     351             : {
     352     4330714 :     return isnan(val1) || (!isnan(val2) && val1 >= val2);
     353             : }
     354             : 
     355             : static inline float4
     356             : float4_min(const float4 val1, const float4 val2)
     357             : {
     358             :     return float4_lt(val1, val2) ? val1 : val2;
     359             : }
     360             : 
     361             : static inline float8
     362    58957444 : float8_min(const float8 val1, const float8 val2)
     363             : {
     364    58957444 :     return float8_lt(val1, val2) ? val1 : val2;
     365             : }
     366             : 
     367             : static inline float4
     368             : float4_max(const float4 val1, const float4 val2)
     369             : {
     370             :     return float4_gt(val1, val2) ? val1 : val2;
     371             : }
     372             : 
     373             : static inline float8
     374    58957444 : float8_max(const float8 val1, const float8 val2)
     375             : {
     376    58957444 :     return float8_gt(val1, val2) ? val1 : val2;
     377             : }
     378             : 
     379             : #endif                          /* FLOAT_H */

Generated by: LCOV version 1.13