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)) }