LCOV - code coverage report
Current view: top level - src/include/utils - float.h (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 88.6 % 88 78
Test Date: 2026-03-03 13:15:30 Functions: 100.0 % 26 26
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-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       178252 : get_float4_infinity(void)
      59              : {
      60              :     /* C99 standard way */
      61       178252 :     return (float4) INFINITY;
      62              : }
      63              : 
      64              : static inline float8
      65       750400 : get_float8_infinity(void)
      66              : {
      67              :     /* C99 standard way */
      68       750400 :     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           15 : get_float4_nan(void)
      78              : {
      79              :     /* C99 standard way */
      80           15 :     return (float4) NAN;
      81              : }
      82              : 
      83              : static inline float8
      84         1134 : get_float8_nan(void)
      85              : {
      86              :     /* C99 standard way */
      87         1134 :     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           27 : float4_pl(const float4 val1, const float4 val2)
     102              : {
     103              :     float4      result;
     104              : 
     105           27 :     result = val1 + val2;
     106           27 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
     107            0 :         float_overflow_error();
     108              : 
     109           27 :     return result;
     110              : }
     111              : 
     112              : static inline float8
     113      2892711 : float8_pl(const float8 val1, const float8 val2)
     114              : {
     115              :     float8      result;
     116              : 
     117      2892711 :     result = val1 + val2;
     118      2892711 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
     119            0 :         float_overflow_error();
     120              : 
     121      2892711 :     return result;
     122              : }
     123              : 
     124              : static inline float4
     125            9 : float4_mi(const float4 val1, const float4 val2)
     126              : {
     127              :     float4      result;
     128              : 
     129            9 :     result = val1 - val2;
     130            9 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
     131            0 :         float_overflow_error();
     132              : 
     133            9 :     return result;
     134              : }
     135              : 
     136              : static inline float8
     137    130290641 : float8_mi(const float8 val1, const float8 val2)
     138              : {
     139              :     float8      result;
     140              : 
     141    130290641 :     result = val1 - val2;
     142    130290641 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
     143            0 :         float_overflow_error();
     144              : 
     145    130290641 :     return result;
     146              : }
     147              : 
     148              : static inline float4
     149           18 : float4_mul(const float4 val1, const float4 val2)
     150              : {
     151              :     float4      result;
     152              : 
     153           18 :     result = val1 * val2;
     154           18 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
     155            0 :         float_overflow_error();
     156           18 :     if (unlikely(result == 0.0f) && val1 != 0.0f && val2 != 0.0f)
     157            0 :         float_underflow_error();
     158              : 
     159           18 :     return result;
     160              : }
     161              : 
     162              : static inline float8
     163     56783857 : float8_mul(const float8 val1, const float8 val2)
     164              : {
     165              :     float8      result;
     166              : 
     167     56783857 :     result = val1 * val2;
     168     56783857 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
     169           12 :         float_overflow_error();
     170     56783845 :     if (unlikely(result == 0.0) && val1 != 0.0 && val2 != 0.0)
     171            3 :         float_underflow_error();
     172              : 
     173     56783842 :     return result;
     174              : }
     175              : 
     176              : static inline float4
     177      3535353 : float4_div(const float4 val1, const float4 val2)
     178              : {
     179              :     float4      result;
     180              : 
     181      3535353 :     if (unlikely(val2 == 0.0f) && !isnan(val1))
     182            3 :         float_zero_divide_error();
     183      3535350 :     result = val1 / val2;
     184      3535350 :     if (unlikely(isinf(result)) && !isinf(val1))
     185            0 :         float_overflow_error();
     186      3535350 :     if (unlikely(result == 0.0f) && val1 != 0.0f && !isinf(val2))
     187            0 :         float_underflow_error();
     188              : 
     189      3535350 :     return result;
     190              : }
     191              : 
     192              : static inline float8
     193      9714169 : float8_div(const float8 val1, const float8 val2)
     194              : {
     195              :     float8      result;
     196              : 
     197      9714169 :     if (unlikely(val2 == 0.0) && !isnan(val1))
     198           33 :         float_zero_divide_error();
     199      9714136 :     result = val1 / val2;
     200      9714136 :     if (unlikely(isinf(result)) && !isinf(val1))
     201            0 :         float_overflow_error();
     202      9714136 :     if (unlikely(result == 0.0) && val1 != 0.0 && !isinf(val2))
     203            0 :         float_underflow_error();
     204              : 
     205      9714136 :     return result;
     206              : }
     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        22431 : float4_eq(const float4 val1, const float4 val2)
     218              : {
     219        22431 :     return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
     220              : }
     221              : 
     222              : static inline bool
     223      8658075 : float8_eq(const float8 val1, const float8 val2)
     224              : {
     225      8658075 :     return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
     226              : }
     227              : 
     228              : static inline bool
     229           15 : float4_ne(const float4 val1, const float4 val2)
     230              : {
     231           15 :     return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
     232              : }
     233              : 
     234              : static inline bool
     235        18318 : float8_ne(const float8 val1, const float8 val2)
     236              : {
     237        18318 :     return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
     238              : }
     239              : 
     240              : static inline bool
     241      7540575 : float4_lt(const float4 val1, const float4 val2)
     242              : {
     243      7540575 :     return !isnan(val1) && (isnan(val2) || val1 < val2);
     244              : }
     245              : 
     246              : static inline bool
     247     62463512 : float8_lt(const float8 val1, const float8 val2)
     248              : {
     249     62463512 :     return !isnan(val1) && (isnan(val2) || val1 < val2);
     250              : }
     251              : 
     252              : static inline bool
     253         1914 : float4_le(const float4 val1, const float4 val2)
     254              : {
     255         1914 :     return isnan(val2) || (!isnan(val1) && val1 <= val2);
     256              : }
     257              : 
     258              : static inline bool
     259     85152625 : float8_le(const float8 val1, const float8 val2)
     260              : {
     261     85152625 :     return isnan(val2) || (!isnan(val1) && val1 <= val2);
     262              : }
     263              : 
     264              : static inline bool
     265      7714481 : float4_gt(const float4 val1, const float4 val2)
     266              : {
     267      7714481 :     return !isnan(val2) && (isnan(val1) || val1 > val2);
     268              : }
     269              : 
     270              : static inline bool
     271     66863712 : float8_gt(const float8 val1, const float8 val2)
     272              : {
     273     66863712 :     return !isnan(val2) && (isnan(val1) || val1 > val2);
     274              : }
     275              : 
     276              : static inline bool
     277         1914 : float4_ge(const float4 val1, const float4 val2)
     278              : {
     279         1914 :     return isnan(val1) || (!isnan(val2) && val1 >= val2);
     280              : }
     281              : 
     282              : static inline bool
     283      3967217 : float8_ge(const float8 val1, const float8 val2)
     284              : {
     285      3967217 :     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     46793150 : float8_min(const float8 val1, const float8 val2)
     296              : {
     297     46793150 :     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     46793150 : float8_max(const float8 val1, const float8 val2)
     308              : {
     309     46793150 :     return float8_gt(val1, val2) ? val1 : val2;
     310              : }
     311              : 
     312              : #endif                          /* FLOAT_H */
        

Generated by: LCOV version 2.0-1