summaryrefslogtreecommitdiff
path: root/diffpriv.go
blob: 6cf09f1bddf89a80898db9f3b1cc1bc65026cf0f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package main

import (
	"math"
	"math/rand"
	"time"
)

var (
	rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
)

// Returns 0 if epsilon is less than or equal to 0.
// Otherwise it picks a number from the laplace
// distribution with the mean 0 and standard deviation
// sensitivity/epsilon.
// This follows the definition of differential privacy
// noise addition.
func diffpriv(value int, sensitivity, epsilon float64) int {
	if epsilon <= 0 {
		return 0
	}
	noise := laplaceDist(0, sensitivity/epsilon)
	return round(math.Abs(float64(value) + noise))
}

// Returns a random value from a laplace
// distribution with parameters u and b.
func laplaceDist(u, b float64) float64 {
	uniform := rnd.Float64() // Random [0.0,1.0)
	uniform -= 0.5
	return u - b*sgn(uniform)*math.Log(1-2*math.Abs(uniform))
}

// The signum function
func sgn(x float64) float64 {
	if x < 0 {
		return -1
	}
	if x > 0 {
		return 1
	}
	return 0
}

func round(n float64) int {
	if n < 0 {
		return int(math.Ceil(n - 0.5))
	}
	return int(math.Floor(n + 0.5))
}