33use crate :: alloc:: borrow:: ToOwned ;
44#[ allow( unused) ]
55use num_traits:: float:: Float ;
6- use sp_runtime:: traits:: CheckedAdd ;
6+ use sp_runtime:: traits:: { CheckedAdd , Saturating } ;
77use sp_std:: cmp:: Ordering ;
88
99use sp_std:: vec;
@@ -1161,52 +1161,59 @@ pub fn mat_ema_alpha_vec_sparse(
11611161 let n = new. len ( ) ; // Assume square matrix, rows=cols
11621162 let zero: I32F32 = I32F32 :: from_num ( 0.0 ) ;
11631163 let mut result: Vec < Vec < ( u16 , I32F32 ) > > = vec ! [ vec![ ] ; n] ;
1164+
11641165 // Iterate over each row of the matrices.
1165- for i in 0 ..new . len ( ) {
1166+ for ( i , ( new_row , old_row ) ) in new . iter ( ) . zip ( old ) . enumerate ( ) {
11661167 // Initialize a row of zeros for the result matrix.
11671168 let mut row: Vec < I32F32 > = vec ! [ zero; n] ;
11681169
11691170 // Process the new matrix values.
1170- for ( j, value) in new [ i ] . iter ( ) {
1171+ for ( j, value) in new_row . iter ( ) {
11711172 // Retrieve the alpha value for the current column.
1172- let alpha_val: I32F32 = alpha[ * j as usize ] ;
1173- // Compute the EMA component for the new value.
1174- row[ * j as usize ] = alpha_val * value;
1173+ let alpha_val: I32F32 = alpha. get ( * j as usize ) . copied ( ) . unwrap_or ( zero) ;
1174+ // Compute the EMA component for the new value using saturating multiplication.
1175+ if let Some ( row_val) = row. get_mut ( * j as usize ) {
1176+ * row_val = alpha_val. saturating_mul ( * value) ;
1177+ }
11751178 log:: trace!(
11761179 "new[{}][{}] * alpha[{}] = {} * {} = {}" ,
11771180 i,
11781181 j,
11791182 j,
11801183 value,
11811184 alpha_val,
1182- row[ * j as usize ]
1185+ row. get ( * j as usize ) . unwrap_or ( & zero )
11831186 ) ;
11841187 }
11851188
11861189 // Process the old matrix values.
1187- for ( j, value) in old [ i ] . iter ( ) {
1190+ for ( j, value) in old_row . iter ( ) {
11881191 // Retrieve the alpha value for the current column.
1189- let alpha_val: I32F32 = alpha[ * j as usize ] ;
1190- // Calculate the complement of the alpha value.
1191- let one_minus_alpha: I32F32 = I32F32 :: from_num ( 1.0 ) - alpha_val;
1192- // Compute the EMA component for the old value and add it to the row.
1193- row[ * j as usize ] += one_minus_alpha * value;
1192+ let alpha_val: I32F32 = alpha. get ( * j as usize ) . copied ( ) . unwrap_or ( zero) ;
1193+ // Calculate the complement of the alpha value using saturating subtraction.
1194+ let one_minus_alpha: I32F32 = I32F32 :: from_num ( 1.0 ) . saturating_sub ( alpha_val) ;
1195+ // Compute the EMA component for the old value and add it to the row using saturating operations.
1196+ if let Some ( row_val) = row. get_mut ( * j as usize ) {
1197+ * row_val = row_val. saturating_add ( one_minus_alpha. saturating_mul ( * value) ) ;
1198+ }
11941199 log:: trace!(
11951200 "old[{}][{}] * (1 - alpha[{}]) = {} * {} = {}" ,
11961201 i,
11971202 j,
11981203 j,
11991204 value,
12001205 one_minus_alpha,
1201- one_minus_alpha * value
1206+ one_minus_alpha. saturating_mul ( * value)
12021207 ) ;
12031208 }
12041209
12051210 // Collect the non-zero values into the result matrix.
12061211 for ( j, value) in row. iter ( ) . enumerate ( ) {
12071212 if * value > zero {
1208- result[ i] . push ( ( j as u16 , * value) ) ;
1209- log:: trace!( "result[{}][{}] = {}" , i, j, value) ;
1213+ if let Some ( result_row) = result. get_mut ( i) {
1214+ result_row. push ( ( j as u16 , * value) ) ;
1215+ log:: trace!( "result[{}][{}] = {}" , i, j, value) ;
1216+ }
12101217 }
12111218 }
12121219 }
@@ -1224,16 +1231,17 @@ pub fn mat_ema_alpha_vec(
12241231 alpha : & [ I32F32 ] ,
12251232) -> Vec < Vec < I32F32 > > {
12261233 // Check if the new matrix is empty or its first row is empty.
1227- if new. is_empty ( ) || new[ 0 ] . is_empty ( ) {
1234+ if new. is_empty ( ) || new. first ( ) . map_or ( true , |row| row . is_empty ( ) ) {
12281235 return vec ! [ vec![ ] ; 1 ] ;
12291236 }
12301237
12311238 // Ensure the dimensions of the new and old matrices match.
12321239 assert ! ( new. len( ) == old. len( ) ) ;
1233- assert ! ( new[ 0 ] . len( ) == alpha. len( ) ) ;
1240+ assert ! ( new. first ( ) . map_or ( 0 , |row| row . len( ) ) == alpha. len( ) ) ;
12341241
12351242 // Initialize the result matrix with zeros, having the same dimensions as the new matrix.
1236- let mut result: Vec < Vec < I32F32 > > = vec ! [ vec![ I32F32 :: from_num( 0.0 ) ; new[ 0 ] . len( ) ] ; new. len( ) ] ;
1243+ let mut result: Vec < Vec < I32F32 > > =
1244+ vec ! [ vec![ I32F32 :: from_num( 0.0 ) ; new. first( ) . map_or( 0 , |row| row. len( ) ) ] ; new. len( ) ] ;
12371245
12381246 // Iterate over each row of the matrices.
12391247 for ( i, ( new_row, old_row) ) in new. iter ( ) . zip ( old) . enumerate ( ) {
@@ -1242,11 +1250,19 @@ pub fn mat_ema_alpha_vec(
12421250
12431251 // Iterate over each column of the current row.
12441252 for ( j, & alpha_val) in alpha. iter ( ) . enumerate ( ) . take ( new_row. len ( ) ) {
1245- // Calculate the complement of the alpha value.
1246- let one_minus_alpha = I32F32 :: from_num ( 1.0 ) - alpha_val;
1247-
1248- // Compute the EMA for the current element.
1249- result[ i] [ j] = alpha_val * new_row[ j] + one_minus_alpha * old_row[ j] ;
1253+ // Calculate the complement of the alpha value using saturating subtraction.
1254+ let one_minus_alpha = I32F32 :: from_num ( 1.0 ) . saturating_sub ( alpha_val) ;
1255+
1256+ // Compute the EMA for the current element using saturating operations.
1257+ if let ( Some ( new_val) , Some ( old_val) , Some ( result_val) ) = (
1258+ new_row. get ( j) ,
1259+ old_row. get ( j) ,
1260+ result. get_mut ( i) . and_then ( |row| row. get_mut ( j) ) ,
1261+ ) {
1262+ * result_val = alpha_val
1263+ . saturating_mul ( * new_val)
1264+ . saturating_add ( one_minus_alpha. saturating_mul ( * old_val) ) ;
1265+ }
12501266 }
12511267 }
12521268
@@ -1271,7 +1287,7 @@ pub fn quantile(data: &[I32F32], quantile: f64) -> I32F32 {
12711287 }
12721288
12731289 // Calculate the position in the sorted array corresponding to the quantile.
1274- let pos = quantile * ( len - 1 ) as f64 ;
1290+ let pos = quantile * ( len. saturating_sub ( 1 ) ) as f64 ;
12751291
12761292 // Determine the lower index by flooring the position.
12771293 let low = pos. floor ( ) as usize ;
@@ -1281,17 +1297,26 @@ pub fn quantile(data: &[I32F32], quantile: f64) -> I32F32 {
12811297
12821298 // If the low and high indices are the same, return the value at that index.
12831299 if low == high {
1284- sorted_data[ low]
1300+ sorted_data
1301+ . get ( low)
1302+ . copied ( )
1303+ . unwrap_or_else ( || I32F32 :: from_num ( 0 ) )
12851304 } else {
12861305 // Otherwise, perform linear interpolation between the low and high values.
1287- let low_value = sorted_data[ low] ;
1288- let high_value = sorted_data[ high] ;
1306+ let low_value = sorted_data
1307+ . get ( low)
1308+ . copied ( )
1309+ . unwrap_or_else ( || I32F32 :: from_num ( 0 ) ) ;
1310+ let high_value = sorted_data
1311+ . get ( high)
1312+ . copied ( )
1313+ . unwrap_or_else ( || I32F32 :: from_num ( 0 ) ) ;
12891314
12901315 // Calculate the weight for interpolation.
12911316 let weight = I32F32 :: from_num ( pos - low as f64 ) ;
12921317
1293- // Return the interpolated value.
1294- low_value + ( high_value - low_value) * weight
1318+ // Return the interpolated value using saturating operations .
1319+ low_value. saturating_add ( ( high_value. saturating_sub ( low_value) ) . saturating_mul ( weight) )
12951320 }
12961321}
12971322
0 commit comments