LCOV - differential code coverage report
Current view: top level - src/include/utils - float.h (source / functions) Coverage Total Hit LBC GBC GIC CBC EUB ECB
Current: Differential Code Coverage HEAD vs 15 Lines: 88.6 % 88 78 10 3 60 15 7 53
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 26 26 26 26
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * float.h
       4                 :  *    Definitions for the built-in floating-point types
       5                 :  *
       6                 :  * Portions Copyright (c) 1996-2023, 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                 : /* Visual C++ etc lacks NAN, and won't accept 0.0/0.0. */
      29                 : #if defined(WIN32) && !defined(NAN)
      30                 : static const uint32 nan[2] = {0xffffffff, 0x7fffffff};
      31                 : 
      32                 : #define NAN (*(const float8 *) nan)
      33                 : #endif
      34                 : 
      35                 : extern PGDLLIMPORT int extra_float_digits;
      36                 : 
      37                 : /*
      38                 :  * Utility functions in float.c
      39                 :  */
      40                 : extern void float_overflow_error(void) pg_attribute_noreturn();
      41                 : extern void float_underflow_error(void) pg_attribute_noreturn();
      42                 : extern void float_zero_divide_error(void) pg_attribute_noreturn();
      43                 : extern int  is_infinite(float8 val);
      44                 : extern float8 float8in_internal(char *num, char **endptr_p,
      45                 :                                 const char *type_name, const char *orig_string,
      46                 :                                 struct Node *escontext);
      47                 : extern float4 float4in_internal(char *num, char **endptr_p,
      48                 :                                 const char *type_name, const char *orig_string,
      49                 :                                 struct Node *escontext);
      50                 : extern char *float8out_internal(float8 num);
      51                 : extern int  float4_cmp_internal(float4 a, float4 b);
      52                 : extern int  float8_cmp_internal(float8 a, float8 b);
      53                 : 
      54                 : /*
      55                 :  * Routines to provide reasonably platform-independent handling of
      56                 :  * infinity and NaN
      57                 :  *
      58                 :  * We assume that isinf() and isnan() are available and work per spec.
      59                 :  * (On some platforms, we have to supply our own; see src/port.)  However,
      60                 :  * generating an Infinity or NaN in the first place is less well standardized;
      61                 :  * pre-C99 systems tend not to have C99's INFINITY and NaN macros.  We
      62                 :  * centralize our workarounds for this here.
      63                 :  */
      64                 : 
      65                 : /*
      66                 :  * The funny placements of the two #pragmas is necessary because of a
      67                 :  * long lived bug in the Microsoft compilers.
      68                 :  * See http://support.microsoft.com/kb/120968/en-us for details
      69                 :  */
      70                 : #ifdef _MSC_VER
      71                 : #pragma warning(disable:4756)
      72                 : #endif
      73                 : static inline float4
      74 GIC      207542 : get_float4_infinity(void)
      75 ECB             : {
      76                 : #ifdef INFINITY
      77                 :     /* C99 standard way */
      78 GIC      207542 :     return (float4) INFINITY;
      79 ECB             : #else
      80                 : #ifdef _MSC_VER
      81                 : #pragma warning(default:4756)
      82                 : #endif
      83                 : 
      84                 :     /*
      85                 :      * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the
      86                 :      * largest normal float8.  We assume forcing an overflow will get us a
      87                 :      * true infinity.
      88                 :      */
      89                 :     return (float4) (HUGE_VAL * HUGE_VAL);
      90                 : #endif
      91                 : }
      92                 : 
      93                 : static inline float8
      94 GIC      753921 : get_float8_infinity(void)
      95 ECB             : {
      96                 : #ifdef INFINITY
      97                 :     /* C99 standard way */
      98 GIC      753921 :     return (float8) INFINITY;
      99 ECB             : #else
     100                 : 
     101                 :     /*
     102                 :      * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the
     103                 :      * largest normal float8.  We assume forcing an overflow will get us a
     104                 :      * true infinity.
     105                 :      */
     106                 :     return (float8) (HUGE_VAL * HUGE_VAL);
     107                 : #endif
     108                 : }
     109                 : 
     110                 : static inline float4
     111 GIC          15 : get_float4_nan(void)
     112 ECB             : {
     113                 : #ifdef NAN
     114                 :     /* C99 standard way */
     115 GIC          15 :     return (float4) NAN;
     116 ECB             : #else
     117                 :     /* Assume we can get a NAN via zero divide */
     118                 :     return (float4) (0.0 / 0.0);
     119                 : #endif
     120                 : }
     121                 : 
     122                 : static inline float8
     123 GIC       10866 : get_float8_nan(void)
     124 ECB             : {
     125                 :     /* (float8) NAN doesn't work on some NetBSD/MIPS releases */
     126                 : #if defined(NAN) && !(defined(__NetBSD__) && defined(__mips__))
     127                 :     /* C99 standard way */
     128 GIC       10866 :     return (float8) NAN;
     129 ECB             : #else
     130                 :     /* Assume we can get a NaN via zero divide */
     131                 :     return (float8) (0.0 / 0.0);
     132                 : #endif
     133                 : }
     134                 : 
     135                 : /*
     136                 :  * Floating-point arithmetic with overflow/underflow reported as errors
     137                 :  *
     138                 :  * There isn't any way to check for underflow of addition/subtraction
     139                 :  * because numbers near the underflow value have already been rounded to
     140                 :  * the point where we can't detect that the two values were originally
     141                 :  * different, e.g. on x86, '1e-45'::float4 == '2e-45'::float4 ==
     142                 :  * 1.4013e-45.
     143                 :  */
     144                 : 
     145                 : static inline float4
     146 GIC          27 : float4_pl(const float4 val1, const float4 val2)
     147 ECB             : {
     148                 :     float4      result;
     149                 : 
     150 GIC          27 :     result = val1 + val2;
     151 CBC          27 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
     152 LBC           0 :         float_overflow_error();
     153 EUB             : 
     154 GIC          27 :     return result;
     155 ECB             : }
     156                 : 
     157                 : static inline float8
     158 GIC     2866988 : float8_pl(const float8 val1, const float8 val2)
     159 ECB             : {
     160                 :     float8      result;
     161                 : 
     162 GIC     2866988 :     result = val1 + val2;
     163 CBC     2866988 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
     164 LBC           0 :         float_overflow_error();
     165 EUB             : 
     166 GIC     2866988 :     return result;
     167 ECB             : }
     168                 : 
     169                 : static inline float4
     170 GIC           9 : float4_mi(const float4 val1, const float4 val2)
     171 ECB             : {
     172                 :     float4      result;
     173                 : 
     174 GIC           9 :     result = val1 - val2;
     175 CBC           9 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
     176 LBC           0 :         float_overflow_error();
     177 EUB             : 
     178 GIC           9 :     return result;
     179 ECB             : }
     180                 : 
     181                 : static inline float8
     182 GIC   130288673 : float8_mi(const float8 val1, const float8 val2)
     183 ECB             : {
     184                 :     float8      result;
     185                 : 
     186 GIC   130288673 :     result = val1 - val2;
     187 CBC   130288673 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
     188 LBC           0 :         float_overflow_error();
     189 EUB             : 
     190 GIC   130288673 :     return result;
     191 ECB             : }
     192                 : 
     193                 : static inline float4
     194 GIC          18 : float4_mul(const float4 val1, const float4 val2)
     195 ECB             : {
     196                 :     float4      result;
     197                 : 
     198 GIC          18 :     result = val1 * val2;
     199 CBC          18 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
     200 LBC           0 :         float_overflow_error();
     201 GBC          18 :     if (unlikely(result == 0.0f) && val1 != 0.0f && val2 != 0.0f)
     202 LBC           0 :         float_underflow_error();
     203 EUB             : 
     204 GIC          18 :     return result;
     205 ECB             : }
     206                 : 
     207                 : static inline float8
     208 GIC    56153160 : float8_mul(const float8 val1, const float8 val2)
     209 ECB             : {
     210                 :     float8      result;
     211                 : 
     212 GIC    56153160 :     result = val1 * val2;
     213 CBC    56153160 :     if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
     214               9 :         float_overflow_error();
     215        56153151 :     if (unlikely(result == 0.0) && val1 != 0.0 && val2 != 0.0)
     216               3 :         float_underflow_error();
     217 ECB             : 
     218 GIC    56153148 :     return result;
     219 ECB             : }
     220                 : 
     221                 : static inline float4
     222 GIC     3525265 : float4_div(const float4 val1, const float4 val2)
     223 ECB             : {
     224                 :     float4      result;
     225                 : 
     226 GIC     3525265 :     if (unlikely(val2 == 0.0f) && !isnan(val1))
     227 CBC           3 :         float_zero_divide_error();
     228         3525262 :     result = val1 / val2;
     229         3525262 :     if (unlikely(isinf(result)) && !isinf(val1))
     230 LBC           0 :         float_overflow_error();
     231 GBC     3525262 :     if (unlikely(result == 0.0f) && val1 != 0.0f && !isinf(val2))
     232 LBC           0 :         float_underflow_error();
     233 EUB             : 
     234 GIC     3525262 :     return result;
     235 ECB             : }
     236                 : 
     237                 : static inline float8
     238 GIC     9709887 : float8_div(const float8 val1, const float8 val2)
     239 ECB             : {
     240                 :     float8      result;
     241                 : 
     242 GIC     9709887 :     if (unlikely(val2 == 0.0) && !isnan(val1))
     243 CBC          33 :         float_zero_divide_error();
     244         9709854 :     result = val1 / val2;
     245         9709854 :     if (unlikely(isinf(result)) && !isinf(val1))
     246 LBC           0 :         float_overflow_error();
     247 GBC     9709854 :     if (unlikely(result == 0.0) && val1 != 0.0 && !isinf(val2))
     248 LBC           0 :         float_underflow_error();
     249 EUB             : 
     250 GIC     9709854 :     return result;
     251 ECB             : }
     252                 : 
     253                 : /*
     254                 :  * Routines for NaN-aware comparisons
     255                 :  *
     256                 :  * We consider all NaNs to be equal and larger than any non-NaN. This is
     257                 :  * somewhat arbitrary; the important thing is to have a consistent sort
     258                 :  * order.
     259                 :  */
     260                 : 
     261                 : static inline bool
     262 GIC       31166 : float4_eq(const float4 val1, const float4 val2)
     263 ECB             : {
     264 GIC       31166 :     return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
     265 ECB             : }
     266                 : 
     267                 : static inline bool
     268 GIC     8464387 : float8_eq(const float8 val1, const float8 val2)
     269 ECB             : {
     270 GIC     8464387 :     return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
     271 ECB             : }
     272                 : 
     273                 : static inline bool
     274 GIC          15 : float4_ne(const float4 val1, const float4 val2)
     275 ECB             : {
     276 GIC          15 :     return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
     277 ECB             : }
     278                 : 
     279                 : static inline bool
     280 GIC        9912 : float8_ne(const float8 val1, const float8 val2)
     281 ECB             : {
     282 GIC        9912 :     return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
     283 ECB             : }
     284                 : 
     285                 : static inline bool
     286 GIC    24738422 : float4_lt(const float4 val1, const float4 val2)
     287 ECB             : {
     288 GIC    24738422 :     return !isnan(val1) && (isnan(val2) || val1 < val2);
     289 ECB             : }
     290                 : 
     291                 : static inline bool
     292 GIC    62399573 : float8_lt(const float8 val1, const float8 val2)
     293 ECB             : {
     294 GIC    62399573 :     return !isnan(val1) && (isnan(val2) || val1 < val2);
     295 ECB             : }
     296                 : 
     297                 : static inline bool
     298 GIC        1914 : float4_le(const float4 val1, const float4 val2)
     299 ECB             : {
     300 GIC        1914 :     return isnan(val2) || (!isnan(val1) && val1 <= val2);
     301 ECB             : }
     302                 : 
     303                 : static inline bool
     304 GIC    85143552 : float8_le(const float8 val1, const float8 val2)
     305 ECB             : {
     306 GIC    85143552 :     return isnan(val2) || (!isnan(val1) && val1 <= val2);
     307 ECB             : }
     308                 : 
     309                 : static inline bool
     310 GIC    25269094 : float4_gt(const float4 val1, const float4 val2)
     311 ECB             : {
     312 GIC    25269094 :     return !isnan(val2) && (isnan(val1) || val1 > val2);
     313 ECB             : }
     314                 : 
     315                 : static inline bool
     316 GIC    66649997 : float8_gt(const float8 val1, const float8 val2)
     317 ECB             : {
     318 GIC    66649997 :     return !isnan(val2) && (isnan(val1) || val1 > val2);
     319 ECB             : }
     320                 : 
     321                 : static inline bool
     322 GIC        1914 : float4_ge(const float4 val1, const float4 val2)
     323 ECB             : {
     324 GIC        1914 :     return isnan(val1) || (!isnan(val2) && val1 >= val2);
     325 ECB             : }
     326                 : 
     327                 : static inline bool
     328 GIC     4433507 : float8_ge(const float8 val1, const float8 val2)
     329 ECB             : {
     330 GIC     4433507 :     return isnan(val1) || (!isnan(val2) && val1 >= val2);
     331 ECB             : }
     332                 : 
     333                 : static inline float4
     334                 : float4_min(const float4 val1, const float4 val2)
     335                 : {
     336                 :     return float4_lt(val1, val2) ? val1 : val2;
     337                 : }
     338                 : 
     339                 : static inline float8
     340 GIC    46795660 : float8_min(const float8 val1, const float8 val2)
     341 ECB             : {
     342 GIC    46795660 :     return float8_lt(val1, val2) ? val1 : val2;
     343 ECB             : }
     344                 : 
     345                 : static inline float4
     346                 : float4_max(const float4 val1, const float4 val2)
     347                 : {
     348                 :     return float4_gt(val1, val2) ? val1 : val2;
     349                 : }
     350                 : 
     351                 : static inline float8
     352 GIC    46795660 : float8_max(const float8 val1, const float8 val2)
     353 ECB             : {
     354 GIC    46795660 :     return float8_gt(val1, val2) ? val1 : val2;
     355 ECB             : }
     356                 : 
     357                 : #endif                          /* FLOAT_H */
        

Generated by: LCOV version v1.16-55-g56c0a2a