///|
pub fn dft(signal : ArrayView[Complex]) -> Array[Complex] raise SpectrumError {
  let n = signal.length()
  if n == 0 {
    raise EmptySignal
  }
  let out : Array[Complex] = []
  for k in 0.. Array[Complex] raise SpectrumError {
  let n = signal.length()
  if n == 0 {
    raise EmptySignal
  }
  if !is_power_of_two(n) {
    raise NonPowerOfTwo(length=n)
  }
  fft_inner(signal)
}

///|
pub fn ifft(
  spectrum : ArrayView[Complex],
) -> Array[Complex] raise SpectrumError {
  let n = spectrum.length()
  if n == 0 {
    raise EmptySignal
  }
  let conjugated = spectrum.map(item => complex(re=item.re, im=-item.im))
  let transformed = fft(conjugated)
  transformed.map(item => {
    complex(re=item.re / Double::from_int(n), im=-item.im / Double::from_int(n))
  })
}

///|
pub fn real_signal(values : ArrayView[Double]) -> Array[Complex] {
  values.map(v => complex(re=v, im=0.0))
}

///|
fn is_power_of_two(n : Int) -> Bool {
  if n <= 0 {
    false
  } else {
    for value = n; value > 1; {
      if value % 2 != 0 {
        break false
      } else {
        continue value / 2
      }
    } nobreak {
      true
    }
  }
}

///|
fn fft_inner(signal : ArrayView[Complex]) -> Array[Complex] {
  let n = signal.length()
  if n == 1 {
    [signal[0]]
  } else {
    let even : Array[Complex] = []
    let odd : Array[Complex] = []
    for i in 0..