#![allow(dead_code)]
use handwired_rs::{Circuit, CompareOptions, Lin, OutOfRange, Relation, Wire, emit_compare_with};
pub struct Rng(u64);
impl Rng {
pub fn new(seed: u64) -> Rng {
Rng(seed.wrapping_mul(0x9E37_79B9_7F4A_7C15) | 1)
}
pub fn next_u64(&mut self) -> u64 {
self.0 ^= self.0 >> 12;
self.0 ^= self.0 << 25;
self.0 ^= self.0 >> 27;
self.0.wrapping_mul(0x2545_F491_4F6C_DD1D)
}
pub fn below(&mut self, bound: usize) -> usize {
(self.next_u64() % bound as u64) as usize
}
pub fn uniform(&mut self, min: f64, max: f64) -> f64 {
min + (self.next_u64() >> 11) as f64 / (1u64 << 53) as f64 * (max - min)
}
pub fn pick<T: Copy>(&mut self, items: &[T]) -> T {
items[self.below(items.len())]
}
}
pub fn step_f32(value: f32, up: bool) -> f32 {
if value == 0.0 {
let tiny = f32::from_bits(1);
return if up { tiny } else { -tiny };
}
let bits = value.to_bits();
let away_from_zero = (value > 0.0) == up;
f32::from_bits(if away_from_zero { bits + 1 } else { bits - 1 })
}
pub const SOURCES: usize = 6;
pub fn random_circuit(rng: &mut Rng, operations: usize) -> Circuit {
let mut circuit = Circuit::new(SOURCES);
for index in 0..4 {
circuit.assume_range(circuit.source(index), -10.0, 10.0);
}
circuit.assume_bit(circuit.source(4));
let index = circuit.source(5);
circuit.assume_range(index, 0.0, 7.0);
circuit.assume_grid(index, 1.0);
let bit = circuit.source(4);
let coefficients = [1.0, -1.0, 0.5, 2.0, -0.25, 0.1, 3.7, -1.3];
let mut wires: Vec<Wire> = (0..4).map(|index| circuit.source(index)).collect();
while circuit.operations().len() < operations {
let bounded: Vec<Wire> = wires
.iter()
.copied()
.filter(|&wire| {
let range = circuit.range(wire);
range.is_finite() && range.min.abs().max(range.max.abs()) < 1e4
})
.collect();
let pick = |rng: &mut Rng| rng.pick(&bounded);
let form = |rng: &mut Rng| {
let count = 1 + rng.below(5);
let terms = (0..count).map(|_| (pick(rng), rng.pick(&coefficients))).collect();
Lin::new(terms, rng.pick(&coefficients))
};
let wire = match rng.below(7) {
0 => circuit.affine(form(rng)),
1 => circuit.round_affine(form(rng)),
2 => circuit.reglu(form(rng), form(rng)),
3 => circuit.multiply(pick(rng), pick(rng)),
4 => circuit.select(bit, pick(rng), pick(rng)),
5 => {
let (a, b) = (pick(rng), pick(rng));
let relation = rng.pick(&[Relation::Greater, Relation::AtLeast, Relation::Equal]);
let end_with_boolean = rng.below(2) == 0;
emit_compare_with(&mut circuit, a, relation, b, CompareOptions { end_with_boolean })
}
_ => {
let table: Vec<Wire> = (0..1 + rng.below(8)).map(|_| pick(rng)).collect();
let rule = rng.pick(&[OutOfRange::Clamp, OutOfRange::Zero]);
circuit.index_read(index, &table, rule)
}
};
wires.push(wire);
}
circuit
}
pub fn random_source(rng: &mut Rng) -> Vec<f32> {
let mut source: Vec<f32> = (0..4).map(|_| rng.uniform(-10.0, 10.0) as f32).collect();
source.push(rng.below(2) as f32);
source.push(rng.below(8) as f32);
source
}