Skip to content
Snippets Groups Projects

Dynamic Constant Math

Merged Aaron Councilman requested to merge dyn_const_math into main
1 unresolved thread
1 file
+ 38
34
Compare changes
  • Side-by-side
  • Inline
@@ -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)
}
}
}
Loading