Skip to content

Commit 25f8816

Browse files
committed
WIP: Log approximation
1 parent 76d8581 commit 25f8816

File tree

1 file changed

+77
-13
lines changed

1 file changed

+77
-13
lines changed

lightning/src/routing/scoring.rs

Lines changed: 77 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,35 @@ impl<L: DerefMut<Target = u64>, T: Time, U: DerefMut<Target = T>> DirectedChanne
722722
}
723723
}
724724

725+
const FRACTIONAL_BITS: u32 = 3;
726+
const FRACTIONAL_BITMASK: u64 = (1 << FRACTIONAL_BITS) - 1;
727+
const LOG2_FRACTIONAL_PART: [f64; 1 << FRACTIONAL_BITS] =
728+
[0.0, 0.17, 0.32, 0.46, 0.58, 0.70, 0.81, 0.91];
729+
const LOG2_10: f64 = 3.32;
730+
731+
fn log10_approx(numerator: u64, denominator: u64) -> f64 {
732+
(log2_approx(numerator) - log2_approx(denominator)) / LOG2_10
733+
}
734+
735+
#[inline]
736+
fn log2_approx(x: u64) -> f64 {
737+
let leading_zeros = x.leading_zeros();
738+
let integer_part = (63 - leading_zeros) as f64;
739+
let fractional_part = LOG2_FRACTIONAL_PART[
740+
(((x << leading_zeros) >> (63 - FRACTIONAL_BITS)) & FRACTIONAL_BITMASK) as usize
741+
];
742+
integer_part + fractional_part
743+
}
744+
745+
fn log10_approx_without_fractional(numerator: u64, denominator: u64) -> f64 {
746+
(log2_approx_without_fractional(numerator) - log2_approx_without_fractional(denominator)) / LOG2_10
747+
}
748+
749+
#[inline]
750+
fn log2_approx_without_fractional(x: u64) -> f64 {
751+
(63 - x.leading_zeros()) as f64
752+
}
753+
725754
impl<G: Deref<Target = NetworkGraph>, T: Time> Score for ProbabilisticScorerUsingTime<G, T> {
726755
fn channel_penalty_msat(
727756
&self, short_channel_id: u64, amount_msat: u64, capacity_msat: u64, source: &NodeId,
@@ -742,8 +771,8 @@ impl<G: Deref<Target = NetworkGraph>, T: Time> Score for ProbabilisticScorerUsin
742771
Probability::Zero => u64::max_value(),
743772
Probability::One => 0,
744773
Probability::Ratio { numerator, denominator } => {
745-
let success_probability = numerator as f64 / denominator as f64;
746-
(-(success_probability.log10()) * liquidity_penalty_multiplier_msat as f64) as u64
774+
let log_success_probability = log10_approx(numerator, denominator);
775+
(-log_success_probability * liquidity_penalty_multiplier_msat as f64) as u64
747776
},
748777
}
749778
}
@@ -1742,43 +1771,43 @@ mod tests {
17421771
let target = target_node_id();
17431772

17441773
assert_eq!(scorer.channel_penalty_msat(42, 0, 1_024, &source, &target), 0);
1745-
assert_eq!(scorer.channel_penalty_msat(42, 1_024, 1_024, &source, &target), 3_010);
1774+
assert_eq!(scorer.channel_penalty_msat(42, 1_024, 1_024, &source, &target), 3_012);
17461775

17471776
scorer.payment_path_failed(&payment_path_for_amount(768).iter().collect::<Vec<_>>(), 42);
17481777
scorer.payment_path_failed(&payment_path_for_amount(128).iter().collect::<Vec<_>>(), 43);
17491778

17501779
assert_eq!(scorer.channel_penalty_msat(42, 128, 1_024, &source, &target), 0);
1751-
assert_eq!(scorer.channel_penalty_msat(42, 256, 1_024, &source, &target), 92);
1752-
assert_eq!(scorer.channel_penalty_msat(42, 768, 1_024, &source, &target), 1_424);
1780+
assert_eq!(scorer.channel_penalty_msat(42, 256, 1_024, &source, &target), 96);
1781+
assert_eq!(scorer.channel_penalty_msat(42, 768, 1_024, &source, &target), 1_427);
17531782
assert_eq!(scorer.channel_penalty_msat(42, 896, 1_024, &source, &target), u64::max_value());
17541783

17551784
SinceEpoch::advance(Duration::from_secs(9));
17561785
assert_eq!(scorer.channel_penalty_msat(42, 128, 1_024, &source, &target), 0);
1757-
assert_eq!(scorer.channel_penalty_msat(42, 256, 1_024, &source, &target), 92);
1758-
assert_eq!(scorer.channel_penalty_msat(42, 768, 1_024, &source, &target), 1_424);
1786+
assert_eq!(scorer.channel_penalty_msat(42, 256, 1_024, &source, &target), 96);
1787+
assert_eq!(scorer.channel_penalty_msat(42, 768, 1_024, &source, &target), 1_427);
17591788
assert_eq!(scorer.channel_penalty_msat(42, 896, 1_024, &source, &target), u64::max_value());
17601789

17611790
SinceEpoch::advance(Duration::from_secs(1));
17621791
assert_eq!(scorer.channel_penalty_msat(42, 64, 1_024, &source, &target), 0);
1763-
assert_eq!(scorer.channel_penalty_msat(42, 128, 1_024, &source, &target), 34);
1764-
assert_eq!(scorer.channel_penalty_msat(42, 896, 1_024, &source, &target), 1_812);
1792+
assert_eq!(scorer.channel_penalty_msat(42, 128, 1_024, &source, &target), 36);
1793+
assert_eq!(scorer.channel_penalty_msat(42, 896, 1_024, &source, &target), 1_807);
17651794
assert_eq!(scorer.channel_penalty_msat(42, 960, 1_024, &source, &target), u64::max_value());
17661795

17671796
// Fully decay liquidity lower bound.
17681797
SinceEpoch::advance(Duration::from_secs(10 * 7));
17691798
assert_eq!(scorer.channel_penalty_msat(42, 0, 1_024, &source, &target), 0);
17701799
assert_eq!(scorer.channel_penalty_msat(42, 1, 1_024, &source, &target), 0);
1771-
assert_eq!(scorer.channel_penalty_msat(42, 1_023, 1_024, &source, &target), 2_709);
1772-
assert_eq!(scorer.channel_penalty_msat(42, 1_024, 1_024, &source, &target), 3_010);
1800+
assert_eq!(scorer.channel_penalty_msat(42, 1_023, 1_024, &source, &target), 2_710);
1801+
assert_eq!(scorer.channel_penalty_msat(42, 1_024, 1_024, &source, &target), 3_012);
17731802

17741803
// Fully decay liquidity upper bound.
17751804
SinceEpoch::advance(Duration::from_secs(10));
17761805
assert_eq!(scorer.channel_penalty_msat(42, 0, 1_024, &source, &target), 0);
1777-
assert_eq!(scorer.channel_penalty_msat(42, 1_024, 1_024, &source, &target), 3_010);
1806+
assert_eq!(scorer.channel_penalty_msat(42, 1_024, 1_024, &source, &target), 3_012);
17781807

17791808
SinceEpoch::advance(Duration::from_secs(10));
17801809
assert_eq!(scorer.channel_penalty_msat(42, 0, 1_024, &source, &target), 0);
1781-
assert_eq!(scorer.channel_penalty_msat(42, 1_024, 1_024, &source, &target), 3_010);
1810+
assert_eq!(scorer.channel_penalty_msat(42, 1_024, 1_024, &source, &target), 3_012);
17821811
}
17831812

