]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
Move floating-point math functions into a new lib/math
authorNick Mathewson <nickm@torproject.org>
Thu, 28 Jun 2018 16:24:45 +0000 (12:24 -0400)
committerNick Mathewson <nickm@torproject.org>
Thu, 28 Jun 2018 16:24:45 +0000 (12:24 -0400)
19 files changed:
.gitignore
Makefile.am
src/common/util.c
src/common/util.h
src/include.am
src/lib/math/.may_include [new file with mode: 0644]
src/lib/math/fp.c [new file with mode: 0644]
src/lib/math/fp.h [new file with mode: 0644]
src/lib/math/include.am [new file with mode: 0644]
src/lib/math/laplace.c [new file with mode: 0644]
src/lib/math/laplace.h [new file with mode: 0644]
src/or/circpathbias.c
src/or/circuitstats.c
src/or/circuituse.c
src/or/entrynodes.c
src/or/rephist.c
src/or/routerlist.c
src/or/scheduler_kist.c
src/test/test_util.c

index 8f2d66b0dc7685fa6078ebf6c8712281aaaa4f13..c940166aa8864f744dc0891712ecd7e27ac09612 100644 (file)
@@ -187,6 +187,8 @@ uptime-*.json
 /src/lib/libtor-log-testing.a
 /src/lib/libtor-malloc.a
 /src/lib/libtor-malloc-testing.a
+/src/lib/libtor-math.a
+/src/lib/libtor-math-testing.a
 /src/lib/libtor-memarea.a
 /src/lib/libtor-memarea-testing.a
 /src/lib/libtor-net.a
index f28eae3bb0af733bb32ecf8f0f728976e14187ef..5a7271e30fc3add7fe758b1227e03aaedb9e7e82 100644 (file)
@@ -48,6 +48,7 @@ TOR_UTIL_LIBS = \
        src/lib/libtor-net.a \
         src/lib/libtor-thread.a \
         src/lib/libtor-memarea.a \
+       src/lib/libtor-math.a \
         src/lib/libtor-log.a \
         src/lib/libtor-lock.a \
         src/lib/libtor-fdio.a \
@@ -71,6 +72,7 @@ TOR_UTIL_TESTING_LIBS = \
        src/lib/libtor-net-testing.a \
         src/lib/libtor-thread-testing.a \
         src/lib/libtor-memarea-testing.a \
+       src/lib/libtor-math-testing.a \
         src/lib/libtor-log-testing.a \
         src/lib/libtor-lock-testing.a \
         src/lib/libtor-fdio-testing.a \
index 6a557c956038a8a5dc5b6f0caef4a687faa3e110..e1fae0deab8b3f7b59fe082483d5be95fce5258c 100644 (file)
@@ -127,100 +127,6 @@ ENABLE_GCC_WARNING(aggregate-return)
  * Math
  * ===== */
 
