LCOV - code coverage report
Current view: | top level - Include/internal - pycore_pymath.h (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 4 | 15 | 26.7 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 1 | 2 | 50.0 %
|  |  | Branches: | 3 | 22 | 13.6 %

               Branch data     Line data    Source code
           1                 :            : #ifndef Py_INTERNAL_PYMATH_H
           2                 :            : #define Py_INTERNAL_PYMATH_H
           3                 :            : #ifdef __cplusplus
           4                 :            : extern "C" {
           5                 :            : #endif
           6                 :            :
           7                 :            : #ifndef Py_BUILD_CORE
           8                 :            : #  error "this header requires Py_BUILD_CORE define"
           9                 :            : #endif
          10                 :            :
          11                 :            :
          12                 :            : /* _Py_ADJUST_ERANGE1(x)
          13                 :            :  * _Py_ADJUST_ERANGE2(x, y)
          14                 :            :  * Set errno to 0 before calling a libm function, and invoke one of these
          15                 :            :  * macros after, passing the function result(s) (_Py_ADJUST_ERANGE2 is useful
          16                 :            :  * for functions returning complex results).  This makes two kinds of
          17                 :            :  * adjustments to errno:  (A) If it looks like the platform libm set
          18                 :            :  * errno=ERANGE due to underflow, clear errno. (B) If it looks like the
          19                 :            :  * platform libm overflowed but didn't set errno, force errno to ERANGE.  In
          20                 :            :  * effect, we're trying to force a useful implementation of C89 errno
          21                 :            :  * behavior.
          22                 :            :  * Caution:
          23                 :            :  *    This isn't reliable.  C99 no longer requires libm to set errno under
          24                 :            :  *        any exceptional condition, but does require +- HUGE_VAL return
          25                 :            :  *        values on overflow.  A 754 box *probably* maps HUGE_VAL to a
          26                 :            :  *        double infinity, and we're cool if that's so, unless the input
          27                 :            :  *        was an infinity and an infinity is the expected result.  A C89
          28                 :            :  *        system sets errno to ERANGE, so we check for that too.  We're
          29                 :            :  *        out of luck if a C99 754 box doesn't map HUGE_VAL to +Inf, or
          30                 :            :  *        if the returned result is a NaN, or if a C89 box returns HUGE_VAL
          31                 :            :  *        in non-overflow cases.
          32                 :            :  */
          33                 :     204349 : static inline void _Py_ADJUST_ERANGE1(double x)
          34                 :            : {
          35         [ +  - ]:     204349 :     if (errno == 0) {
          36   [ +  -  -  + ]:     204349 :         if (x == Py_HUGE_VAL || x == -Py_HUGE_VAL) {
          37                 :          0 :             errno = ERANGE;
          38                 :            :         }
          39                 :            :     }
          40   [ #  #  #  # ]:          0 :     else if (errno == ERANGE && x == 0.0) {
          41                 :          0 :         errno = 0;
          42                 :            :     }
          43                 :     204349 : }
          44                 :            :
          45                 :          0 : static inline void _Py_ADJUST_ERANGE2(double x, double y)
          46                 :            : {
          47   [ #  #  #  #  :          0 :     if (x == Py_HUGE_VAL || x == -Py_HUGE_VAL ||
                       #  # ]
          48         [ #  # ]:          0 :         y == Py_HUGE_VAL || y == -Py_HUGE_VAL)
          49                 :            :     {
          50         [ #  # ]:          0 :         if (errno == 0) {
          51                 :          0 :             errno = ERANGE;
          52                 :            :         }
          53                 :            :     }
          54         [ #  # ]:          0 :     else if (errno == ERANGE) {
          55                 :          0 :         errno = 0;
          56                 :            :     }
          57                 :          0 : }
          58                 :            :
          59                 :            :
          60                 :            : //--- HAVE_PY_SET_53BIT_PRECISION macro ------------------------------------
          61                 :            : //
          62                 :            : // The functions _Py_dg_strtod() and _Py_dg_dtoa() in Python/dtoa.c (which are
          63                 :            : // required to support the short float repr introduced in Python 3.1) require
          64                 :            : // that the floating-point unit that's being used for arithmetic operations on
          65                 :            : // C doubles is set to use 53-bit precision.  It also requires that the FPU
          66                 :            : // rounding mode is round-half-to-even, but that's less often an issue.
          67                 :            : //
          68                 :            : // If your FPU isn't already set to 53-bit precision/round-half-to-even, and
          69                 :            : // you want to make use of _Py_dg_strtod() and _Py_dg_dtoa(), then you should:
          70                 :            : //
          71                 :            : //     #define HAVE_PY_SET_53BIT_PRECISION 1
          72                 :            : //
          73                 :            : // and also give appropriate definitions for the following three macros:
          74                 :            : //
          75                 :            : // * _Py_SET_53BIT_PRECISION_HEADER: any variable declarations needed to
          76                 :            : //   use the two macros below.
          77                 :            : // * _Py_SET_53BIT_PRECISION_START: store original FPU settings, and
          78                 :            : //   set FPU to 53-bit precision/round-half-to-even
          79                 :            : // * _Py_SET_53BIT_PRECISION_END: restore original FPU settings
          80                 :            : //
          81                 :            : // The macros are designed to be used within a single C function: see
          82                 :            : // Python/pystrtod.c for an example of their use.
          83                 :            :
          84                 :            :
          85                 :            : // Get and set x87 control word for gcc/x86
          86                 :            : #ifdef HAVE_GCC_ASM_FOR_X87
          87                 :            : #define HAVE_PY_SET_53BIT_PRECISION 1
          88                 :            :
          89                 :            : // Functions defined in Python/pymath.c
          90                 :            : extern unsigned short _Py_get_387controlword(void);
          91                 :            : extern void _Py_set_387controlword(unsigned short);
          92                 :            :
          93                 :            : #define _Py_SET_53BIT_PRECISION_HEADER                                  \
          94                 :            :     unsigned short old_387controlword, new_387controlword
          95                 :            : #define _Py_SET_53BIT_PRECISION_START                                   \
          96                 :            :     do {                                                                \
          97                 :            :         old_387controlword = _Py_get_387controlword();                  \
          98                 :            :         new_387controlword = (old_387controlword & ~0x0f00) | 0x0200;   \
          99                 :            :         if (new_387controlword != old_387controlword) {                 \
         100                 :            :             _Py_set_387controlword(new_387controlword);                 \
         101                 :            :         }                                                               \
         102                 :            :     } while (0)
         103                 :            : #define _Py_SET_53BIT_PRECISION_END                                     \
         104                 :            :     do {                                                                \
         105                 :            :         if (new_387controlword != old_387controlword) {                 \
         106                 :            :             _Py_set_387controlword(old_387controlword);                 \
         107                 :            :         }                                                               \
         108                 :            :     } while (0)
         109                 :            : #endif
         110                 :            :
         111                 :            : // Get and set x87 control word for VisualStudio/x86.
         112                 :            : // x87 is not supported in 64-bit or ARM.
         113                 :            : #if defined(_MSC_VER) && !defined(_WIN64) && !defined(_M_ARM)
         114                 :            : #define HAVE_PY_SET_53BIT_PRECISION 1
         115                 :            :
         116                 :            : #include <float.h>                // __control87_2()
         117                 :            :
         118                 :            : #define _Py_SET_53BIT_PRECISION_HEADER \
         119                 :            :     unsigned int old_387controlword, new_387controlword, out_387controlword
         120                 :            :     // We use the __control87_2 function to set only the x87 control word.
         121                 :            :     // The SSE control word is unaffected.
         122                 :            : #define _Py_SET_53BIT_PRECISION_START                                   \
         123                 :            :     do {                                                                \
         124                 :            :         __control87_2(0, 0, &old_387controlword, NULL);                 \
         125                 :            :         new_387controlword =                                            \
         126                 :            :           (old_387controlword & ~(_MCW_PC | _MCW_RC)) | (_PC_53 | _RC_NEAR); \
         127                 :            :         if (new_387controlword != old_387controlword) {                 \
         128                 :            :             __control87_2(new_387controlword, _MCW_PC | _MCW_RC,        \
         129                 :            :                           &out_387controlword, NULL);                   \
         130                 :            :         }                                                               \
         131                 :            :     } while (0)
         132                 :            : #define _Py_SET_53BIT_PRECISION_END                                     \
         133                 :            :     do {                                                                \
         134                 :            :         if (new_387controlword != old_387controlword) {                 \
         135                 :            :             __control87_2(old_387controlword, _MCW_PC | _MCW_RC,        \
         136                 :            :                           &out_387controlword, NULL);                   \
         137                 :            :         }                                                               \
         138                 :            :     } while (0)
         139                 :            : #endif
         140                 :            :
         141                 :            :
         142                 :            : // MC68881
         143                 :            : #ifdef HAVE_GCC_ASM_FOR_MC68881
         144                 :            : #define HAVE_PY_SET_53BIT_PRECISION 1
         145                 :            : #define _Py_SET_53BIT_PRECISION_HEADER \
         146                 :            :     unsigned int old_fpcr, new_fpcr
         147                 :            : #define _Py_SET_53BIT_PRECISION_START                                   \
         148                 :            :     do {                                                                \
         149                 :            :         __asm__ ("fmove.l %%fpcr,%0" : "=g" (old_fpcr));                \
         150                 :            :         /* Set double precision / round to nearest.  */                 \
         151                 :            :         new_fpcr = (old_fpcr & ~0xf0) | 0x80;                           \
         152                 :            :         if (new_fpcr != old_fpcr) {                                     \
         153                 :            :               __asm__ volatile ("fmove.l %0,%%fpcr" : : "g" (new_fpcr));\
         154                 :            :         }                                                               \
         155                 :            :     } while (0)
         156                 :            : #define _Py_SET_53BIT_PRECISION_END                                     \
         157                 :            :     do {                                                                \
         158                 :            :         if (new_fpcr != old_fpcr) {                                     \
         159                 :            :             __asm__ volatile ("fmove.l %0,%%fpcr" : : "g" (old_fpcr));  \
         160                 :            :         }                                                               \
         161                 :            :     } while (0)
         162                 :            : #endif
         163                 :            :
         164                 :            : // Default definitions are empty
         165                 :            : #ifndef _Py_SET_53BIT_PRECISION_HEADER
         166                 :            : #  define _Py_SET_53BIT_PRECISION_HEADER
         167                 :            : #  define _Py_SET_53BIT_PRECISION_START
         168                 :            : #  define _Py_SET_53BIT_PRECISION_END
         169                 :            : #endif
         170                 :            :
         171                 :            :
         172                 :            : //--- _PY_SHORT_FLOAT_REPR macro -------------------------------------------
         173                 :            :
         174                 :            : // If we can't guarantee 53-bit precision, don't use the code
         175                 :            : // in Python/dtoa.c, but fall back to standard code.  This
         176                 :            : // means that repr of a float will be long (17 significant digits).
         177                 :            : //
         178                 :            : // Realistically, there are two things that could go wrong:
         179                 :            : //
         180                 :            : // (1) doubles aren't IEEE 754 doubles, or
         181                 :            : // (2) we're on x86 with the rounding precision set to 64-bits
         182                 :            : //     (extended precision), and we don't know how to change
         183                 :            : //     the rounding precision.
         184                 :            : #if !defined(DOUBLE_IS_LITTLE_ENDIAN_IEEE754) && \
         185                 :            :     !defined(DOUBLE_IS_BIG_ENDIAN_IEEE754) && \
         186                 :            :     !defined(DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754)
         187                 :            : #  define _PY_SHORT_FLOAT_REPR 0
         188                 :            : #endif
         189                 :            :
         190                 :            : // Double rounding is symptomatic of use of extended precision on x86.
         191                 :            : // If we're seeing double rounding, and we don't have any mechanism available
         192                 :            : // for changing the FPU rounding precision, then don't use Python/dtoa.c.
         193                 :            : #if defined(X87_DOUBLE_ROUNDING) && !defined(HAVE_PY_SET_53BIT_PRECISION)
         194                 :            : #  define _PY_SHORT_FLOAT_REPR 0
         195                 :            : #endif
         196                 :            :
         197                 :            : #ifndef _PY_SHORT_FLOAT_REPR
         198                 :            : #  define _PY_SHORT_FLOAT_REPR 1
         199                 :            : #endif
         200                 :            :
         201                 :            :
         202                 :            : #ifdef __cplusplus
         203                 :            : }
         204                 :            : #endif
         205                 :            : #endif /* !Py_INTERNAL_PYMATH_H */

Generated by: LCOV version 1.14