///|
struct StreamingRobustStats {
  mut count : Int
  mut mu : Double
  mut m2 : Double
  clip_limit : Double
}

///|
pub fn StreamingRobustStats::new(clip_limit : Double) -> StreamingRobustStats {
  { count: 0, mu: 0.0, m2: 0.0, clip_limit }
}

///|
pub fn StreamingRobustStats::push(
  self : StreamingRobustStats,
  value : Double,
) -> Unit {
  self.count += 1
  let c = self.count.to_double()

  if self.count == 1 {
    self.mu = value
    return
  }

  let mut dev = value - self.mu
  if dev > self.clip_limit {
    dev = self.clip_limit
  }
  if dev < -self.clip_limit {
    dev = -self.clip_limit
  }

  let new_mu = self.mu + dev / c
  self.m2 += dev * (value - new_mu)
  self.mu = new_mu
}

///|
pub fn StreamingRobustStats::mean(self : StreamingRobustStats) -> Double {
  self.mu
}

///|
pub fn StreamingRobustStats::variance(self : StreamingRobustStats) -> Double {
  if self.count > 1 {
    self.m2 / (self.count - 1).to_double()
  } else {
    0.0
  }
}