-/**
- * Returns the natural logarithm of d base e.  We defined this wrapper here so
- * to avoid conflicts with old versions of tor_log(), which were named log().
- */
-double
-tor_mathlog(double d)
-{
-  return log(d);
-}
-
-/** Return the long integer closest to <b>d</b>. We define this wrapper
- * here so that not all users of math.h need to use the right incantations
- * to get the c99 functions. */
-long
-tor_lround(double d)
-{
-#if defined(HAVE_LROUND)
-  return lround(d);
-#elif defined(HAVE_RINT)
-  return (long)rint(d);
-#else
-  return (long)(d > 0 ? d + 0.5 : ceil(d - 0.5));
-#endif /* defined(HAVE_LROUND) || ... */
-}
-
-/** Return the 64-bit integer closest to d.  We define this wrapper here so
- * that not all users of math.h need to use the right incantations to get the
- * c99 functions. */
-int64_t
-tor_llround(double d)
-{
-#if defined(HAVE_LLROUND)
-  return (int64_t)llround(d);
-#elif defined(HAVE_RINT)
-  return (int64_t)rint(d);
-#else
-  return (int64_t)(d > 0 ? d + 0.5 : ceil(d - 0.5));
-#endif /* defined(HAVE_LLROUND) || ... */
-}
-
-/** Transform a random value <b>p</b> from the uniform distribution in
- * [0.0, 1.0[ into a Laplace distributed value with location parameter
- * <b>mu</b> and scale parameter <b>b</b>. Truncate the final result
- * to be an integer in [INT64_MIN, INT64_MAX]. */
-int64_t
-sample_laplace_distribution(double mu, double b, double p)
-{
-  double result;
-  tor_assert(p >= 0.0 && p < 1.0);
-
-  /* This is the "inverse cumulative distribution function" from:
-   * http://en.wikipedia.org/wiki/Laplace_distribution */
-  if (p <= 0.0) {
-    /* Avoid taking log(0.0) == -INFINITY, as some processors or compiler
-     * options can cause the program to trap. */
-    return INT64_MIN;
-  }
-
-  result = mu - b * (p > 0.5 ? 1.0 : -1.0)
-                  * tor_mathlog(1.0 - 2.0 * fabs(p - 0.5));
-
-  return clamp_double_to_int64(result);
-}
-
-/** Add random noise between INT64_MIN and INT64_MAX coming from a Laplace
- * distribution with mu = 0 and b = <b>delta_f</b>/<b>epsilon</b> to
- * <b>signal</b> based on the provided <b>random</b> value in [0.0, 1.0[.
- * The epsilon value must be between ]0.0, 1.0]. delta_f must be greater
- * than 0. */
-int64_t
-add_laplace_noise(int64_t signal_, double random_, double delta_f,
-                  double epsilon)
-{
-  int64_t noise;
-
-  /* epsilon MUST be between ]0.0, 1.0] */
-  tor_assert(epsilon > 0.0 && epsilon <= 1.0);
-  /* delta_f MUST be greater than 0. */
-  tor_assert(delta_f > 0.0);
-
-  /* Just add noise, no further signal */
-  noise = sample_laplace_distribution(0.0,
-                                      delta_f / epsilon,
-                                      random_);
-
-  /* Clip (signal + noise) to [INT64_MIN, INT64_MAX] */
-  if (noise > 0 && INT64_MAX - noise < signal_)
-    return INT64_MAX;
-  else if (noise < 0 && INT64_MIN - noise > signal_)
-    return INT64_MIN;
-  else
-    return signal_ + noise;
-}
-
 /* =====
  * String manipulation
  * ===== */
@@ -389,67 +295,3 @@ load_windows_system_library(const TCHAR *library_name)
   return LoadLibrary(path);
 }
 #endif /* defined(_WIN32) */
-
-/** 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
-clamp_double_to_int64(double number)
-{
-  int exponent;
-
-#if defined(MINGW_ANY) && GCC_VERSION >= 409
-/*
-  Mingw's math.h uses gcc's __builtin_choose_expr() facility to declare
-  isnan, isfinite, and signbit.  But as implemented in at least some
-  versions of gcc, __builtin_choose_expr() can generate type warnings
-  even from branches that are not taken.  So, suppress those warnings.
-*/
-#define PROBLEMATIC_FLOAT_CONVERSION_WARNING
-DISABLE_GCC_WARNING(float-conversion)
-#endif /* defined(MINGW_ANY) && GCC_VERSION >= 409 */
-
-/*
-  With clang 4.0 we apparently run into "double promotion" warnings here,
-  since clang thinks we're promoting a double to a long double.
- */
-#if defined(__clang__)
-#if __has_warning("-Wdouble-promotion")
-#define PROBLEMATIC_DOUBLE_PROMOTION_WARNING
-DISABLE_GCC_WARNING(double-promotion)
-#endif
-#endif /* defined(__clang__) */
-
-  /* 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
-   * are exponent unspecified. */
-  frexp(number, &exponent);
-
-  /* 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) && exponent <= 63) {
-    return (int64_t)number;
-  }
-
-  /* Handle infinities and finite numbers with magnitude >= 2^63. */
-  return signbit(number) ? INT64_MIN : INT64_MAX;
-
-#ifdef PROBLEMATIC_DOUBLE_PROMOTION_WARNING
-ENABLE_GCC_WARNING(double-promotion)
-#endif
-#ifdef PROBLEMATIC_FLOAT_CONVERSION_WARNING
-ENABLE_GCC_WARNING(float-conversion)
-#endif
-}
index 0f991f8c46d6fe16357b070ceadc2fd8dbb8dc2e..3068f023a49531e8a74fc2f1e7dec8f3943ef86e 100644 (file)
@@ -62,13 +62,6 @@ void tor_log_mallinfo(int severity);
 #define bool_neq(a,b) (!(a)!=!(b))
 
 /* Math functions */
