LCOV - code coverage report
Current view: top level - src/include/utils - float.h (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 89.6 % 96 86
Test Date: 2026-07-03 19:57:34 Functions: 100.0 % 30 30
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 74.3 % 152 113

             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 float8 float_overflow_error_ext(struct Node *escontext);
      37                 :             : extern float8 float_underflow_error_ext(struct Node *escontext);
      38                 :             : extern float8 float_zero_divide_error_ext(struct Node *escontext);
      39                 :             : extern int  is_infinite(float8 val);
      40                 :             : extern float8 float8in_internal(char *num, char **endptr_p,
      41                 :             :                                 const char *type_name, const char *orig_string,
      42                 :             :                                 struct Node *escontext);
      43                 :             : extern float4 float4in_internal(char *num, char **endptr_p,
      44                 :             :                                 const char *type_name, const char *orig_string,
      45                 :             :                                 struct Node *escontext);
      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                 :             :  * Postgres requires IEEE-standard float arithmetic, including infinities
      52                 :             :  * and NaNs.  We used to support pre-C99 compilers on which <math.h> might
      53                 :             :  * not supply the standard macros INFINITY and NAN.  We no longer do so,
      54                 :             :  * but these wrapper functions are still preferred over using those macros
      55                 :             :  * directly.
      56                 :             :  *
      57                 :             :  * If you change these functions, see copies in interfaces/ecpg/ecpglib/data.c.
      58                 :             :  */
      59                 :             : 
      60                 :             : static inline float4
      61                 :      214844 : get_float4_infinity(void)
      62                 :             : {
      63                 :             :     /* C99 standard way */
      64                 :      214844 :     return (float4) INFINITY;
      65                 :             : }
      66                 :             : 
      67                 :             : static inline float8
      68                 :     1000320 : get_float8_infinity(void)
      69                 :             : {
      70                 :             :     /* C99 standard way */
      71                 :     1000320 :     return (float8) INFINITY;
      72                 :             : }
      73                 :             : 
      74                 :             : /* The C standard allows implementations to omit NAN, but we don't */
      75                 :             : #ifndef NAN
      76                 :             : #error "Postgres requires support for IEEE quiet NaNs"
      77                 :             : #endif
      78                 :             : 
      79                 :             : static inline float4
      80                 :          22 : get_float4_nan(void)
      81                 :             : {
      82                 :             :     /* C99 standard way */
      83                 :          22 :     return (float4) NAN;
      84                 :             : }
      85                 :             : 
      86                 :             : static inline float8
      87                 :        1670 : get_float8_nan(void)
      88                 :             : {
      89                 :             :     /* C99 standard way */
      90                 :        1670 :     return (float8) NAN;
      91                 :             : }
      92                 :             : 
      93                 :             : /*
      94                 :             :  * Floating-point arithmetic with overflow/underflow reported as errors
      95                 :             :  *
      96                 :             :  * There isn't any way to check for underflow of addition/subtraction
      97                 :             :  * because numbers near the underflow value have already been rounded to
      98                 :             :  * the point where we can't detect that the two values were originally
      99                 :             :  * different, e.g. on x86, '1e-45'::float4 == '2e-45'::float4 ==
     100                 :             :  * 1.4013e-45.
     101                 :             :  */
     102                 :             : 
     103                 :             : static inline float4
     104                 :          36 : float4_pl(const float4 val1, const float4 val2)
     105                 :             : {
     106                 :             :     float4      result;
     107                 :             : 
     108                 :          36 :     result = val1 + val2;
     109   [ -  +  -  -  :          36 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
                   -  - ]
     110                 :           0 :         float_overflow_error();
     111                 :             : 
     112                 :          36 :     return result;
     113                 :             : }
     114                 :             : 
     115                 :             : static inline float8
     116                 :     3842932 : float8_pl_safe(const float8 val1, const float8 val2, struct Node *escontext)
     117                 :             : {
     118                 :             :     float8      result;
     119                 :             : 
     120                 :     3842932 :     result = val1 + val2;
     121   [ +  +  +  +  :     3842932 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
                   -  + ]
     122                 :           0 :         return float_overflow_error_ext(escontext);
     123                 :             : 
     124                 :     3842932 :     return result;
     125                 :             : }
     126                 :             : 
     127                 :             : static inline float8
     128                 :     3332512 : float8_pl(const float8 val1, const float8 val2)
     129                 :             : {
     130                 :     3332512 :     return float8_pl_safe(val1, val2, NULL);
     131                 :             : }
     132                 :             : 
     133                 :             : static inline float4
     134                 :          12 : float4_mi(const float4 val1, const float4 val2)
     135                 :             : {
     136                 :             :     float4      result;
     137                 :             : 
     138                 :          12 :     result = val1 - val2;
     139   [ -  +  -  -  :          12 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
                   -  - ]
     140                 :           0 :         float_overflow_error();
     141                 :             : 
     142                 :          12 :     return result;
     143                 :             : }
     144                 :             : 
     145                 :             : static inline float8
     146                 :   173446521 : float8_mi_safe(const float8 val1, const float8 val2, struct Node *escontext)
     147                 :             : {
     148                 :             :     float8      result;
     149                 :             : 
     150                 :   173446521 :     result = val1 - val2;
     151   [ +  +  +  +  :   173446521 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
                   -  + ]
     152                 :           0 :         return float_overflow_error_ext(escontext);
     153                 :             : 
     154                 :   173446521 :     return result;
     155                 :             : }
     156                 :             : 
     157                 :             : static inline float8
     158                 :   152236963 : float8_mi(const float8 val1, const float8 val2)
     159                 :             : {
     160                 :   152236963 :     return float8_mi_safe(val1, val2, NULL);
     161                 :             : }
     162                 :             : 
     163                 :             : static inline float4
     164                 :          24 : float4_mul(const float4 val1, const float4 val2)
     165                 :             : {
     166                 :             :     float4      result;
     167                 :             : 
     168                 :          24 :     result = val1 * val2;
     169   [ -  +  -  -  :          24 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
                   -  - ]
     170                 :           0 :         float_overflow_error();
     171   [ -  +  -  -  :          24 :     if (unlikely(result == 0.0f) && val1 != 0.0f && val2 != 0.0f)
                   -  - ]
     172                 :           0 :         float_underflow_error();
     173                 :             : 
     174                 :          24 :     return result;
     175                 :             : }
     176                 :             : 
     177                 :             : static inline float8
     178                 :    75378104 : float8_mul_safe(const float8 val1, const float8 val2, struct Node *escontext)
     179                 :             : {
     180                 :             :     float8      result;
     181                 :             : 
     182                 :    75378104 :     result = val1 * val2;
     183   [ +  +  +  +  :    75378104 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
                   +  + ]
     184                 :          16 :         return float_overflow_error_ext(escontext);
     185   [ +  +  +  +  :    75378088 :     if (unlikely(result == 0.0) && val1 != 0.0 && val2 != 0.0)
                   +  + ]
     186                 :           4 :         return float_underflow_error_ext(escontext);
     187                 :             : 
     188                 :    75378084 :     return result;
     189                 :             : }
     190                 :             : 
     191                 :             : static inline float8
     192                 :    73936628 : float8_mul(const float8 val1, const float8 val2)
     193                 :             : {
     194                 :    73936628 :     return float8_mul_safe(val1, val2, NULL);
     195                 :             : }
     196                 :             : 
     197                 :             : static inline float4
     198                 :     4618625 : float4_div(const float4 val1, const float4 val2)
     199                 :             : {
     200                 :             :     float4      result;
     201                 :             : 
     202   [ +  +  +  + ]:     4618625 :     if (unlikely(val2 == 0.0f) && !isnan(val1))
     203                 :           4 :         float_zero_divide_error();
     204                 :     4618621 :     result = val1 / val2;
     205   [ -  +  -  - ]:     4618621 :     if (unlikely(isinf(result)) && !isinf(val1))
     206                 :           0 :         float_overflow_error();
     207   [ +  +  +  -  :     4618621 :     if (unlikely(result == 0.0f) && val1 != 0.0f && !isinf(val2))
                   -  + ]
     208                 :           0 :         float_underflow_error();
     209                 :             : 
     210                 :     4618621 :     return result;
     211                 :             : }
     212                 :             : 
     213                 :             : static inline float8
     214                 :    12913464 : float8_div_safe(const float8 val1, const float8 val2, struct Node *escontext)
     215                 :             : {
     216                 :             :     float8      result;
     217                 :             : 
     218   [ +  +  +  + ]:    12913464 :     if (unlikely(val2 == 0.0) && !isnan(val1))
     219                 :          44 :         return float_zero_divide_error_ext(escontext);
     220                 :    12913420 :     result = val1 / val2;
     221   [ +  +  -  + ]:    12913420 :     if (unlikely(isinf(result)) && !isinf(val1))
     222                 :           0 :         return float_overflow_error_ext(escontext);
     223   [ +  +  +  +  :    12913420 :     if (unlikely(result == 0.0) && val1 != 0.0 && !isinf(val2))
                   -  + ]
     224                 :           0 :         return float_underflow_error_ext(escontext);
     225                 :             : 
     226                 :    12913420 :     return result;
     227                 :             : }
     228                 :             : 
     229                 :             : static inline float8
     230                 :    12887688 : float8_div(const float8 val1, const float8 val2)
     231                 :             : {
     232                 :    12887688 :     return float8_div_safe(val1, val2, NULL);
     233                 :             : }
     234                 :             : 
     235                 :             : /*
     236                 :             :  * Routines for NaN-aware comparisons
     237                 :             :  *
     238                 :             :  * We consider all NaNs to be equal and larger than any non-NaN. This is
     239                 :             :  * somewhat arbitrary; the important thing is to have a consistent sort
     240                 :             :  * order.
     241                 :             :  */
     242                 :             : 
     243                 :             : static inline bool
     244                 :       24922 : float4_eq(const float4 val1, const float4 val2)
     245                 :             : {
     246   [ +  +  +  -  :       24922 :     return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
                   +  + ]
     247                 :             : }
     248                 :             : 
     249                 :             : static inline bool
     250                 :    11316825 : float8_eq(const float8 val1, const float8 val2)
     251                 :             : {
     252   [ +  +  +  +  :    11316825 :     return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
                   +  + ]
     253                 :             : }
     254                 :             : 
     255                 :             : static inline bool
     256                 :          20 : float4_ne(const float4 val1, const float4 val2)
     257                 :             : {
     258   [ -  +  +  -  :          20 :     return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
                   +  + ]
     259                 :             : }
     260                 :             : 
     261                 :             : static inline bool
     262                 :       21690 : float8_ne(const float8 val1, const float8 val2)
     263                 :             : {
     264   [ -  +  +  -  :       21690 :     return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
                   +  + ]
     265                 :             : }
     266                 :             : 
     267                 :             : static inline bool
     268                 :     8910025 : float4_lt(const float4 val1, const float4 val2)
     269                 :             : {
     270   [ +  +  +  +  :     8910025 :     return !isnan(val1) && (isnan(val2) || val1 < val2);
                   +  + ]
     271                 :             : }
     272                 :             : 
     273                 :             : static inline bool
     274                 :    82682394 : float8_lt(const float8 val1, const float8 val2)
     275                 :             : {
     276   [ +  +  +  +  :    82682394 :     return !isnan(val1) && (isnan(val2) || val1 < val2);
                   +  + ]
     277                 :             : }
     278                 :             : 
     279                 :             : static inline bool
     280                 :        3112 : float4_le(const float4 val1, const float4 val2)
     281                 :             : {
     282   [ +  -  +  -  :        3112 :     return isnan(val2) || (!isnan(val1) && val1 <= val2);
                   +  + ]
     283                 :             : }
     284                 :             : 
     285                 :             : static inline bool
     286                 :   113259491 : float8_le(const float8 val1, const float8 val2)
     287                 :             : {
     288   [ +  -  +  +  :   113259491 :     return isnan(val2) || (!isnan(val1) && val1 <= val2);
                   +  + ]
     289                 :             : }
     290                 :             : 
     291                 :             : static inline bool
     292                 :     9128420 : float4_gt(const float4 val1, const float4 val2)
     293                 :             : {
     294   [ +  +  +  +  :     9128420 :     return !isnan(val2) && (isnan(val1) || val1 > val2);
                   +  + ]
     295                 :             : }
     296                 :             : 
     297                 :             : static inline bool
     298                 :    88271521 : float8_gt(const float8 val1, const float8 val2)
     299                 :             : {
     300   [ +  +  +  +  :    88271521 :     return !isnan(val2) && (isnan(val1) || val1 > val2);
                   +  + ]
     301                 :             : }
     302                 :             : 
     303                 :             : static inline bool
     304                 :        3354 : float4_ge(const float4 val1, const float4 val2)
     305                 :             : {
     306   [ +  +  +  -  :        3354 :     return isnan(val1) || (!isnan(val2) && val1 >= val2);
                   +  + ]
     307                 :             : }
     308                 :             : 
     309                 :             : static inline bool
     310                 :     5181973 : float8_ge(const float8 val1, const float8 val2)
     311                 :             : {
     312   [ +  +  +  -  :     5181973 :     return isnan(val1) || (!isnan(val2) && val1 >= val2);
                   +  + ]
     313                 :             : }
     314                 :             : 
     315                 :             : static inline float4
     316                 :             : float4_min(const float4 val1, const float4 val2)
     317                 :             : {
     318                 :             :     return float4_lt(val1, val2) ? val1 : val2;
     319                 :             : }
     320                 :             : 
     321                 :             : static inline float8
     322                 :    62311738 : float8_min(const float8 val1, const float8 val2)
     323                 :             : {
     324         [ +  + ]:    62311738 :     return float8_lt(val1, val2) ? val1 : val2;
     325                 :             : }
     326                 :             : 
     327                 :             : static inline float4
     328                 :             : float4_max(const float4 val1, const float4 val2)
     329                 :             : {
     330                 :             :     return float4_gt(val1, val2) ? val1 : val2;
     331                 :             : }
     332                 :             : 
     333                 :             : static inline float8
     334                 :    62311738 : float8_max(const float8 val1, const float8 val2)
     335                 :             : {
     336         [ +  + ]:    62311738 :     return float8_gt(val1, val2) ? val1 : val2;
     337                 :             : }
     338                 :             : 
     339                 :             : #endif                          /* FLOAT_H */
        

Generated by: LCOV version 2.0-1