[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [tor/master] Add an util function to cast double to int64_t
commit 8acccdbeac69b066be805f711133e188a7b04f28
Author: David Goulet <dgoulet@xxxxxxxxx>
Date: Mon Feb 16 15:55:30 2015 -0500
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@xxxxxxxxx>
---
src/common/util.c | 41 +++++++++++++++++++++++++++++++++++------
src/common/util.h | 1 +
2 files changed, 36 insertions(+), 6 deletions(-)
diff --git a/src/common/util.c b/src/common/util.c
index d8da8b1..cc7760b 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;
+}
diff --git a/src/common/util.h b/src/common/util.h
index 30ac248..e303da2 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -185,6 +185,7 @@ int64_t sample_laplace_distribution(double mu, double b, double p);
int64_t add_laplace_noise(int64_t signal, double random, double delta_f,
double epsilon);
int n_bits_set_u8(uint8_t v);
+int64_t cast_double_to_int64(double number);
/* Compute the CEIL of <b>a</b> divided by <b>b</b>, for nonnegative <b>a</b>
* and positive <b>b</b>. Works on integer types only. Not defined if a+b can
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits