///|
pub fn welch_psd(
  signal : ArrayView[Double],
  sample_rate~ : Double,
  segment_length~ : Int,
  overlap~ : Double,
  window_kind? : WindowKind = Rectangular,
) -> WelchResult raise SpectrumError {
  if signal.length() == 0 {
    raise EmptySignal
  }
  if sample_rate <= 0.0 {
    raise InvalidArgument(message="sample_rate must be positive")
  }
  if segment_length <= 0 {
    raise InvalidArgument(message="segment_length must be positive")
  }
  if !is_power_of_two(segment_length) {
    raise NonPowerOfTwo(length=segment_length)
  }
  if overlap < 0.0 || overlap >= 1.0 {
    raise InvalidArgument(message="overlap must be in [0, 1)")
  }
  if signal.length() < segment_length {
    raise InvalidArgument(message="signal is shorter than segment_length")
  }
  let raw_step = Double::from_int(segment_length) * (1.0 - overlap)
  let step = raw_step.floor().to_int()
  if step <= 0 {
    raise InvalidArgument(message="overlap leaves no positive step")
  }
  let segment_count = 1 + (signal.length() - segment_length) / step
  let output_length = segment_length / 2 + 1
  let averaged = Array::make(output_length, 0.0)
  for segment in 0..