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 */
9 * \brief Implements a Laplace distribution, used for adding noise to things.
13 #include "lib/math/laplace.h"
14 #include "lib/math/fp.h"
16 #include "lib/log/util_bug.h"
21 /** Transform a random value <b>p</b> from the uniform distribution in
22 * [0.0, 1.0[ into a Laplace distributed value with location parameter
23 * <b>mu</b> and scale parameter <b>b</b>. Truncate the final result
24 * to be an integer in [INT64_MIN, INT64_MAX]. */
26 sample_laplace_distribution(double mu
, double b
, double p
)
29 tor_assert(p
>= 0.0 && p
< 1.0);
31 /* This is the "inverse cumulative distribution function" from:
32 * https://en.wikipedia.org/wiki/Laplace_distribution */
34 /* Avoid taking log(0.0) == -INFINITY, as some processors or compiler
35 * options can cause the program to trap. */
39 result
= mu
- b
* (p
> 0.5 ? 1.0 : -1.0)
40 * tor_mathlog(1.0 - 2.0 * fabs(p
- 0.5));
42 return clamp_double_to_int64(result
);
45 /** Add random noise between INT64_MIN and INT64_MAX coming from a Laplace
46 * distribution with mu = 0 and b = <b>delta_f</b>/<b>epsilon</b> to
47 * <b>signal</b> based on the provided <b>random</b> value in [0.0, 1.0[.
48 * The epsilon value must be between ]0.0, 1.0]. delta_f must be greater
51 add_laplace_noise(int64_t signal_
, double random_
, double delta_f
,
56 /* epsilon MUST be between ]0.0, 1.0] */
57 tor_assert(epsilon
> 0.0 && epsilon
<= 1.0);
58 /* delta_f MUST be greater than 0. */
59 tor_assert(delta_f
> 0.0);
61 /* Just add noise, no further signal */
62 noise
= sample_laplace_distribution(0.0,
66 /* Clip (signal + noise) to [INT64_MIN, INT64_MAX] */
67 if (noise
> 0 && INT64_MAX
- noise
< signal_
)
69 else if (noise
< 0 && INT64_MIN
- noise
> signal_
)
72 return signal_
+ noise
;