#![allow(clippy::excessive_precision)]
use handwired_rs::handwired;
#[handwired]
fn pick(a: u8) -> u8 {
if a > 4 { 10 } else { 12 }
}
#[test]
fn readme_example() {
let compiled = pick_circuit();
for a in 0..=255u8 {
assert_eq!(compiled.eval(&(a,)).unwrap(), pick(a));
}
assert!(compiled.program.live_operation_count() <= 8, "{}", compiled.program.live_operation_count());
}
#[handwired]
#[allow(clippy::too_many_arguments)]
fn toggle_step(
on: bool,
armed: bool,
#[range(0, 16384)] viewport_width: i32,
#[range(0, 16384)] viewport_height: i32,
down: bool,
#[range(-16384, 16384)]
#[grid(1.0 / 64.0)]
down_x: f32,
#[range(-16384, 16384)]
#[grid(1.0 / 64.0)]
down_y: f32,
up: bool,
#[range(-16384, 16384)]
#[grid(1.0 / 64.0)]
up_x: f32,
#[range(-16384, 16384)]
#[grid(1.0 / 64.0)]
up_y: f32,
cancel: bool,
) -> (bool, bool) {
let track_left = viewport_width as f32 * 0.5 - 26.0;
let track_top = viewport_height as f32 * 0.5 - 16.0;
let down_inside =
down_x >= track_left && down_x < track_left + 52.0 && down_y >= track_top && down_y < track_top + 32.0;
let up_inside = up_x >= track_left && up_x < track_left + 52.0 && up_y >= track_top && up_y < track_top + 32.0;
let mut on = on;
let mut armed = armed;
if down {
armed = down_inside;
}
if up && armed && up_inside {
on = !on;
}
if up || cancel {
armed = false;
}
(on, armed)
}
#[test]
fn toggle_matches_its_function() {
let compiled = toggle_step_circuit();
let report = compiled.verify(20_000).unwrap();
assert_eq!(report.skipped, 0);
for x in [613.984_375f32, 614.0, 640.0, 665.984_375, 666.0] {
for y in [383.984_375f32, 384.0, 400.0, 415.984_375, 416.0] {
for (on, armed, down, up) in
[(false, false, true, false), (false, true, false, true), (true, true, true, true)]
{
let args = (on, armed, 1280, 800, down, x, y, up, x, y, false);
assert_eq!(compiled.eval(&args).unwrap(), compiled.oracle(args), "{args:?}");
}
}
}
}
#[handwired]
fn arithmetic(a: u8, b: u8, #[range(-1000, 1000)] c: i16) -> (u16, i16, bool) {
let sum = a as u16 + b as u16 * 3;
let difference = c - a as i16;
let either = a == b || c != 0;
(sum, difference.abs(), either)
}
#[test]
fn integer_arithmetic_and_casts() {
let report = arithmetic_circuit().verify(20_000).unwrap();
assert_eq!(report.skipped, 0);
}
#[test]
fn batches_run_typed_records() {
let compiled = arithmetic_circuit();
let records: Vec<(u8, u8, i16)> =
(0..1_000).map(|n: i32| ((n * 7 % 256) as u8, (n * 13 % 256) as u8, (n * 37 % 2001 - 1000) as i16)).collect();
let results = compiled.run_batch(&records).unwrap();
for (record, result) in records.iter().zip(results) {
assert_eq!(result, arithmetic(record.0, record.1, record.2), "{record:?}");
}
assert!(matches!(compiled.run_batch(&[(0, 0, 2000)]), Err(handwired_rs::Error::SourceOutOfRange { .. })));
}
#[handwired]
fn overflowing(a: u8, b: u8) -> u8 {
if a > b { a - b } else { a + b }
}
#[cfg(debug_assertions)]
#[test]
fn panicking_inputs_are_skipped() {
let report = overflowing_circuit().verify(5_000).unwrap();
assert!(report.checked > 0 && report.skipped > 0, "{report:?}");
}