pub const GRAMS_PER_TROY_OZ: f64 = 31.1034768;
#[inline]
pub fn purity(karat: u32) -> f64 {
karat as f64 / 24.0
}
#[inline]
pub fn spot_per_gram(spot_per_troy_oz: f64) -> f64 {
spot_per_troy_oz / GRAMS_PER_TROY_OZ
}
pub fn melt_value_grams(grams: f64, karat: u32, spot_per_troy_oz: f64) -> f64 {
grams * purity(karat) * spot_per_gram(spot_per_troy_oz)
}
pub fn melt_value_dwt(dwt: f64, karat: u32, spot_per_troy_oz: f64) -> f64 {
let troy_oz = dwt / 20.0;
troy_oz * purity(karat) * spot_per_troy_oz
}
pub fn melt_value_troy_oz(troy_oz: f64, karat: u32, spot_per_troy_oz: f64) -> f64 {
troy_oz * purity(karat) * spot_per_troy_oz
}
pub mod karats {
pub const K24: u32 = 24;
pub const K22: u32 = 22;
pub const K18: u32 = 18;
pub const K14: u32 = 14;
pub const K10: u32 = 10;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn pure_gold_one_gram_at_spot() {
let v = melt_value_grams(1.0, 24, 3983.30);
assert!((v - 128.066).abs() < 0.001);
}
#[test]
fn ten_grams_14k() {
let v = melt_value_grams(10.0, 14, 3983.30);
assert!((v - 747.05).abs() < 0.05);
}
#[test]
fn pennyweight_matches_troy() {
let spot = 3983.30;
let from_dwt = melt_value_dwt(20.0, 24, spot);
let from_oz = melt_value_troy_oz(1.0, 24, spot);
assert!((from_dwt - from_oz).abs() < 1e-6);
}
#[test]
fn purity_table() {
assert_eq!(purity(24), 1.0);
assert!((purity(18) - 0.75).abs() < 1e-9);
assert!((purity(14) - 0.5833333).abs() < 1e-6);
}
}