LCOV - code coverage report
Current view: top level - lib/math - laplace.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 15 15 100.0 %
Date: 2021-11-24 03:28:48 Functions: 2 2 100.0 %

          Line data    Source code
       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 laplace.c
       8             :  *
       9             :  * \brief Implements a Laplace distribution, used for adding noise to things.
      10             :  **/
      11             : 
      12             : #include "orconfig.h"
      13             : #include "lib/math/laplace.h"
      14             : #include "lib/math/fp.h"
      15             : 
      16             : #include "lib/log/util_bug.h"
      17             : 
      18             : #include <math.h>
      19             : #include <stdlib.h>
      20             : 
      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]. */
      25             : int64_t
      26          36 : sample_laplace_distribution(double mu, double b, double p)
      27             : {
      28          36 :   double result;
      29          36 :   tor_assert(p >= 0.0 && p < 1.0);
      30             : 
      31             :   /* This is the "inverse cumulative distribution function" from:
      32             :    * https://en.wikipedia.org/wiki/Laplace_distribution */
      33          36 :   if (p <= 0.0) {
      34             :     /* Avoid taking log(0.0) == -INFINITY, as some processors or compiler
      35             :      * options can cause the program to trap. */
      36             :     return INT64_MIN;
      37             :   }
      38             : 
      39          27 :   result = mu - b * (p > 0.5 ? 1.0 : -1.0)
      40          27 :                   * tor_mathlog(1.0 - 2.0 * fabs(p - 0.5));
      41             : 
      42          27 :   return clamp_double_to_int64(result);
      43             : }
      44             : 
      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
      49             :  * than 0. */
      50             : int64_t
      51          31 : add_laplace_noise(int64_t signal_, double random_, double delta_f,
      52             :                   double epsilon)
      53             : {
      54          31 :   int64_t noise;
      55             : 
      56             :   /* epsilon MUST be between ]0.0, 1.0] */
      57          31 :   tor_assert(epsilon > 0.0 && epsilon <= 1.0);
      58             :   /* delta_f MUST be greater than 0. */
      59          31 :   tor_assert(delta_f > 0.0);
      60             : 
      61             :   /* Just add noise, no further signal */
      62          31 :   noise = sample_laplace_distribution(0.0,
      63             :                                       delta_f / epsilon,
      64             :                                       random_);
      65             : 
      66             :   /* Clip (signal + noise) to [INT64_MIN, INT64_MAX] */
      67          31 :   if (noise > 0 && INT64_MAX - noise < signal_)
      68             :     return INT64_MAX;
      69          27 :   else if (noise < 0 && INT64_MIN - noise > signal_)
      70             :     return INT64_MIN;
      71             :   else
      72          22 :     return signal_ + noise;
      73             : }

Generated by: LCOV version 1.14