// CPU-only independent stochastic path repetitions.
// Run once with a native optimized build; no artifacts are written by this benchmark.
// Change worker count deliberately to fit the machine's effective allocation.
import aner.parallel

fn stochastic_path(parameters: List, iteration: Int64, seed: Int64) -> List {
    let initial = cast<Float64>(parameters.get(0))
    let steps = cast<Int64>(parameters.get(1))
    let drift = cast<Float64>(parameters.get(2))
    let shock = cast<Float64>(parameters.get(3))
    var value = initial
    var draw = 0
    var peak = initial
    while draw < steps {
        let innovation = parallel.random(seed: seed, draw: draw) - 0.5
        value = value + drift + shock * innovation
        if value > peak { peak = value }
        draw = draw + 1
    }
    return List(value, peak)
}

// General parameters are created once, before the parallel boundary.
let parameters = List(100.0, 200, 0.01, 0.2)
let one = parallel.repeat(iterations: 10000, task: stochastic_path,
    parameters: parameters, execution: parallel.local(workers: 1), seed: 2026)
let four = parallel.repeat(iterations: 10000, task: stochastic_path,
    parameters: parameters, execution: parallel.local(workers: 4), seed: 2026)

// The call returns only after every independent repetition has completed.
var identical = true
var iteration = 0
while iteration < one.rows() {
    if one.value(iteration, 0) != four.value(iteration, 0) ||
       one.value(iteration, 1) != four.value(iteration, 1) ||
       one.seed(iteration) != four.seed(iteration) { identical = false }
    iteration = iteration + 1
}
print("Identical results across worker counts")
print(identical)
print("One-worker seconds")
print(one.seconds())
print("Four-worker seconds")
print(four.seconds())
print("Measured speedup")
print(one.seconds() / four.seconds())
print("Final value mean and sample standard deviation")
print(four.mean(column: 0))
print(four.std(column: 0, sample: true))
print("Peak value mean")
print(four.mean(column: 1))
