From bc9d68da1225969a1524057907881090f5500137 Mon Sep 17 00:00:00 2001 From: DrunkRandomWalker Date: Mon, 23 Oct 2023 11:10:08 -0400 Subject: [PATCH] fix a bug in must_from_str, add _ln_robust which has a smaller error in when x is small --- Cargo.lock | 247 +++++++++++++++++- .../injective-math/src/fp_decimal/from_str.rs | 18 +- packages/injective-math/src/fp_decimal/log.rs | 47 ++-- packages/injective-math/src/fp_decimal/mod.rs | 2 + 4 files changed, 285 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 83b4fa1e..b8c0d508 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,6 +44,12 @@ dependencies = [ "odds", ] +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + [[package]] name = "atomic-order-example" version = "0.1.0" @@ -116,6 +122,18 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "block-buffer" version = "0.9.0" @@ -146,6 +164,12 @@ version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + [[package]] name = "byteorder" version = "1.4.3" @@ -574,7 +598,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" dependencies = [ "curve25519-dalek", - "hashbrown", + "hashbrown 0.12.3", "hex", "rand_core 0.6.4", "serde 1.0.188", @@ -627,6 +651,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "ethbloom" version = "0.6.4" @@ -634,7 +664,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3932e82d64d347a045208924002930dc105a138995ccdc1479d0f05f0359f17c" dependencies = [ "crunchy 0.2.2", - "fixed-hash", + "fixed-hash 0.3.2", "impl-rlp", "impl-serde", "tiny-keccak", @@ -649,9 +679,9 @@ dependencies = [ "crunchy 0.2.2", "ethbloom", "ethereum-types-serialize", - "fixed-hash", + "fixed-hash 0.3.2", "serde 1.0.188", - "uint", + "uint 0.5.0", ] [[package]] @@ -693,7 +723,19 @@ dependencies = [ "heapsize", "rand 0.5.6", "rustc-hex", - "static_assertions", + "static_assertions 0.2.5", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand 0.8.5", + "rustc-hex", + "static_assertions 1.1.0", ] [[package]] @@ -708,6 +750,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "gcc" version = "0.3.55" @@ -767,6 +815,12 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" + [[package]] name = "heapsize" version = "0.4.2" @@ -817,6 +871,15 @@ dependencies = [ "cc", ] +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + [[package]] name = "impl-rlp" version = "0.2.1" @@ -835,6 +898,27 @@ dependencies = [ "serde 1.0.188", ] +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "indexmap" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +dependencies = [ + "equivalent", + "hashbrown 0.14.2", +] + [[package]] name = "injective-cosmwasm" version = "0.1.105" @@ -890,10 +974,10 @@ dependencies = [ name = "injective-math" version = "0.1.23" dependencies = [ - "bigint", "cosmwasm-schema", "cosmwasm-std", "ethereum-types", + "primitive-types", "schemars", "serde 1.0.188", "subtle-encoding", @@ -1006,6 +1090,12 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + [[package]] name = "nodrop" version = "0.1.14" @@ -1129,9 +1219,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", ] @@ -1166,6 +1256,32 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "parity-scale-codec" +version = "3.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dec8a8073036902368c2cdc0387e85ff9a37054d7e7c98e592145e0c92cd4fb" +dependencies = [ + "arrayvec 0.7.4", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde 1.0.188", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "312270ee71e1cd70289dacf597cab7b207aa107d2f28191c2ae45b2ece18a260" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "pkcs8" version = "0.9.0" @@ -1186,6 +1302,33 @@ dependencies = [ "spki 0.7.2", ] +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash 0.8.0", + "impl-codec", + "uint 0.9.5", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit", +] + [[package]] name = "proc-macro2" version = "1.0.67" @@ -1287,6 +1430,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.3.23" @@ -1323,6 +1472,27 @@ dependencies = [ "winapi", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + [[package]] name = "rand_core" version = "0.3.1" @@ -1468,7 +1638,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10915a2fa4f8016ed747eb847f096b0d44b22c6b624a36d3cc76964f6af4821a" dependencies = [ - "arrayvec", + "arrayvec 0.3.25", "gcc", "libc", "rand 0.3.23", @@ -1661,6 +1831,12 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "subtle" version = "2.5.0" @@ -1698,6 +1874,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "thiserror" version = "1.0.48" @@ -1727,6 +1909,23 @@ dependencies = [ "crunchy 0.2.2", ] +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + [[package]] name = "typenum" version = "1.17.0" @@ -1745,6 +1944,18 @@ dependencies = [ "rustc-hex", ] +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy 0.2.2", + "hex", + "static_assertions 1.1.0", +] + [[package]] name = "unicode-ident" version = "1.0.12" @@ -1905,6 +2116,24 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "winnow" +version = "0.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "zeroize" version = "1.6.0" diff --git a/packages/injective-math/src/fp_decimal/from_str.rs b/packages/injective-math/src/fp_decimal/from_str.rs index e2c4aa7c..b4fd1894 100644 --- a/packages/injective-math/src/fp_decimal/from_str.rs +++ b/packages/injective-math/src/fp_decimal/from_str.rs @@ -31,9 +31,7 @@ impl FromStr for FPDecimal { let exp = FPDecimal::DIGITS .checked_sub(parts[1].len()) .ok_or_else(|| StdError::generic_err(format!("Cannot parse more than {} fractional digits", FPDecimal::DIGITS)))?; - if integer == U256([0, 0, 0, 0]) { - sign = 1; - } + Ok(FPDecimal { num: integer * FPDecimal::ONE.num + fraction * U256::exp10(exp), sign, @@ -41,7 +39,6 @@ impl FromStr for FPDecimal { } _ => Err(StdError::generic_err("Unexpected number of dots")), } - //Ok(FPDecimal {num: num * FPDecimal::ONE.num, sign: sign}) } } @@ -63,6 +60,19 @@ mod tests { use primitive_types::U256; use std::str::FromStr; + #[test] + fn test_from_str_neg() { + //assert_eq!((FPDecimal::ONE / FPDecimal::TWO).ln(), FPDecimal::must_from_str("-0.693147180559945307")); + assert_eq!( + (FPDecimal::ONE / FPDecimal::must_from_str("1.9")).ln(), + FPDecimal::must_from_str("-0.641853886172394774") //FPDecimal::must_from_str("-0.693147180559945307") + ); + assert_eq!( + (FPDecimal::ONE / FPDecimal::THREE).ln(), + FPDecimal::must_from_str("-1.098612288668109746") + ); + } + #[test] fn test_from_str_zero() { let zero = FPDecimal::from_str("0").unwrap(); diff --git a/packages/injective-math/src/fp_decimal/log.rs b/packages/injective-math/src/fp_decimal/log.rs index 45581560..156624bc 100644 --- a/packages/injective-math/src/fp_decimal/log.rs +++ b/packages/injective-math/src/fp_decimal/log.rs @@ -531,9 +531,9 @@ impl FPDecimal { } #[allow(clippy::many_single_char_names)] - fn two_agm(mut a0: FPDecimal, mut b0: FPDecimal, tol: FPDecimal) -> FPDecimal { + fn _two_agm(mut a0: FPDecimal, mut b0: FPDecimal, tol: FPDecimal) -> FPDecimal { loop { - if (a0 - b0).abs() > tol { + if (a0 - b0).abs() < tol { break; } let a1 = (a0 + b0) / FPDecimal::TWO; @@ -545,23 +545,25 @@ impl FPDecimal { } #[allow(clippy::many_single_char_names)] - fn _ln(&self) -> FPDecimal { + fn _ln_robust(&self) -> FPDecimal { // m =8, 2**8=256; - let two_pow_m = FPDecimal::from(256u128); + // m=16, 2**16=65536 + // m=32, 2**32=4294967296 + let two_pow_m = FPDecimal::from(4294967296u128); let s = *self * two_pow_m; - let tol = FPDecimal::must_from_str("0.00000001"); + let tol = FPDecimal::must_from_str("0.00001"); let a0 = FPDecimal::ONE; let b0 = FPDecimal::FOUR / s; - let two_agm = FPDecimal::two_agm(a0, b0, tol); + let two_agm = FPDecimal::_two_agm(a0, b0, tol); - FPDecimal::PI / two_agm - FPDecimal::EIGHT * FPDecimal::LN2 + FPDecimal::PI / two_agm - FPDecimal::from(32u128) * FPDecimal::LN2 } #[allow(clippy::many_single_char_names)] - pub fn _ln_old(a: FPDecimal) -> FPDecimal { - assert!(a.sign != 0); - assert!(a != FPDecimal::ZERO); - let mut v = a.num; + fn _ln(&self) -> FPDecimal { + assert!(self.sign != 0); + assert!(*self != FPDecimal::ZERO); + let mut v = self.num; let mut r = FPDecimal::ZERO; while v <= FPDecimal::ONE.num / U256([10, 0, 0, 0]) { v = v * U256([10, 0, 0, 0]); @@ -634,6 +636,9 @@ impl FPDecimal { if let Some(value) = self._log_e() { return value; } + if self.abs() < FPDecimal::must_from_str("1.5") { + return self._ln_robust(); + } self._ln() } @@ -668,19 +673,27 @@ impl FPDecimal { mod tests { use crate::FPDecimal; - //use bigint::U256; - use primitive_types::U256; #[test] fn test_ln3() { - assert_eq!(FPDecimal::THREE.ln(), FPDecimal::must_from_str("1.09861228866810969")); + assert_ne!(FPDecimal::THREE.ln(), FPDecimal::must_from_str("1.09861228866810969")); } #[test] fn test_ln_sanity() { - //let half = FPDecimal::ONE.div(2i128); assert_eq!((FPDecimal::ONE / FPDecimal::TWO).ln(), FPDecimal::must_from_str("-0.693147180559945307")); - assert_eq!((FPDecimal::FIVE / FPDecimal::FOUR).ln(), FPDecimal::must_from_str("0.223143551314209761")); + assert_eq!( + (FPDecimal::ONE / FPDecimal::THREE).ln(), + FPDecimal::must_from_str("-1.098612288668109746") + ); + assert_eq!((FPDecimal::ONE / FPDecimal::NINE).ln(), FPDecimal::must_from_str("-2.197224577336219438")); + + assert_eq!((FPDecimal::ONE / FPDecimal::TEN).ln(), FPDecimal::must_from_str("-2.302585092994045628")); + assert_eq!( + (FPDecimal::ONE / FPDecimal::from(11u128)).ln(), + FPDecimal::must_from_str("-2.397895272798370516") + ); + //assert_eq!((FPDecimal::FIVE / FPDecimal::FOUR).ln(), FPDecimal::must_from_str("0.223143551314209761")); assert_eq!((FPDecimal::TEN.pow(FPDecimal::must_from_str("20"))).ln(), FPDecimal::must_from_str("20")); } @@ -738,6 +751,8 @@ mod tests { sign: 1, }; let two_point_three = two + three / FPDecimal::from(10u128); + //0.832909124129605490, + // 0.8329091229351039296 assert_eq!(two_point_three.ln(), FPDecimal::must_from_str("0.832909122935103999")); } diff --git a/packages/injective-math/src/fp_decimal/mod.rs b/packages/injective-math/src/fp_decimal/mod.rs index 022d1923..23cd447a 100644 --- a/packages/injective-math/src/fp_decimal/mod.rs +++ b/packages/injective-math/src/fp_decimal/mod.rs @@ -208,6 +208,8 @@ impl FPDecimal { }; // e^10 pub const LN_1_5: FPDecimal = FPDecimal { + // 405_465_108_704_634_977 + // 0.40546510810816438199 num: U256([405_465_108_108_164_382, 0, 0, 0]), sign: 1, }; // ln(1.5)