// Native CUDA research workflow, from new weights through exact continuation.
// Requires a CUDA-enabled Aner build and a complete available CUDA backend.
// These small synthetic documents check mechanisms, not language-model quality.
// Run from a fresh output directory; checkpoints never replace existing files.
import aner.token
import aner.gen
import aner.nn

fn verify(label: String, condition: Bool) -> Unit {
    print("check_" + label)
    if !condition {
        let failure: Result<Bool, String> = Result.err(label)
        print(failure.unwrap())
    }
    print(condition)
}
fn same_ids(left: List, right: List) -> Bool {
    if left.len() != right.len() { return false }
    var index = 0
    while index < left.len() {
        if cast<Int64>(left.get(index)) != cast<Int64>(right.get(index)) { return false }
        index = index + 1
    }
    return true
}

// No fallback: require CUDA sequence support before choosing its exact dtype.
verify("cuda_available", gen.device_supported("cuda", "Float32"))
nn.configure("cuda", "Float32", "preserve")
let documents = List(
    "temperature pressure temperature pressure",
    "pressure temperature pressure temperature")
let fitting = token.corpus(token.byte_tokenizer(), documents, role: "training")
let codec = token.bpe(fitting, vocabulary: 280, min_frequency: 2)
let training = token.corpus(codec, documents, role: "training")
let validation = token.corpus(codec, List(
    "temperature pressure measurement",
    "pressure temperature experiment"), role: "validation")
let initial = gen.decoder(codec, context: 24, width: 8,
    heads: 2, layers: 1, seed: 63, dropout: 0.1)
verify("cuda_placement", initial.device() == "cuda" && initial.dtype() == "Float32")
print(initial.memory_summary(2, 24, true))

let partial = initial.train(training, steps: 2, batch: 2, rate: 0.005, seed: 99,
    clip_norm: 1.0, warmup_steps: 2, weight_decay: 0.01)
partial.save("cuda-partial.anergen")
let restored = gen.load("cuda-partial.anergen", device: "cuda")
verify("checkpoint_roundtrip", restored.fingerprint() == partial.fingerprint())
let trained = restored.resume(training, steps: 2)
let uninterrupted = initial.train(training, steps: 4, batch: 2, rate: 0.005, seed: 99,
    clip_norm: 1.0, warmup_steps: 2, weight_decay: 0.01)
verify("exact_resume", trained.fingerprint() == uninterrupted.fingerprint())
verify("update_count", trained.steps() == 4)
print("validation_loss")
print(trained.loss(validation))

let prompt = codec.encode("temperature", bos: true, eos: false)
let identity = trained.fingerprint()
let cached = trained.generate(prompt, max_new_tokens: 8,
    temperature: 0.0, top_k: 0, top_p: 1.0, seed: 7, use_cache: true)
let uncached = trained.generate(prompt, max_new_tokens: 8,
    temperature: 0.0, top_k: 0, top_p: 1.0, seed: 7, use_cache: false)
verify("greedy_cache_reference", same_ids(cached, uncached))
let sampled = trained.generate(prompt, max_new_tokens: 8,
    temperature: 0.8, top_k: 20, top_p: 0.95, seed: 71)
let sampled_reference = trained.generate(prompt, max_new_tokens: 8,
    temperature: 0.8, top_k: 20, top_p: 0.95, seed: 71, use_cache: false)
verify("seeded_cache_reference", same_ids(sampled, sampled_reference))
verify("inference_preserves_state", trained.fingerprint() == identity && trained.steps() == 4)
trained.save("cuda-trained.anergen")
print("continuation_hex")
print(codec.decode_bytes(cached, skip_special: true).hex())
print("cuda_checks_passed")
