#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct Work {
pub pixels: u64,
pub samples: u64,
pub blocks: u64,
pub bytes: u64,
}
impl Work {
pub const ZERO: Work = Work {
pixels: 0,
samples: 0,
blocks: 0,
bytes: 0,
};
#[must_use]
pub const fn pixels(n: u64) -> Work {
Work {
pixels: n,
..Work::ZERO
}
}
#[must_use]
pub const fn samples(n: u64) -> Work {
Work {
samples: n,
..Work::ZERO
}
}
#[must_use]
pub const fn blocks(n: u64) -> Work {
Work {
blocks: n,
..Work::ZERO
}
}
pub fn add(&mut self, other: Work) {
self.pixels = self.pixels.saturating_add(other.pixels);
self.samples = self.samples.saturating_add(other.samples);
self.blocks = self.blocks.saturating_add(other.blocks);
self.bytes = self.bytes.saturating_add(other.bytes);
}
#[must_use]
pub fn parity(&self, other: &Work) -> bool {
self == other
}
}
#[must_use]
pub const fn pipeline_gain_permille(share_permille: u32, speedup_x100: u32) -> u32 {
if speedup_x100 <= 100 {
return 0;
}
let removed_x100 = speedup_x100 - 100;
let num = share_permille as u64 * removed_x100 as u64;
((num + speedup_x100 as u64 / 2) / speedup_x100 as u64) as u32
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Verdict {
Build {
gain_permille: u32,
},
BelowFloor {
gain_permille: u32,
floor_permille: u32,
},
}
#[must_use]
pub const fn ceiling(share_permille: u32, speedup_x100: u32, floor_permille: u32) -> Verdict {
let gain_permille = pipeline_gain_permille(share_permille, speedup_x100);
if gain_permille > floor_permille {
Verdict::Build { gain_permille }
} else {
Verdict::BelowFloor {
gain_permille,
floor_permille,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_plan_example_six_percent_stage_four_times_faster_is_four_and_a_half() {
assert_eq!(pipeline_gain_permille(60, 400), 45);
assert_eq!(pipeline_gain_permille(1000, 200), 500);
assert_eq!(pipeline_gain_permille(500, 100), 0);
assert_eq!(
pipeline_gain_permille(500, 50),
0,
"a slowdown buys nothing"
);
assert_eq!(pipeline_gain_permille(1000, 100_000), 999);
}
#[test]
fn a_gain_under_the_floor_is_not_built() {
assert_eq!(
ceiling(60, 400, 50),
Verdict::BelowFloor {
gain_permille: 45,
floor_permille: 50
}
);
assert_eq!(ceiling(300, 400, 50), Verdict::Build { gain_permille: 225 });
assert_eq!(
ceiling(60, 400, 45),
Verdict::BelowFloor {
gain_permille: 45,
floor_permille: 45
},
"equal to the floor is under it"
);
}
#[test]
fn work_adds_saturating_and_parity_is_equality() {
let mut w = Work::pixels(76_800);
w.add(Work::samples(16_000));
w.add(Work {
bytes: u64::MAX,
..Work::ZERO
});
w.add(Work {
bytes: 1,
..Work::ZERO
});
assert_eq!(
w,
Work {
pixels: 76_800,
samples: 16_000,
blocks: 0,
bytes: u64::MAX
}
);
assert!(w.parity(&w));
assert!(!w.parity(&Work::pixels(76_800)));
assert_eq!(Work::blocks(3).blocks, 3);
}
}