///|
/// Performance evidence for the mechanisms and the audit paths.
///
/// Timing is delegated to the official `moonbitlang/core/bench`
/// harness (batching, warm-up and winsorised statistics are its
/// code, not ours), so the numbers in the README are reproducible
/// with `moon run --release benchmarks`. Markets are generated by a
/// fixed-seed LCG: same binary, same numbers, every run.
struct Lcg {
  mut s : Int64
}

///|
fn Lcg::next(self : Lcg, bound : Int) -> Int {
  // classic Knuth MMIX constants; the mask keeps the drawn value a
  // non-negative 30-bit Int regardless of 64-bit wrap-around
  self.s = self.s * 6364136223846793005L + 1442695040888963407L
  let v = ((self.s >> 33) & 0x3fffffffL).to_int()
  v % bound
}

///|
fn Lcg::perm(self : Lcg, n : Int) -> Array[Int] {
  let out = Array(capacity=n)
  for i in 0.. Array[Array[Int]] {
  let out = Array(capacity=rows)
  for _ in 0.. @moonmatch.Preferences {
  let rng = Lcg::{ s: 42L + n.to_int64() * 1000003L, }
  @moonmatch.Preferences::new(rng.table(n, n), rng.table(n, n)) catch {
    e => @abort.abort("generated market must pass the gate: \{e}")
  }
}

///|
fn main {
  let b = @bench.Bench()
  for n in [100, 300, 1000] {
    let prefs = market(n)
    let m = prefs.deferred_acceptance()
    let cert = m.certificate()
    let rng = Lcg::{ s: 7L + n.to_int64(), }
    let ttc_market = @moonmatch.Market::new(rng.table(n, n), rng.perm(n)) catch {
      e => @abort.abort("generated housing market must pass the gate: \{e}")
    }
    b.bench(name="da_\{n}", fn() { b.keep(prefs.deferred_acceptance()) })
    b.bench(name="blocking_pairs_\{n}", fn() { b.keep(m.blocking_pairs()) })
    b.bench(name="certificate_\{n}", fn() { b.keep(m.certificate()) })
    b.bench(name="verify_\{n}", fn() {
      cert.verify() catch {
        e => @abort.abort("the DA certificate must always verify: \{e}")
      }
    })
    b.bench(name="ttc_\{n}", fn() { b.keep(ttc_market.top_trading_cycles()) })
  }
  println(b.dump_summaries())
}