From 29d969f6f257a107b912fa895e219aececee4240 Mon Sep 17 00:00:00 2001 From: Aaron Councilman <aaronjc4@illinois.edu> Date: Wed, 25 Sep 2024 15:28:15 -0500 Subject: [PATCH] Fixes to dynamic constant generation from Juno --- juno_frontend/src/dynconst.rs | 72 ++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 34 deletions(-) diff --git a/juno_frontend/src/dynconst.rs b/juno_frontend/src/dynconst.rs index 72a9d0ff..ba726299 100644 --- a/juno_frontend/src/dynconst.rs +++ b/juno_frontend/src/dynconst.rs @@ -256,16 +256,29 @@ impl DynConst { .collect::<Vec<_>>(); non_zero_coeff.sort_by(|(d1, _), (d2, _)| d1.cmp(d2)); - non_zero_coeff.iter().map(|(d, c)| self.build_mono(builder, d, c)) - .collect::<Vec<_>>().into_iter() - .reduce(|x, y| builder.create_dynamic_constant_add(x, y)) - // If there are no terms, this dynamic constant is 0 - .unwrap_or_else(|| builder.create_dynamic_constant_constant(0)) + let (pos, neg) : (Vec<_>, Vec<_>) = + non_zero_coeff.iter() + .map(|(d, c)| self.build_mono(builder, d, c)) + .partition(|(_, neg)| ! *neg); + + let pos_sum = pos.into_iter().map(|(t, _)| t) + .reduce(|x, y| builder.create_dynamic_constant_add(x, y)) + .unwrap_or_else(|| builder.create_dynamic_constant_constant(0)); + + let neg_sum = neg.into_iter().map(|(t, _)| t) + .reduce(|x, y| builder.create_dynamic_constant_add(x, y)); + + match neg_sum { + None => pos_sum, + Some(neg) => builder.create_dynamic_constant_sub(pos_sum, neg) + } } // Build's a monomial, with a given list of powers (term) and coefficients + // Returns the dynamic constant id of the positive value and a boolean + // indicating whether the value should actually be negative fn build_mono(&self, builder : &mut Builder, term : &Vec<i64>, - coeff : &Ratio<i64>) -> DynamicConstantID { + coeff : &Ratio<i64>) -> (DynamicConstantID, bool) { let term_id = term.iter().enumerate() .filter(|(_, p)| **p != 0) .map(|(v, p)| self.build_power(builder, v, *p)) @@ -279,20 +292,30 @@ impl DynConst { panic!("Dynamic constant is a non-integer constant") } else { let val : i64 = coeff.to_integer(); - if val < 0 { - panic!("Dynamic constant is a negative constant") - } else { - builder.create_dynamic_constant_constant(val as usize) - } + (builder.create_dynamic_constant_constant(val.abs() as usize), + val < 0) } }, Some(term) => { - if coeff.is_one() { term } + if coeff.is_one() { (term, false) } else { - let numer : i64 = *coeff.numer(); + let numer : i64 = coeff.numer().abs(); let denom : i64 = *coeff.denom(); // > 0 - let coeff_id = self.build_coeff(builder, numer, denom); - builder.create_dynamic_constant_mul(coeff_id, term) + + let with_numer = + if numer == 1 { term } + else { + let numer_id = builder.create_dynamic_constant_constant(numer as usize); + builder.create_dynamic_constant_mul(numer_id, term) + }; + let with_denom = + if denom == 1 { with_numer } + else { + let denom_id = builder.create_dynamic_constant_constant(denom as usize); + builder.create_dynamic_constant_div(with_numer, denom_id) + }; + + (with_denom, numer < 0) } }, } @@ -316,23 +339,4 @@ impl DynConst { builder.create_dynamic_constant_div(one_id, power_id) } } - - // Build's a dynamic constant that is a certain rational number (n / d) - fn build_coeff(&self, builder : &mut Builder, n : i64, d : i64) -> DynamicConstantID { - assert!(n != 0); assert!(d > 0); - - let n_abs_term = builder.create_dynamic_constant_constant(n.abs() as usize); - let n_term = - if n > 0 { n_abs_term } - else { - let zero_term = builder.create_dynamic_constant_constant(0); - builder.create_dynamic_constant_sub(zero_term, n_abs_term) - }; - - if d == 1 { n_term } - else { - let d_term = builder.create_dynamic_constant_constant(d as usize); - builder.create_dynamic_constant_div(n_term, d_term) - } - } } -- GitLab