tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

fp.c (4334B)


      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 tor_mathlog(double d)
     23 {
     24  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 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  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 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  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 clamp_double_to_int64(double number)
     62 {
     63  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  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  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  if (isfinite(number) && exponent <= 63) {
    111    return (int64_t)number;
    112  }
    113 
    114  /* Handle infinities and finite numbers with magnitude >= 2^63. */
    115  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 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  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 }