use crate::estimate::Estimate;
pub const K_B: f64 = 1.380_649e-23;
pub const H_BAR: f64 = 1.054_571_817e-34;
pub const LANDAUER_JOULES_300K: f64 = 2.870_979e-21;
pub type LandauerCost = Estimate<f64>;
#[must_use]
#[allow(clippy::cast_precision_loss)] pub fn landauer_floor_joules(bits_erased: u64, temperature_k: f64) -> LandauerCost {
let joules = bits_erased as f64 * K_B * temperature_k * std::f64::consts::LN_2;
Estimate::exact(joules)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn landauer_floor_at_300k_one_bit() {
let cost = landauer_floor_joules(1, 300.0);
let expected = LANDAUER_JOULES_300K;
let ratio = cost.point / expected;
assert!((ratio - 1.0).abs() < 1e-3, "ratio={ratio}");
}
#[test]
fn landauer_floor_scales_linearly_with_bits() {
let one = landauer_floor_joules(1, 300.0).point;
let mega = landauer_floor_joules(1_000_000, 300.0).point;
let ratio = mega / one;
assert!((ratio - 1_000_000.0).abs() < 1.0, "ratio={ratio}");
}
#[test]
fn landauer_floor_scales_linearly_with_temperature() {
let at_300 = landauer_floor_joules(1, 300.0).point;
let at_600 = landauer_floor_joules(1, 600.0).point;
let ratio = at_600 / at_300;
assert!((ratio - 2.0).abs() < 1e-10, "ratio={ratio}");
}
#[test]
fn landauer_floor_zero_bits_is_zero() {
let cost = landauer_floor_joules(0, 300.0);
assert_eq!(cost.point, 0.0);
}
}