///|
/// Return the arithmetic mean, or zero for an empty collection.
pub fn mean(values : Array[Double]) -> Double {
  if values.length() == 0 {
    0.0
  } else {
    let mut total = 0.0
    for value in values {
      total += value
    }
    total / values.length().to_double()
  }
}

///|
/// Return the smallest value, or None for an empty collection.
pub fn minimum(values : Array[Double]) -> Double? {
  if values.length() == 0 {
    None
  } else {
    let mut result = values[0]
    for value in values[1:] {
      if value < result {
        result = value
      }
    }
    Some(result)
  }
}

///|
/// Return the largest value, or None for an empty collection.
pub fn maximum(values : Array[Double]) -> Double? {
  if values.length() == 0 {
    None
  } else {
    let mut result = values[0]
    for value in values[1:] {
      if value > result {
        result = value
      }
    }
    Some(result)
  }
}

///|
/// Return max-min, or zero for an empty collection.
pub fn range(values : Array[Double]) -> Double {
  match (minimum(values), maximum(values)) {
    (Some(low), Some(high)) => high - low
    _ => 0.0
  }
}

///|
/// Return population standard deviation.
pub fn population_stddev(values : Array[Double]) -> Double {
  if values.length() == 0 {
    0.0
  } else {
    let average = mean(values)
    let mut squared = 0.0
    for value in values {
      let difference = value - average
      squared += difference * difference
    }
    (squared / values.length().to_double()).sqrt()
  }
}

///|
/// Return sample standard deviation, using zero for fewer than two values.
pub fn sample_stddev(values : Array[Double]) -> Double {
  if values.length() <= 1 {
    0.0
  } else {
    let average = mean(values)
    let mut squared = 0.0
    for value in values {
      let difference = value - average
      squared += difference * difference
    }
    (squared / (values.length() - 1).to_double()).sqrt()
  }
}

///|
/// Return whether values are non-decreasing.
pub fn is_non_decreasing(values : Array[Double]) -> Bool {
  let mut result = true
  if values.length() > 1 {
    for i in 1.. Bool {
  let mut result = true
  if values.length() > 1 {
    for i in 1.. values[i - 1] {
        result = false
      }
    }
  }
  result
}

///|
/// Return the number of adjacent direction changes.
pub fn direction_change_count(values : Array[Double]) -> Int {
  if values.length() < 3 {
    0
  } else {
    let mut result = 0
    let mut previous_direction = 0
    for i in 1.. values[i - 1] {
        1
      } else if values[i] < values[i - 1] {
        -1
      } else {
        0
      }
      if direction != 0 &&
        previous_direction != 0 &&
        direction != previous_direction {
        result += 1
      }
      if direction != 0 {
        previous_direction = direction
      }
    }
    result
  }
}