17841813
#[test]
@@ -1904,3 +1933,38 @@ mod tests {
19041933
assert_eq!(deserialized_scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 367);
19051934
}
19061935
}
1936+
1937+
#[cfg(all(test, feature = "unstable", not(feature = "no-std")))]
1938+
mod benches {
1939+
use super::*;
1940+
1941+
use test::black_box;
1942+
use test::Bencher;
1943+
1944+
#[bench]
1945+
fn log10_bench(bench: &mut Bencher) {
1946+
bench.iter(|| {
1947+
for i in 1..85_184 {
1948+
black_box((i as f64 / 85_184 as f64).log10());
1949+
}
1950+
});
1951+
}
1952+
1953+
#[bench]
1954+
fn log10_approx_bench(bench: &mut Bencher) {
1955+
bench.iter(|| {
1956+
for i in 1..85_184 {
1957+
black_box(log10_approx(i, 85_184));
1958+
}
1959+
});
1960+
}
1961+
1962+
#[bench]
1963+
fn log10_approx_without_fractional_bench(bench: &mut Bencher) {
1964+
bench.iter(|| {
1965+
for i in 1..85_184 {
1966+
black_box(log10_approx_without_fractional(i, 85_184));
1967+
}
1968+
});
1969+
}
1970+
}

0 commit comments

Comments
 (0)