LCOV - code coverage report
Current view: top level - src/include/utils - float.h (source / functions) Coverage Total Hit
Test: Code coverage Lines: 90.4 % 104 94
Test Date: 2026-01-26 10:56:24 Functions: 100.0 % 26 26
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 56.0 % 232 130

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * float.h
       4                 :             :  *        Definitions for the built-in floating-point types
       5                 :             :  *
       6                 :             :  * Portions Copyright (c) 1996-2026, 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                 :             : /* X/Open (XSI) requires <math.h> to provide M_PI, but core POSIX does not */
      21                 :             : #ifndef M_PI
      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                 :             : extern PGDLLIMPORT int extra_float_digits;
      29                 :             : 
      30                 :             : /*
      31                 :             :  * Utility functions in float.c
      32                 :             :  */
      33                 :             : pg_noreturn extern void float_overflow_error(void);
      34                 :             : pg_noreturn extern void float_underflow_error(void);
      35                 :             : pg_noreturn extern void float_zero_divide_error(void);
      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                 :             :                                                                 struct Node *escontext);
      40                 :             : extern float4 float4in_internal(char *num, char **endptr_p,
      41                 :             :                                                                 const char *type_name, const char *orig_string,
      42                 :             :                                                                 struct Node *escontext);
      43                 :             : extern char *float8out_internal(float8 num);
      44                 :             : extern int      float4_cmp_internal(float4 a, float4 b);
      45                 :             : extern int      float8_cmp_internal(float8 a, float8 b);
      46                 :             : 
      47                 :             : /*
      48                 :             :  * Postgres requires IEEE-standard float arithmetic, including infinities
      49                 :             :  * and NaNs.  We used to support pre-C99 compilers on which <math.h> might
      50                 :             :  * not supply the standard macros INFINITY and NAN.  We no longer do so,
      51                 :             :  * but these wrapper functions are still preferred over using those macros
      52                 :             :  * directly.
      53                 :             :  *
      54                 :             :  * If you change these functions, see copies in interfaces/ecpg/ecpglib/data.c.
      55                 :             :  */
      56                 :             : 
      57                 :             : static inline float4
      58                 :       41783 : get_float4_infinity(void)
      59                 :             : {
      60                 :             :         /* C99 standard way */
      61                 :       41783 :         return (float4) INFINITY;
      62                 :             : }
      63                 :             : 
      64                 :             : static inline float8
      65                 :      249857 : get_float8_infinity(void)
      66                 :             : {
      67                 :             :         /* C99 standard way */
      68                 :      249857 :         return (float8) INFINITY;
      69                 :             : }
      70                 :             : 
      71                 :             : /* The C standard allows implementations to omit NAN, but we don't */
      72                 :             : #ifndef NAN
      73                 :             : #error "Postgres requires support for IEEE quiet NaNs"
      74                 :             : #endif
      75                 :             : 
      76                 :             : static inline float4
      77                 :           5 : get_float4_nan(void)
      78                 :             : {
      79                 :             :         /* C99 standard way */
      80                 :           5 :         return (float4) NAN;
      81                 :             : }
      82                 :             : 
      83                 :             : static inline float8
      84                 :         378 : get_float8_nan(void)
      85                 :             : {
      86                 :             :         /* C99 standard way */
      87                 :         378 :         return (float8) NAN;
      88                 :             : }
      89                 :             : 
      90                 :             : /*
      91                 :             :  * Floating-point arithmetic with overflow/underflow reported as errors
      92                 :             :  *
      93                 :             :  * There isn't any way to check for underflow of addition/subtraction
      94                 :             :  * because numbers near the underflow value have already been rounded to
      95                 :             :  * the point where we can't detect that the two values were originally
      96                 :             :  * different, e.g. on x86, '1e-45'::float4 == '2e-45'::float4 ==
      97                 :             :  * 1.4013e-45.
      98                 :             :  */
      99                 :             : 
     100                 :             : static inline float4
     101                 :           9 : float4_pl(const float4 val1, const float4 val2)
     102                 :             : {
     103                 :           9 :         float4          result;
     104                 :             : 
     105                 :           9 :         result = val1 + val2;
     106   [ -  +  #  #  :           9 :         if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
                   #  # ]
     107                 :           0 :                 float_overflow_error();
     108                 :             : 
     109                 :          18 :         return result;
     110                 :           9 : }
     111                 :             : 
     112                 :             : static inline float8
     113                 :      896173 : float8_pl(const float8 val1, const float8 val2)
     114                 :             : {
     115                 :      896173 :         float8          result;
     116                 :             : 
     117                 :      896173 :         result = val1 + val2;
     118   [ +  +  +  +  :      896173 :         if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
                   +  - ]
     119                 :           0 :                 float_overflow_error();
     120                 :             : 
     121                 :     1792346 :         return result;
     122                 :      896173 : }
     123                 :             : 
     124                 :             : static inline float4
     125                 :           3 : float4_mi(const float4 val1, const float4 val2)
     126                 :             : {
     127                 :           3 :         float4          result;
     128                 :             : 
     129                 :           3 :         result = val1 - val2;
     130   [ -  +  #  #  :           3 :         if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
                   #  # ]
     131                 :           0 :                 float_overflow_error();
     132                 :             : 
     133                 :           6 :         return result;
     134                 :           3 : }
     135                 :             : 
     136                 :             : static inline float8
     137                 :     8800666 : float8_mi(const float8 val1, const float8 val2)
     138                 :             : {
     139                 :     8800666 :         float8          result;
     140                 :             : 
     141                 :     8800666 :         result = val1 - val2;
     142   [ +  +  +  +  :     8800666 :         if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
                   +  - ]
     143                 :           0 :                 float_overflow_error();
     144                 :             : 
     145                 :    17601332 :         return result;
     146                 :     8800666 : }
     147                 :             : 
     148                 :             : static inline float4
     149                 :           6 : float4_mul(const float4 val1, const float4 val2)
     150                 :             : {
     151                 :           6 :         float4          result;
     152                 :             : 
     153                 :           6 :         result = val1 * val2;
     154   [ -  +  #  #  :           6 :         if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
                   #  # ]
     155                 :           0 :                 float_overflow_error();
     156   [ -  +  #  #  :           6 :         if (unlikely(result == 0.0f) && val1 != 0.0f && val2 != 0.0f)
                   #  # ]
     157                 :           0 :                 float_underflow_error();
     158                 :             : 
     159                 :          12 :         return result;
     160                 :           6 : }
     161                 :             : 
     162                 :             : static inline float8
     163                 :     5168635 : float8_mul(const float8 val1, const float8 val2)
     164                 :             : {
     165                 :     5168635 :         float8          result;
     166                 :             : 
     167                 :     5168635 :         result = val1 * val2;
     168   [ +  +  +  +  :     5168635 :         if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
                   +  + ]
     169                 :           4 :                 float_overflow_error();
     170   [ +  +  +  +  :     5168631 :         if (unlikely(result == 0.0) && val1 != 0.0 && val2 != 0.0)
                   +  + ]
     171                 :           1 :                 float_underflow_error();
     172                 :             : 
     173                 :    10337260 :         return result;
     174                 :     5168630 : }
     175                 :             : 
     176                 :             : static inline float4
     177                 :           8 : float4_div(const float4 val1, const float4 val2)
     178                 :             : {
     179                 :           8 :         float4          result;
     180                 :             : 
     181   [ +  +  +  -  :           8 :         if (unlikely(val2 == 0.0f) && !isnan(val1))
             +  +  #  # ]
     182                 :           1 :                 float_zero_divide_error();
     183                 :           7 :         result = val1 / val2;
     184   [ -  +  #  # ]:           7 :         if (unlikely(isinf(result)) && !isinf(val1))
     185                 :           0 :                 float_overflow_error();
     186   [ +  +  +  -  :           7 :         if (unlikely(result == 0.0f) && val1 != 0.0f && !isinf(val2))
                   +  - ]
     187                 :           0 :                 float_underflow_error();
     188                 :             : 
     189                 :          14 :         return result;
     190                 :           7 : }
     191                 :             : 
     192                 :             : static inline float8
     193                 :     2762332 : float8_div(const float8 val1, const float8 val2)
     194                 :             : {
     195                 :     2762332 :         float8          result;
     196                 :             : 
     197   [ +  +  -  +  :     2762332 :         if (unlikely(val2 == 0.0) && !isnan(val1))
             +  +  +  - ]
     198                 :          11 :                 float_zero_divide_error();
     199                 :     2762343 :         result = val1 / val2;
     200   [ +  +  +  - ]:     2762343 :         if (unlikely(isinf(result)) && !isinf(val1))
     201                 :           0 :                 float_overflow_error();
     202   [ +  +  +  +  :     2762343 :         if (unlikely(result == 0.0) && val1 != 0.0 && !isinf(val2))
                   +  - ]
     203                 :           0 :                 float_underflow_error();
     204                 :             : 
     205                 :     5524686 :         return result;
     206                 :     2762343 : }
     207                 :             : 
     208                 :             : /*
     209                 :             :  * Routines for NaN-aware comparisons
     210                 :             :  *
     211                 :             :  * We consider all NaNs to be equal and larger than any non-NaN. This is
     212                 :             :  * somewhat arbitrary; the important thing is to have a consistent sort
     213                 :             :  * order.
     214                 :             :  */
     215                 :             : 
     216                 :             : static inline bool
     217                 :        3722 : float4_eq(const float4 val1, const float4 val2)
     218                 :             : {
     219   [ +  -  +  +  :        3722 :         return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
          #  #  +  -  -  
                +  #  # ]
     220                 :             : }
     221                 :             : 
     222                 :             : static inline bool
     223                 :       98673 : float8_eq(const float8 val1, const float8 val2)
     224                 :             : {
     225   [ -  +  +  +  :       98673 :         return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
          +  -  -  +  +  
                +  +  - ]
     226                 :             : }
     227                 :             : 
     228                 :             : static inline bool
     229                 :           5 : float4_ne(const float4 val1, const float4 val2)
     230                 :             : {
     231   [ +  -  -  +  :           5 :         return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
          #  #  +  -  -  
                +  #  # ]
     232                 :             : }
     233                 :             : 
     234                 :             : static inline bool
     235                 :        3437 : float8_ne(const float8 val1, const float8 val2)
     236                 :             : {
     237   [ -  +  +  +  :        3437 :         return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
          +  -  -  +  +  
                +  +  - ]
     238                 :             : }
     239                 :             : 
     240                 :             : static inline bool
     241                 :       86150 : float4_lt(const float4 val1, const float4 val2)
     242                 :             : {
     243   [ +  -  +  +  :      172298 :         return !isnan(val1) && (isnan(val2) || val1 < val2);
          #  #  +  -  +  
                +  #  # ]
     244                 :             : }
     245                 :             : 
     246                 :             : static inline bool
     247                 :     4895247 : float8_lt(const float8 val1, const float8 val2)
     248                 :             : {
     249   [ -  +  +  +  :    19578977 :         return !isnan(val1) && (isnan(val2) || val1 < val2);
          +  -  -  +  +  
                +  +  - ]
     250                 :             : }
     251                 :             : 
     252                 :             : static inline bool
     253                 :         638 : float4_le(const float4 val1, const float4 val2)
     254                 :             : {
     255   [ +  -  -  +  :         638 :         return isnan(val2) || (!isnan(val1) && val1 <= val2);
          #  #  +  -  -  
                +  #  # ]
     256                 :             : }
     257                 :             : 
     258                 :             : static inline bool
     259                 :        5680 : float8_le(const float8 val1, const float8 val2)
     260                 :             : {
     261   [ -  +  +  +  :        5680 :         return isnan(val2) || (!isnan(val1) && val1 <= val2);
          +  -  -  +  +  
                +  +  - ]
     262                 :             : }
     263                 :             : 
     264                 :             : static inline bool
     265                 :       76539 : float4_gt(const float4 val1, const float4 val2)
     266                 :             : {
     267   [ +  -  +  +  :      153072 :         return !isnan(val2) && (isnan(val1) || val1 > val2);
          #  #  +  -  -  
                +  #  # ]
     268                 :             : }
     269                 :             : 
     270                 :             : static inline bool
     271                 :     6209447 : float8_gt(const float8 val1, const float8 val2)
     272                 :             : {
     273   [ -  +  +  +  :    24836443 :         return !isnan(val2) && (isnan(val1) || val1 > val2);
          +  -  -  +  +  
                +  +  - ]
     274                 :             : }
     275                 :             : 
     276                 :             : static inline bool
     277                 :         638 : float4_ge(const float4 val1, const float4 val2)
     278                 :             : {
     279   [ +  -  -  +  :         638 :         return isnan(val1) || (!isnan(val2) && val1 >= val2);
          #  #  +  -  -  
                +  #  # ]
     280                 :             : }
     281                 :             : 
     282                 :             : static inline bool
     283                 :        4530 : float8_ge(const float8 val1, const float8 val2)
     284                 :             : {
     285   [ -  +  +  +  :        4530 :         return isnan(val1) || (!isnan(val2) && val1 >= val2);
          +  -  -  +  +  
                +  +  - ]
     286                 :             : }
     287                 :             : 
     288                 :             : static inline float4
     289                 :             : float4_min(const float4 val1, const float4 val2)
     290                 :             : {
     291                 :             :         return float4_lt(val1, val2) ? val1 : val2;
     292                 :             : }
     293                 :             : 
     294                 :             : static inline float8
     295                 :     2147588 : float8_min(const float8 val1, const float8 val2)
     296                 :             : {
     297         [ +  + ]:     2147588 :         return float8_lt(val1, val2) ? val1 : val2;
     298                 :             : }
     299                 :             : 
     300                 :             : static inline float4
     301                 :             : float4_max(const float4 val1, const float4 val2)
     302                 :             : {
     303                 :             :         return float4_gt(val1, val2) ? val1 : val2;
     304                 :             : }
     305                 :             : 
     306                 :             : static inline float8
     307                 :     2147588 : float8_max(const float8 val1, const float8 val2)
     308                 :             : {
     309         [ +  + ]:     2147588 :         return float8_gt(val1, val2) ? val1 : val2;
     310                 :             : }
     311                 :             : 
     312                 :             : #endif                                                  /* FLOAT_H */
        

Generated by: LCOV version 2.3.2-1