Skip to content

Commit cb98492

Browse files
committed
feat(rug): fractional powers without roots
1 parent bccc2fc commit cb98492

File tree

5 files changed

+147
-88
lines changed

5 files changed

+147
-88
lines changed

Cargo.lock

Lines changed: 106 additions & 38 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/chain-libs/chain-impl-mockchain/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ criterion = { version = "0.3.0", optional = true }
3232
rand = "0.8"
3333
cryptoxide = "0.4"
3434
tracing.workspace = true
35-
bigdecimal = "~0.2"
36-
bigdecimalmath = "0.1.0"
35+
rug = "1.26.1"
3736
num = "0.4.3"
3837

3938

src/chain-libs/chain-impl-mockchain/src/vote/tally.rs

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ use crate::{
33
value::Value,
44
vote::{Choice, Options},
55
};
6-
use bigdecimal::BigDecimal;
76

8-
use bigdecimal::ToPrimitive;
9-
use bigdecimalmath::root;
107
use chain_vote::EncryptedTally;
11-
8+
use core::cmp::Ordering;
129
use num::FromPrimitive;
10+
1311
use num::Rational32;
12+
use rug::Integer;
13+
use rug::{float::Round, ops::Pow, Float, Rational};
1414

1515
use std::str::FromStr;
1616

@@ -178,24 +178,28 @@ impl TallyResult {
178178
let index = choice.as_byte() as usize;
179179

180180
const GAMMA: &str = "QUADRATIC_VOTING_GAMMA";
181+
const PRECISION: &str = "QUADRATIC_VOTING_PRECISION";
181182

182183
// Apply quadratic scaling if gamma value specified in env var. Else gamma is 1 and has no effect.
183184
let gamma = f64::from_str(&env::var(GAMMA).unwrap_or(1.0.to_string())).unwrap();
184185

186+
let precision =
187+
u32::from_str(&env::var(PRECISION).unwrap_or(1.to_string())).unwrap_or(1);
188+
185189
let gamma = Rational32::from_f64(gamma).unwrap_or(Rational32::from_integer(1));
186-
let denom = isize::try_from(*gamma.denom()).unwrap();
190+
let denom = gamma.denom();
187191
let numer = gamma.numer();
188192

189-
// stake
190-
let base = BigDecimal::from(weight.0);
191-
192-
// m-th power, then take the n-th root: where x^(m/n)
193-
// mth power equals x^m where m in the numerator
194-
let mth_power = self.pow_fractional_exponent(&base, *numer);
193+
let stake = Float::with_val(precision, weight.0);
194+
// r = gamma in rational form
195+
let exp_r = Rational::from((*numer, *denom));
196+
let exp_f = Float::with_val(precision, &exp_r);
197+
let p = stake.clone().pow(&exp_f);
195198

196-
// nth root
197-
let weight = root(denom, mth_power)
198-
.unwrap_or(base.clone())
199+
let weight = p
200+
.to_integer_round(Round::Down)
201+
.unwrap_or((Integer::from(weight.0), Ordering::Less))
202+
.0
199203
.to_u64()
200204
.unwrap_or(weight.0);
201205

@@ -204,13 +208,6 @@ impl TallyResult {
204208
Ok(())
205209
}
206210
}
207-
208-
fn pow_fractional_exponent(&self, x: &BigDecimal, n: i32) -> BigDecimal {
209-
let (bigint, scale) = x.as_bigint_and_exponent();
210-
let new_scale = scale * n as i64;
211-
212-
BigDecimal::new(bigint.pow(n as u32), new_scale)
213-
}
214211
}
215212

216213
impl From<Stake> for Weight {

src/chain-libs/chain-vote/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ thiserror = "1.0"
1414
cryptoxide = "^0.4.2"
1515
const_format = "0.2"
1616
base64 = "0.21.0"
17-
bigdecimal = "~0.2"
18-
bigdecimalmath = "0.1.0"
17+
rug = "1.26.1"
1918
num = "0.4.3"
2019
tracing = "*"
2120

0 commit comments

Comments
 (0)