gold_melt_value/lib.rs
1//! # gold-melt-value
2//!
3//! Compute precious-metal **melt value** from karat (purity), weight, and a live
4//! spot price. Pure, dependency-free math — the same engine behind the
5//! [GoldGramPrice](https://goldgramprice.com/) live gold calculator.
6//!
7//! ## Quick example
8//! ```
9//! use gold_melt_value::{melt_value_grams, purity};
10//!
11//! let spot_per_oz = 3983.30; // USD per troy ounce
12//! let grams = 10.0; // a 10 g chain
13//! let karat = 14;
14//!
15//! let usd = melt_value_grams(grams, karat, spot_per_oz);
16//! // 10 g of 14k contains ~5.83 g pure gold → melt ≈ $747.05
17//! assert!((usd - 747.05).abs() < 0.05);
18//! assert_eq!(purity(14), 14.0 / 24.0);
19//! ```
20
21/// Grams in one troy ounce (1 oz t = 31.1034768 g).
22pub const GRAMS_PER_TROY_OZ: f64 = 31.1034768;
23
24/// Decimal purity for a karat value (karat / 24).
25///
26/// `purity(24) == 1.0` (pure), `purity(18) == 0.75`, `purity(14) ≈ 0.5833`.
27#[inline]
28pub fn purity(karat: u32) -> f64 {
29 karat as f64 / 24.0
30}
31
32/// Spot price per **gram** of pure metal, derived from a per-troy-ounce quote.
33#[inline]
34pub fn spot_per_gram(spot_per_troy_oz: f64) -> f64 {
35 spot_per_troy_oz / GRAMS_PER_TROY_OZ
36}
37
38/// Melt value (in the spot-price currency) for a given **weight in grams**,
39/// `karat`, and `spot_per_troy_oz`.
40///
41/// Melt = grams × purity × (spot / 31.1034768).
42pub fn melt_value_grams(grams: f64, karat: u32, spot_per_troy_oz: f64) -> f64 {
43 grams * purity(karat) * spot_per_gram(spot_per_troy_oz)
44}
45
46/// Melt value for a weight in **pennyweight** (dwt). 1 dwt = 1/20 troy oz.
47pub fn melt_value_dwt(dwt: f64, karat: u32, spot_per_troy_oz: f64) -> f64 {
48 let troy_oz = dwt / 20.0;
49 troy_oz * purity(karat) * spot_per_troy_oz
50}
51
52/// Melt value for a weight in **troy ounces** (already in troy units).
53pub fn melt_value_troy_oz(troy_oz: f64, karat: u32, spot_per_troy_oz: f64) -> f64 {
54 troy_oz * purity(karat) * spot_per_troy_oz
55}
56
57/// Common karat purities used in jewelry (US).
58pub mod karats {
59 pub const K24: u32 = 24;
60 pub const K22: u32 = 22;
61 pub const K18: u32 = 18;
62 pub const K14: u32 = 14;
63 pub const K10: u32 = 10;
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn pure_gold_one_gram_at_spot() {
72 // 1 g of 24k at $3983.30/oz ≈ $128.066
73 let v = melt_value_grams(1.0, 24, 3983.30);
74 assert!((v - 128.066).abs() < 0.001);
75 }
76
77 #[test]
78 fn ten_grams_14k() {
79 // 10 g of 14k at $3983.30/oz ≈ $747.05
80 let v = melt_value_grams(10.0, 14, 3983.30);
81 assert!((v - 747.05).abs() < 0.05);
82 }
83
84 #[test]
85 fn pennyweight_matches_troy() {
86 let spot = 3983.30;
87 // 20 dwt == 1 troy oz of 24k
88 let from_dwt = melt_value_dwt(20.0, 24, spot);
89 let from_oz = melt_value_troy_oz(1.0, 24, spot);
90 assert!((from_dwt - from_oz).abs() < 1e-6);
91 }
92
93 #[test]
94 fn purity_table() {
95 assert_eq!(purity(24), 1.0);
96 assert!((purity(18) - 0.75).abs() < 1e-9);
97 assert!((purity(14) - 0.5833333).abs() < 1e-6);
98 }
99}