///|
fn run_scalar(iterations : Int) -> Double {
  let filter = @kalman.Kalman1D::new(0.0, 1.0, 0.02, 0.1)
  filter.set_gate_threshold(100000.0)
  let mut checksum = 0.0
  for i in 0.. Double {
  let model = @kalman.constant_velocity_model(2, 0.1, 0.05, 0.2)
  let filter = @kalman.KalmanND::from_model(
    model,
    [0.0, 0.0, 0.0, 0.0],
    @kalman.Matrix::identity(4),
  )
  filter.set_gate_threshold(100000.0)
  let mut checksum = 0.0
  for i in 0.. ignore
    checksum = checksum + filter.state()[0] + filter.state()[1]
  }
  checksum
}

///|
fn main {
  let scalar_iterations = 1000000
  let matrix_iterations = 10000
  let scalar_start = @env.now()
  let scalar_checksum = run_scalar(scalar_iterations)
  let scalar_elapsed = @env.now() - scalar_start
  let matrix_start = @env.now()
  let matrix_checksum = run_matrix(matrix_iterations)
  let matrix_elapsed = @env.now() - matrix_start
  println("moon-kalman benchmark (native release)")
  println(
    "scalar: iterations=\{scalar_iterations}, elapsed_ms=\{scalar_elapsed}, checksum=\{scalar_checksum}",
  )
  println(
    "matrix_4x2: iterations=\{matrix_iterations}, elapsed_ms=\{matrix_elapsed}, checksum=\{matrix_checksum}",
  )
  let scalar_elapsed_ms = scalar_elapsed.to_double()
  let matrix_elapsed_ms = matrix_elapsed.to_double()
  let scalar_rate = if scalar_elapsed_ms <= 0.0 {
    scalar_iterations.to_double() * 1000.0
  } else {
    scalar_iterations.to_double() * 1000.0 / scalar_elapsed_ms
  }
  let matrix_rate = if matrix_elapsed_ms <= 0.0 {
    matrix_iterations.to_double() * 1000.0
  } else {
    matrix_iterations.to_double() * 1000.0 / matrix_elapsed_ms
  }
  println("scalar_updates_per_second=\{scalar_rate}")
  println("matrix_updates_per_second=\{matrix_rate}")
}