LCOV - code coverage report
Current view: top level - src/include/utils - float.h (source / functions) Hit Total Coverage
Test: PostgreSQL 13beta1 Lines: 78 88 88.6 %
Date: 2020-06-03 11:07:14 Functions: 26 26 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-2020, 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 void float_overflow_error(void) pg_attribute_noreturn();
      41             : extern void float_underflow_error(void) pg_attribute_noreturn();
      42             : extern void float_zero_divide_error(void) pg_attribute_noreturn();
      43             : extern int  is_infinite(float8 val);
      44             : extern float8 float8in_internal(char *num, char **endptr_p,
      45             :                                 const char *type_name, const char *orig_string);
      46             : extern float8 float8in_internal_opt_error(char *num, char **endptr_p,
      47             :                                           const char *type_name, const char *orig_string,
      48             :                                           bool *have_error);
      49             : extern char *float8out_internal(float8 num);
      50             : extern int  float4_cmp_internal(float4 a, float4 b);
      51             : extern int  float8_cmp_internal(float8 a, float8 b);
      52             : 
      53             : /*
      54             :  * Routines to provide reasonably platform-independent handling of
      55             :  * infinity and NaN
      56             :  *
      57             :  * We assume that isinf() and isnan() are available and work per spec.
      58             :  * (On some platforms, we have to supply our own; see src/port.)  However,
      59             :  * generating an Infinity or NaN in the first place is less well standardized;
      60             :  * pre-C99 systems tend not to have C99's INFINITY and NaN macros.  We
      61             :  * centralize our workarounds for this here.
      62             :  */
      63             : 
      64             : /*
      65             :  * The funny placements of the two #pragmas is necessary because of a
      66             :  * long lived bug in the Microsoft compilers.
      67             :  * See http://support.microsoft.com/kb/120968/en-us for details
      68             :  */
      69             : #ifdef _MSC_VER
      70             : #pragma warning(disable:4756)
      71             : #endif
      72             : static inline float4
      73      275114 : get_float4_infinity(void)
      74             : {
      75             : #ifdef INFINITY
      76             :     /* C99 standard way */
      77      275114 :     return (float4) INFINITY;
      78             : #else
      79             : #ifdef _MSC_VER
      80             : #pragma warning(default:4756)
      81             : #endif
      82             : 
      83             :     /*
      84             :      * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the
      85             :      * largest normal float8.  We assume forcing an overflow will get us a
      86             :      * true infinity.
      87             :      */
      88             :     return (float4) (HUGE_VAL * HUGE_VAL);
      89             : #endif
      90             : }
      91             : 
      92             : static inline float8
      93        5942 : get_float8_infinity(void)
      94             : {
      95             : #ifdef INFINITY
      96             :     /* C99 standard way */
      97        5942 :     return (float8) INFINITY;
      98             : #else
      99             : 
     100             :     /*
     101             :      * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the
     102             :      * largest normal float8.  We assume forcing an overflow will get us a
     103             :      * true infinity.
     104             :      */
     105             :     return (float8) (HUGE_VAL * HUGE_VAL);
     106             : #endif
     107             : }
     108             : 
     109             : static inline float4
     110           4 : get_float4_nan(void)
     111             : {
     112             : #ifdef NAN
     113             :     /* C99 standard way */
     114           4 :     return (float4) NAN;
     115             : #else
     116             :     /* Assume we can get a NAN via zero divide */
     117             :     return (float4) (0.0 / 0.0);
     118             : #endif
     119             : }
     120             : 
     121             : static inline float8
     122       15660 : get_float8_nan(void)
     123             : {
     124             :     /* (float8) NAN doesn't work on some NetBSD/MIPS releases */
     125             : #if defined(NAN) && !(defined(__NetBSD__) && defined(__mips__))
     126             :     /* C99 standard way */
     127       15660 :     return (float8) NAN;
     128             : #else
     129             :     /* Assume we can get a NaN via zero divide */
     130             :     return (float8) (0.0 / 0.0);
     131             : #endif
     132             : }
     133             : 
     134             : /*
     135             :  * Floating-point arithmetic with overflow/underflow reported as errors
     136             :  *
     137             :  * There isn't any way to check for underflow of addition/subtraction
     138             :  * because numbers near the underflow value have already been rounded to
     139             :  * the point where we can't detect that the two values were originally
     140             :  * different, e.g. on x86, '1e-45'::float4 == '2e-45'::float4 ==
     141             :  * 1.4013e-45.
     142             :  */
     143             : 
     144             : static inline float4
     145          36 : float4_pl(const float4 val1, const float4 val2)
     146             : {
     147             :     float4      result;
     148             : 
     149          36 :     result = val1 + val2;
     150          36 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
     151           0 :         float_overflow_error();
     152             : 
     153          36 :     return result;
     154             : }
     155             : 
     156             : static inline float8
     157     3725928 : float8_pl(const float8 val1, const float8 val2)
     158             : {
     159             :     float8      result;
     160             : 
     161     3725928 :     result = val1 + val2;
     162     3725928 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
     163           0 :         float_overflow_error();
     164             : 
     165     3725928 :     return result;
     166             : }
     167             : 
     168             : static inline float4
     169          12 : float4_mi(const float4 val1, const float4 val2)
     170             : {
     171             :     float4      result;
     172             : 
     173          12 :     result = val1 - val2;
     174          12 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
     175           0 :         float_overflow_error();
     176             : 
     177          12 :     return result;
     178             : }
     179             : 
     180             : static inline float8
     181   167088076 : float8_mi(const float8 val1, const float8 val2)
     182             : {
     183             :     float8      result;
     184             : 
     185   167088076 :     result = val1 - val2;
     186   167088076 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
     187           0 :         float_overflow_error();
     188             : 
     189   167088076 :     return result;
     190             : }
     191             : 
     192             : static inline float4
     193          24 : float4_mul(const float4 val1, const float4 val2)
     194             : {
     195             :     float4      result;
     196             : 
     197          24 :     result = val1 * val2;
     198          24 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
     199           0 :         float_overflow_error();
     200          24 :     if (unlikely(result == 0.0f) && val1 != 0.0f && val2 != 0.0f)
     201           0 :         float_underflow_error();
     202             : 
     203          24 :     return result;
     204             : }
     205             : 
     206             : static inline float8
     207    73183454 : float8_mul(const float8 val1, const float8 val2)
     208             : {
     209             :     float8      result;
     210             : 
     211    73183454 :     result = val1 * val2;
     212    73183454 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
     213          12 :         float_overflow_error();
     214    73183442 :     if (unlikely(result == 0.0) && val1 != 0.0 && val2 != 0.0)
     215           4 :         float_underflow_error();
     216             : 
     217    73183438 :     return result;
     218             : }
     219             : 
     220             : static inline float4
     221     4054948 : float4_div(const float4 val1, const float4 val2)
     222             : {
     223             :     float4      result;
     224             : 
     225     4054948 :     if (unlikely(val2 == 0.0f))
     226           4 :         float_zero_divide_error();
     227     4054944 :     result = val1 / val2;
     228     4054944 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
     229           0 :         float_overflow_error();
     230     4054944 :     if (unlikely(result == 0.0f) && val1 != 0.0f)
     231           0 :         float_underflow_error();
     232             : 
     233     4054944 :     return result;
     234             : }
     235             : 
     236             : static inline float8
     237    12632846 : float8_div(const float8 val1, const float8 val2)
     238             : {
     239             :     float8      result;
     240             : 
     241    12632846 :     if (unlikely(val2 == 0.0))
     242          40 :         float_zero_divide_error();
     243    12632806 :     result = val1 / val2;
     244    12632806 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
     245           0 :         float_overflow_error();
     246    12632806 :     if (unlikely(result == 0.0) && val1 != 0.0)
     247           0 :         float_underflow_error();
     248             : 
     249    12632806 :     return result;
     250             : }
     251             : 
     252             : /*
     253             :  * Routines for NaN-aware comparisons
     254             :  *
     255             :  * We consider all NaNs to be equal and larger than any non-NaN. This is
     256             :  * somewhat arbitrary; the important thing is to have a consistent sort
     257             :  * order.
     258             :  */
     259             : 
     260             : static inline bool
     261       80432 : float4_eq(const float4 val1, const float4 val2)
     262             : {
     263       80432 :     return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
     264             : }
     265             : 
     266             : static inline bool
     267    10942396 : float8_eq(const float8 val1, const float8 val2)
     268             : {
     269    10942396 :     return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
     270             : }
     271             : 
     272             : static inline bool
     273          20 : float4_ne(const float4 val1, const float4 val2)
     274             : {
     275          20 :     return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
     276             : }
     277             : 
     278             : static inline bool
     279       12080 : float8_ne(const float8 val1, const float8 val2)
     280             : {
     281       12080 :     return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
     282             : }
     283             : 
     284             : static inline bool
     285    31707704 : float4_lt(const float4 val1, const float4 val2)
     286             : {
     287    31707704 :     return !isnan(val1) && (isnan(val2) || val1 < val2);
     288             : }
     289             : 
     290             : static inline bool
     291    78740660 : float8_lt(const float8 val1, const float8 val2)
     292             : {
     293    78740660 :     return !isnan(val1) && (isnan(val2) || val1 < val2);
     294             : }
     295             : 
     296             : static inline bool
     297        1620 : float4_le(const float4 val1, const float4 val2)
     298             : {
     299        1620 :     return isnan(val2) || (!isnan(val1) && val1 <= val2);
     300             : }
     301             : 
     302             : static inline bool
     303   107233806 : float8_le(const float8 val1, const float8 val2)
     304             : {
     305   107233806 :     return isnan(val2) || (!isnan(val1) && val1 <= val2);
     306             : }
     307             : 
     308             : static inline bool
     309    32402220 : float4_gt(const float4 val1, const float4 val2)
     310             : {
     311    32402220 :     return !isnan(val2) && (isnan(val1) || val1 > val2);
     312             : }
     313             : 
     314             : static inline bool
     315    85089960 : float8_gt(const float8 val1, const float8 val2)
     316             : {
     317    85089960 :     return !isnan(val2) && (isnan(val1) || val1 > val2);
     318             : }
     319             : 
     320             : static inline bool
     321        1620 : float4_ge(const float4 val1, const float4 val2)
     322             : {
     323        1620 :     return isnan(val1) || (!isnan(val2) && val1 >= val2);
     324             : }
     325             : 
     326             : static inline bool
     327     4535962 : float8_ge(const float8 val1, const float8 val2)
     328             : {
     329     4535962 :     return isnan(val1) || (!isnan(val2) && val1 >= val2);
     330             : }
     331             : 
     332             : static inline float4
     333             : float4_min(const float4 val1, const float4 val2)
     334             : {
     335             :     return float4_lt(val1, val2) ? val1 : val2;
     336             : }
     337             : 
     338             : static inline float8
     339    59660836 : float8_min(const float8 val1, const float8 val2)
     340             : {
     341    59660836 :     return float8_lt(val1, val2) ? val1 : val2;
     342             : }
     343             : 
     344             : static inline float4
     345             : float4_max(const float4 val1, const float4 val2)
     346             : {
     347             :     return float4_gt(val1, val2) ? val1 : val2;
     348             : }
     349             : 
     350             : static inline float8
     351    59660836 : float8_max(const float8 val1, const float8 val2)
     352             : {
     353    59660836 :     return float8_gt(val1, val2) ? val1 : val2;
     354             : }
     355             : 
     356             : #endif                          /* FLOAT_H */

Generated by: LCOV version 1.13