LCOV - code coverage report
Current view: top level - src/include/utils - float.h (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 89.6 % 96 86
Test Date: 2026-04-07 14:16:30 Functions: 100.0 % 30 30
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 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       214263 : get_float4_infinity(void)
      62              : {
      63              :     /* C99 standard way */
      64       214263 :     return (float4) INFINITY;
      65              : }
      66              : 
      67              : static inline float8
      68       999924 : get_float8_infinity(void)
      69              : {
      70              :     /* C99 standard way */
      71       999924 :     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         1526 : get_float8_nan(void)
      88              : {
      89              :     /* C99 standard way */
      90         1526 :     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      3842902 : float8_pl_safe(const float8 val1, const float8 val2, struct Node *escontext)
     117              : {
     118              :     float8      result;
     119              : 
     120      3842902 :     result = val1 + val2;
     121      3842902 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
     122            0 :         return float_overflow_error_ext(escontext);
     123              : 
     124      3842902 :     return result;
     125              : }
     126              : 
     127              : static inline float8
     128      3332482 : float8_pl(const float8 val1, const float8 val2)
     129              : {
     130      3332482 :     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    173373204 : float8_mi_safe(const float8 val1, const float8 val2, struct Node *escontext)
     147              : {
     148              :     float8      result;
     149              : 
     150    173373204 :     result = val1 - val2;
     151    173373204 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
     152            0 :         return float_overflow_error_ext(escontext);
     153              : 
     154    173373204 :     return result;
     155              : }
     156              : 
     157              : static inline float8
     158    152163654 : float8_mi(const float8 val1, const float8 val2)
     159              : {
     160    152163654 :     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     75304554 : float8_mul_safe(const float8 val1, const float8 val2, struct Node *escontext)
     179              : {
     180              :     float8      result;
     181              : 
     182     75304554 :     result = val1 * val2;
     183     75304554 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
     184           16 :         return float_overflow_error_ext(escontext);
     185     75304538 :     if (unlikely(result == 0.0) && val1 != 0.0 && val2 != 0.0)
     186            4 :         return float_underflow_error_ext(escontext);
     187              : 
     188     75304534 :     return result;
     189              : }
     190              : 
     191              : static inline float8
     192     73863078 : float8_mul(const float8 val1, const float8 val2)
     193              : {
     194     73863078 :     return float8_mul_safe(val1, val2, NULL);
     195              : }
     196              : 
     197              : static inline float4
     198      4620738 : float4_div(const float4 val1, const float4 val2)
     199              : {
     200              :     float4      result;
     201              : 
     202      4620738 :     if (unlikely(val2 == 0.0f) && !isnan(val1))
     203            4 :         float_zero_divide_error();
     204      4620734 :     result = val1 / val2;
     205      4620734 :     if (unlikely(isinf(result)) && !isinf(val1))
     206            0 :         float_overflow_error();
     207      4620734 :     if (unlikely(result == 0.0f) && val1 != 0.0f && !isinf(val2))
     208            0 :         float_underflow_error();
     209              : 
     210      4620734 :     return result;
     211              : }
     212              : 
     213              : static inline float8
     214     12914387 : float8_div_safe(const float8 val1, const float8 val2, struct Node *escontext)
     215              : {
     216              :     float8      result;
     217              : 
     218     12914387 :     if (unlikely(val2 == 0.0) && !isnan(val1))
     219           44 :         return float_zero_divide_error_ext(escontext);
     220     12914343 :     result = val1 / val2;
     221     12914343 :     if (unlikely(isinf(result)) && !isinf(val1))
     222            0 :         return float_overflow_error_ext(escontext);
     223     12914343 :     if (unlikely(result == 0.0) && val1 != 0.0 && !isinf(val2))
     224            0 :         return float_underflow_error_ext(escontext);
     225              : 
     226     12914343 :     return result;
     227              : }
     228              : 
     229              : static inline float8
     230     12888611 : float8_div(const float8 val1, const float8 val2)
     231              : {
     232     12888611 :     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        24366 : float4_eq(const float4 val1, const float4 val2)
     245              : {
     246        24366 :     return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
     247              : }
     248              : 
     249              : static inline bool
     250     11321706 : float8_eq(const float8 val1, const float8 val2)
     251              : {
     252     11321706 :     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        21788 : float8_ne(const float8 val1, const float8 val2)
     263              : {
     264        21788 :     return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
     265              : }
     266              : 
     267              : static inline bool
     268      8597305 : float4_lt(const float4 val1, const float4 val2)
     269              : {
     270      8597305 :     return !isnan(val1) && (isnan(val2) || val1 < val2);
     271              : }
     272              : 
     273              : static inline bool
     274     82651367 : float8_lt(const float8 val1, const float8 val2)
     275              : {
     276     82651367 :     return !isnan(val1) && (isnan(val2) || val1 < val2);
     277              : }
     278              : 
     279              : static inline bool
     280         2552 : float4_le(const float4 val1, const float4 val2)
     281              : {
     282         2552 :     return isnan(val2) || (!isnan(val1) && val1 <= val2);
     283              : }
     284              : 
     285              : static inline bool
     286    113202529 : float8_le(const float8 val1, const float8 val2)
     287              : {
     288    113202529 :     return isnan(val2) || (!isnan(val1) && val1 <= val2);
     289              : }
     290              : 
     291              : static inline bool
     292      8795160 : float4_gt(const float4 val1, const float4 val2)
     293              : {
     294      8795160 :     return !isnan(val2) && (isnan(val1) || val1 > val2);
     295              : }
     296              : 
     297              : static inline bool
     298     88247083 : float8_gt(const float8 val1, const float8 val2)
     299              : {
     300     88247083 :     return !isnan(val2) && (isnan(val1) || val1 > val2);
     301              : }
     302              : 
     303              : static inline bool
     304         2552 : float4_ge(const float4 val1, const float4 val2)
     305              : {
     306         2552 :     return isnan(val1) || (!isnan(val2) && val1 >= val2);
     307              : }
     308              : 
     309              : static inline bool
     310      5184916 : float8_ge(const float8 val1, const float8 val2)
     311              : {
     312      5184916 :     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     62281676 : float8_min(const float8 val1, const float8 val2)
     323              : {
     324     62281676 :     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     62281676 : float8_max(const float8 val1, const float8 val2)
     335              : {
     336     62281676 :     return float8_gt(val1, val2) ? val1 : val2;
     337              : }
     338              : 
     339              : #endif                          /* FLOAT_H */
        

Generated by: LCOV version 2.0-1