-double tor_mathlog(double d) ATTR_CONST;
-long tor_lround(double d) ATTR_CONST;
-int64_t tor_llround(double d) ATTR_CONST;
-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);
-int64_t clamp_double_to_int64(double number);
 
 /* String manipulation */
 
index 621c906d9f239a8d86a4ae9082bb82a4eb0b8162..8345813b71f1f858d4869a0b38e376690df79f0e 100644 (file)
@@ -14,6 +14,7 @@ include src/lib/include.libdonna.am
 include src/lib/intmath/include.am
 include src/lib/lock/include.am
 include src/lib/log/include.am
+include src/lib/math/include.am
 include src/lib/memarea/include.am
 include src/lib/malloc/include.am
 include src/lib/net/include.am
diff --git a/src/lib/math/.may_include b/src/lib/math/.may_include
new file mode 100644 (file)
index 0000000..1fd2686
--- /dev/null
@@ -0,0 +1,5 @@
+orconfig.h
+
+lib/cc/*.h
+lib/log/*.h
+lib/math/*.h
diff --git a/src/lib/math/fp.c b/src/lib/math/fp.c
new file mode 100644 (file)
index 0000000..d1c4428
--- /dev/null
@@ -0,0 +1,113 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "lib/math/fp.h"
+
+#include <math.h>
+
+/**
+ * Returns the natural logarithm of d base e.  We defined this wrapper here so
+ * to avoid conflicts with old versions of tor_log(), which were named log().
+ */
+double
+tor_mathlog(double d)
+{
+  return log(d);
+}
+
+/** Return the long integer closest to <b>d</b>. We define this wrapper
+ * here so that not all users of math.h need to use the right incantations
+ * to get the c99 functions. */
+long
+tor_lround(double d)
+{
+#if defined(HAVE_LROUND)
+  return lround(d);
+#elif defined(HAVE_RINT)
+  return (long)rint(d);
+#else
+  return (long)(d > 0 ? d + 0.5 : ceil(d - 0.5));
+#endif /* defined(HAVE_LROUND) || ... */
+}
+
+/** Return the 64-bit integer closest to d.  We define this wrapper here so
+ * that not all users of math.h need to use the right incantations to get the
+ * c99 functions. */
+int64_t
+tor_llround(double d)
+{
+#if defined(HAVE_LLROUND)
+  return (int64_t)llround(d);
+#elif defined(HAVE_RINT)
+  return (int64_t)rint(d);
+#else
+  return (int64_t)(d > 0 ? d + 0.5 : ceil(d - 0.5));
+#endif /* defined(HAVE_LLROUND) || ... */
+}
+
+/** 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
+clamp_double_to_int64(double number)
+{
+  int exponent;
+
+#if defined(MINGW_ANY) && GCC_VERSION >= 409
+/*
+  Mingw's math.h uses gcc's __builtin_choose_expr() facility to declare
+  isnan, isfinite, and signbit.  But as implemented in at least some
+  versions of gcc, __builtin_choose_expr() can generate type warnings
+  even from branches that are not taken.  So, suppress those warnings.
+*/
+#define PROBLEMATIC_FLOAT_CONVERSION_WARNING
+DISABLE_GCC_WARNING(float-conversion)
+#endif /* defined(MINGW_ANY) && GCC_VERSION >= 409 */
+
+/*
+  With clang 4.0 we apparently run into "double promotion" warnings here,
+  since clang thinks we're promoting a double to a long double.
+ */
+#if defined(__clang__)
+#if __has_warning("-Wdouble-promotion")
+#define PROBLEMATIC_DOUBLE_PROMOTION_WARNING
+DISABLE_GCC_WARNING(double-promotion)
+#endif
+#endif /* defined(__clang__) */
+
+  /* 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
+   * are exponent unspecified. */
+  frexp(number, &exponent);
+
+  /* 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) && exponent <= 63) {
+    return (int64_t)number;
+  }
+
+  /* Handle infinities and finite numbers with magnitude >= 2^63. */
+  return signbit(number) ? INT64_MIN : INT64_MAX;
+
+#ifdef PROBLEMATIC_DOUBLE_PROMOTION_WARNING
+ENABLE_GCC_WARNING(double-promotion)
+#endif
+#ifdef PROBLEMATIC_FLOAT_CONVERSION_WARNING
+ENABLE_GCC_WARNING(float-conversion)
+#endif
+}
diff --git a/src/lib/math/fp.h b/src/lib/math/fp.h
new file mode 100644 (file)
index 0000000..b35c18a
--- /dev/null
@@ -0,0 +1,17 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_FP_H
+#define TOR_FP_H
+
+#include "lib/cc/compat_compiler.h"
+#include "lib/cc/torint.h"
+
+double tor_mathlog(double d) ATTR_CONST;
+long tor_lround(double d) ATTR_CONST;
+int64_t tor_llround(double d) ATTR_CONST;
+int64_t clamp_double_to_int64(double number);
+
+#endif
diff --git a/src/lib/math/include.am b/src/lib/math/include.am
new file mode 100644 (file)
index 0000000..b088b3f
--- /dev/null
@@ -0,0 +1,20 @@
+
+noinst_LIBRARIES += src/lib/libtor-math.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += src/lib/libtor-math-testing.a
+endif
+
+src_lib_libtor_math_a_SOURCES =        \
+               src/lib/math/fp.c               \
+               src/lib/math/laplace.c
+
+
+src_lib_libtor_math_testing_a_SOURCES = \
+       $(src_lib_libtor_math_a_SOURCES)
+src_lib_libtor_math_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
+src_lib_libtor_math_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS +=                              \
+               src/lib/math/fp.h               \
+               src/lib/math/laplace.h
diff --git a/src/lib/math/laplace.c b/src/lib/math/laplace.c
new file mode 100644 (file)
index 0000000..8e45a1f
--- /dev/null
@@ -0,0 +1,67 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "lib/math/laplace.h"
+#include "lib/math/fp.h"
+
+#include "lib/log/util_bug.h"
+
+#include <math.h>
+#include <stdlib.h>
+
+/** Transform a random value <b>p</b> from the uniform distribution in
+ * [0.0, 1.0[ into a Laplace distributed value with location parameter
+ * <b>mu</b> and scale parameter <b>b</b>. Truncate the final result
+ * to be an integer in [INT64_MIN, INT64_MAX]. */
+int64_t
+sample_laplace_distribution(double mu, double b, double p)
+{
+  double result;
+  tor_assert(p >= 0.0 && p < 1.0);
+
+  /* This is the "inverse cumulative distribution function" from:
+   * http://en.wikipedia.org/wiki/Laplace_distribution */
+  if (p <= 0.0) {
+    /* Avoid taking log(0.0) == -INFINITY, as some processors or compiler
+     * options can cause the program to trap. */
+    return INT64_MIN;
+  }
+
+  result = mu - b * (p > 0.5 ? 1.0 : -1.0)
+                  * tor_mathlog(1.0 - 2.0 * fabs(p - 0.5));
+
+  return clamp_double_to_int64(result);
+}
+
+/** Add random noise between INT64_MIN and INT64_MAX coming from a Laplace
+ * distribution with mu = 0 and b = <b>delta_f</b>/<b>epsilon</b> to
+ * <b>signal</b> based on the provided <b>random</b> value in [0.0, 1.0[.
+ * The epsilon value must be between ]0.0, 1.0]. delta_f must be greater
+ * than 0. */
+int64_t
+add_laplace_noise(int64_t signal_, double random_, double delta_f,
+                  double epsilon)
+{
+  int64_t noise;
+
+  /* epsilon MUST be between ]0.0, 1.0] */
+  tor_assert(epsilon > 0.0 && epsilon <= 1.0);
+  /* delta_f MUST be greater than 0. */
+  tor_assert(delta_f > 0.0);
+
+  /* Just add noise, no further signal */
+  noise = sample_laplace_distribution(0.0,
+                                      delta_f / epsilon,
+                                      random_);
+
+  /* Clip (signal + noise) to [INT64_MIN, INT64_MAX] */
+  if (noise > 0 && INT64_MAX - noise < signal_)
+    return INT64_MAX;
+  else if (noise < 0 && INT64_MIN - noise > signal_)
+    return INT64_MIN;
+  else
+    return signal_ + noise;
+}
diff --git a/src/lib/math/laplace.h b/src/lib/math/laplace.h
new file mode 100644 (file)
index 0000000..b22862e
--- /dev/null
@@ -0,0 +1,16 @@
+/* Copyright (c) 2003, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_LAPLACE_H
+#define TOR_LAPLACE_H
+
+#include "lib/cc/compat_compiler.h"
+#include "lib/cc/torint.h"
+
+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);
+
+#endif
index 908b76b4864dc06a1917a610b3caacc0d278a52f..32b3212d3ff4e7505cc4f7f33f2bfb9130ce1ad8 100644 (file)
@@ -34,6 +34,8 @@
 #include "or/entrynodes.h"
 #include "or/networkstatus.h"
 #include "or/relay.h"
+#include "lib/math/fp.h"
+#include "lib/math/laplace.h"
 
 #include "or/cell_st.h"
 #include "or/cpath_build_state_st.h"
@@ -1574,4 +1576,3 @@ pathbias_scale_use_rates(entry_guard_t *guard)
     entry_guards_changed();
   }
 }
-
index 34605457d572028b70fd73afad717ec12bca289f..08186ca9a94ae86f58cfeae6ab642668fd2125d0 100644 (file)
@@ -40,6 +40,7 @@
 #include "or/statefile.h"
 #include "or/circuitlist.h"
 #include "or/circuituse.h"
+#include "lib/math/fp.h"
 
 #include "or/crypt_path_st.h"
 #include "or/origin_circuit_st.h"
@@ -1946,4 +1947,3 @@ cbt_control_event_buildtimeout_set(const circuit_build_times_t *cbt,
 
   tor_free(args);
 }
-
index 0ba3f34b4032c619696febce620f77d4a0010a38..3669eb7f16e4bb7dc4bc25de1366072a01177379 100644 (file)
@@ -56,6 +56,7 @@
 #include "or/rephist.h"
 #include "or/router.h"
 #include "or/routerlist.h"
+#include "lib/math/fp.h"
 
 #include "or/cpath_build_state_st.h"
 #include "or/dir_connection_st.h"
@@ -3152,4 +3153,3 @@ circuit_read_valid_data(origin_circuit_t *circ, uint16_t relay_body_len)
       tor_add_u32_nowrap(circ->n_overhead_read_circ_bw,
                          RELAY_PAYLOAD_SIZE-relay_body_len);
 }
-
index 47e689b5cbd503561b9d539362433493b9684fee..1919336223efd38486105683b218fe4494472882 100644 (file)
 #include "or/routerset.h"
 #include "or/transports.h"
 #include "or/statefile.h"
+#include "lib/math/fp.h"
 
 #include "or/node_st.h"
 #include "or/origin_circuit_st.h"
index 2103eecdfba82ede10a4add5cfc39b6eceb371bb..907b01d68e4cc1a973a5125b3c2305bf1ed5b728 100644 (file)
@@ -94,6 +94,8 @@
 
 #include "lib/container/bloomfilt.h"
 #include "lib/container/order.h"
+#include "lib/math/fp.h"
+#include "lib/math/laplace.h"
 
 static void bw_arrays_init(void);
 static void predicted_ports_alloc(void);
index a86e29adb24cdf0180699d057ac9b4639195e1a4..68fd763441755cc7cafaec0acf5efd2adc208465 100644 (file)
 #include "or/routerset.h"
 #include "lib/sandbox/sandbox.h"
 #include "or/torcert.h"
+#include "lib/math/fp.h"
 
 #include "or/dirauth/dirvote.h"
 #include "or/dirauth/mode.h"
index 6f07458d4458e0ee7e81d335aa20a2cce4a9f7b1..b62281d58695a12b8a9e25448e5a1578465edd07 100644 (file)
@@ -13,6 +13,7 @@
 #include "or/channeltls.h"
 #define SCHEDULER_PRIVATE_
 #include "or/scheduler.h"
+#include "lib/math/fp.h"
 
 #include "or/or_connection_st.h"
 
@@ -835,4 +836,3 @@ scheduler_can_use_kist(void)
 }
 
 #endif /* defined(HAVE_KIST_SUPPORT) */
-
index bdc6fca7dfe801f28094914ed242d46f2ec39da2..8fe308826b9a3d5a409944cda08ae715084c5041 100644 (file)
@@ -29,6 +29,8 @@
 #include "lib/process/subprocess.h"
 #include "lib/intmath/weakrng.h"
 #include "lib/thread/numcpus.h"
+#include "lib/math/fp.h"
+#include "lib/math/laplace.h"
 
 #ifdef HAVE_PWD_H
 #include <pwd.h>