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

Generated by: LCOV version 1.16