diff options
author | David Goulet <dgoulet@ev0ke.net> | 2015-02-16 15:55:30 -0500 |
---|---|---|
committer | teor <teor2345@gmail.com> | 2015-05-06 18:05:16 +1000 |
commit | 8acccdbeac69b066be805f711133e188a7b04f28 (patch) | |
tree | 1d7e685781506b75946d6cdd1f4f61da2580deef /src/common/util.c | |
parent | dad5eb7e1f3c92974c7bcaaea325a05233a27494 (diff) | |
download | tor-8acccdbeac69b066be805f711133e188a7b04f28.tar.gz tor-8acccdbeac69b066be805f711133e188a7b04f28.zip |
Add an util function to cast double to int64_t
Use it in the sample_laplace_distribution function to make sure we return
the correct converted value after math operations are done on the input
values.
Thanks to Yawning for proposing a solution.
Signed-off-by: David Goulet <dgoulet@ev0ke.net>
Diffstat (limited to 'src/common/util.c')
-rw-r--r-- | src/common/util.c | 41 |
1 files changed, 35 insertions, 6 deletions
diff --git a/src/common/util.c b/src/common/util.c index d8da8b1161..cc7760bff8 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -554,12 +554,8 @@ sample_laplace_distribution(double mu, double b, double p) result = mu - b * (p > 0.5 ? 1.0 : -1.0) * tor_mathlog(1.0 - 2.0 * fabs(p - 0.5)); - if (result >= INT64_MAX) - return INT64_MAX; - else if (result <= INT64_MIN) - return INT64_MIN; - else - return tor_llround(trunc(result)); + + return cast_double_to_int64(result); } /** Add random noise between INT64_MIN and INT64_MAX coming from a Laplace @@ -5500,3 +5496,36 @@ tor_weak_random_range(tor_weak_rng_t *rng, int32_t top) return result; } +/** Cast a given double value to a int64_t. Return 0 if number is NaN. + * Returns either INT64_MIN or INT64_MAX if number is outside of the int64_t + * range. */ +int64_t cast_double_to_int64(double number) +{ + int exp; + + /* NaN is a special case that can't be used with the logic below. */ + if (isnan(number)) { + return 0; + } + + /* Time to validate if result can overflows a int64_t value. Fun with + * float! Find that exponent exp such that + * number == x * 2^exp + * for some x with abs(x) in [0.5, 1.0). Note that this implies that the + * magnitude of number is strictly less than 2^exp. + * + * If number is infinite, the call to frexp is legal but the contents of + * exp are unspecified. */ + frexp(number, &exp); + + /* If the magnitude of number is strictly less than 2^63, the truncated + * version of number is guaranteed to be representable. The only + * representable integer for which this is not the case is INT64_MIN, but + * it is covered by the logic below. */ + if (isfinite(number) && exp <= 63) { + return number; + } + + /* Handle infinities and finite numbers with magnitude >= 2^63. */ + return signbit(number) ? INT64_MIN : INT64_MAX; +} |