@@ -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;
107use chain_vote:: EncryptedTally ;
11-
8+ use core :: cmp :: Ordering ;
129use num:: FromPrimitive ;
10+
1311use num:: Rational32 ;
12+ use rug:: Integer ;
13+ use rug:: { float:: Round , ops:: Pow , Float , Rational } ;
1414
1515use 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
216213impl From < Stake > for Weight {
0 commit comments