LCOV - code coverage report
Current view: top level - lib/math - fp.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 15 15 100.0 %
Date: 2021-11-24 03:28:48 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /* Copyright (c) 2003, Roger Dingledine
       2             :  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
       3             :  * Copyright (c) 2007-2021, The Tor Project, Inc. */
       4             : /* See LICENSE for licensing information */
       5             : 
       6             : /**
       7             :  * \file fp.c
       8             :  *
       9             :  * \brief Basic floating-point compatibility and convenience code.
      10             :  **/
      11             : 
      12             : #include "orconfig.h"
      13             : #include "lib/math/fp.h"
      14             : 
      15             : #include <math.h>
      16             : 
      17             : /**
      18             :  * Returns the natural logarithm of d base e.  We defined this wrapper here so
      19             :  * to avoid conflicts with old versions of tor_log(), which were named log().
      20             :  */
      21             : double
      22        1143 : tor_mathlog(double d)
      23             : {
      24        1143 :   return log(d);
      25             : }
      26             : 
      27             : /** Return the long integer closest to <b>d</b>. We define this wrapper
      28             :  * here so that not all users of math.h need to use the right incantations
      29             :  * to get the c99 functions. */
      30             : long
      31        5124 : tor_lround(double d)
      32             : {
      33             : #if defined(HAVE_LROUND)
      34             :   return lround(d);
      35             : #elif defined(HAVE_RINT)
      36             :   return (long)rint(d);
      37             : #else
      38        5124 :   return (long)(d > 0 ? d + 0.5 : ceil(d - 0.5));
      39             : #endif /* defined(HAVE_LROUND) || ... */
      40             : }
      41             : 
      42             : /** Return the 64-bit integer closest to d.  We define this wrapper here so
      43             :  * that not all users of math.h need to use the right incantations to get the
      44             :  * c99 functions. */
      45             : int64_t
      46      231147 : tor_llround(double d)
      47             : {
      48             : #if defined(HAVE_LLROUND)
      49             :   return (int64_t)llround(d);
      50             : #elif defined(HAVE_RINT)
      51             :   return (int64_t)rint(d);
      52             : #else
      53      231147 :   return (int64_t)(d > 0 ? d + 0.5 : ceil(d - 0.5));
      54             : #endif /* defined(HAVE_LLROUND) || ... */
      55             : }
      56             : 
      57             : /** Cast a given double value to a int64_t. Return 0 if number is NaN.
      58             :  * Returns either INT64_MIN or INT64_MAX if number is outside of the int64_t
      59             :  * range. */
      60             : int64_t
      61          59 : clamp_double_to_int64(double number)
      62             : {
      63          59 :   int exponent;
      64             : 
      65             : #if (defined(MINGW_ANY)||defined(__FreeBSD__)) && GCC_VERSION >= 409
      66             : /*
      67             :   Mingw's math.h uses gcc's __builtin_choose_expr() facility to declare
      68             :   isnan, isfinite, and signbit.  But as implemented in at least some
      69             :   versions of gcc, __builtin_choose_expr() can generate type warnings
      70             :   even from branches that are not taken.  So, suppress those warnings.
      71             : 
      72             :   FreeBSD's math.h uses an __fp_type_select() macro, which dispatches
      73             :   based on sizeof -- again, this can generate type warnings from
      74             :   branches that are not taken.
      75             : */
      76             : #define PROBLEMATIC_FLOAT_CONVERSION_WARNING
      77             : DISABLE_GCC_WARNING("-Wfloat-conversion")
      78             : #endif /* (defined(MINGW_ANY)||defined(__FreeBSD__)) && GCC_VERSION >= 409 */
      79             : 
      80             : /*
      81             :   With clang 4.0 we apparently run into "double promotion" warnings here,
      82             :   since clang thinks we're promoting a double to a long double.
      83             :  */
      84             : #if defined(__clang__)
      85             : #if __has_warning("-Wdouble-promotion")
      86             : #define PROBLEMATIC_DOUBLE_PROMOTION_WARNING
      87             : DISABLE_GCC_WARNING("-Wdouble-promotion")
      88             : #endif
      89             : #endif /* defined(__clang__) */
      90             : 
      91             :   /* NaN is a special case that can't be used with the logic below. */
      92          59 :   if (isnan(number)) {
      93             :     return 0;
      94             :   }
      95             : 
      96             :   /* Time to validate if result can overflows a int64_t value. Fun with
      97             :    * float! Find that exponent exp such that
      98             :    *    number == x * 2^exp
      99             :    * for some x with abs(x) in [0.5, 1.0). Note that this implies that the
     100             :    * magnitude of number is strictly less than 2^exp.
     101             :    *
     102             :    * If number is infinite, the call to frexp is legal but the contents of
     103             :    * are exponent unspecified. */
     104          58 :   frexp(number, &exponent);
     105             : 
     106             :   /* If the magnitude of number is strictly less than 2^63, the truncated
     107             :    * version of number is guaranteed to be representable. The only
     108             :    * representable integer for which this is not the case is INT64_MIN, but
     109             :    * it is covered by the logic below. */
     110          58 :   if (isfinite(number) && exponent <= 63) {
     111          47 :     return (int64_t)number;
     112             :   }
     113             : 
     114             :   /* Handle infinities and finite numbers with magnitude >= 2^63. */
     115          11 :   return signbit(number) ? INT64_MIN : INT64_MAX;
     116             : 
     117             : #ifdef PROBLEMATIC_DOUBLE_PROMOTION_WARNING
     118             : ENABLE_GCC_WARNING("-Wdouble-promotion")
     119             : #endif
     120             : #ifdef PROBLEMATIC_FLOAT_CONVERSION_WARNING
     121             : ENABLE_GCC_WARNING("-Wfloat-conversion")
     122             : #endif
     123             : }
     124             : 
     125             : /* isinf() wrapper for tor */
     126             : int
     127       10891 : tor_isinf(double x)
     128             : {
     129             :   /* Same as above, work around the "double promotion" warnings */
     130             : #ifdef PROBLEMATIC_FLOAT_CONVERSION_WARNING
     131             : DISABLE_GCC_WARNING("-Wfloat-conversion")
     132             : #endif
     133             : #ifdef PROBLEMATIC_DOUBLE_PROMOTION_WARNING
     134             : DISABLE_GCC_WARNING("-Wdouble-promotion")
     135             : #endif
     136       10891 :   return isinf(x);
     137             : #ifdef PROBLEMATIC_DOUBLE_PROMOTION_WARNING
     138             : ENABLE_GCC_WARNING("-Wdouble-promotion")
     139             : #endif
     140             : #ifdef PROBLEMATIC_FLOAT_CONVERSION_WARNING
     141             : ENABLE_GCC_WARNING("-Wfloat-conversion")
     142             : #endif
     143             : }

Generated by: LCOV version 1.14