import numpy as np


def laplace_mechanism(true_value, sensitivity, epsilon, rng):
    """Add calibrated Laplace noise to achieve epsilon-differential
    privacy for a single numeric query (e.g., a count or a mean).

    sensitivity: the maximum amount the true_value could change if
    a single individual's record were added to or removed from the
    dataset -- this, together with epsilon, sets the noise scale.
    """
    scale = sensitivity / epsilon
    noise = rng.laplace(0, scale)
    return true_value + noise


def private_mean(data, data_min, data_max, epsilon, rng):
    """A DP mean estimate: clip each record to a known range (so
    a single record's maximum possible influence on the sum is
    bounded), then add Laplace noise scaled to that bound."""
    clipped = np.clip(data, data_min, data_max)
    n = len(clipped)
    sensitivity = (data_max - data_min) / n
    true_mean = clipped.mean()
    return laplace_mechanism(true_mean, sensitivity, epsilon, rng)
