// We handle the structs a bit different here. Firstly, we ignore both the sign/scale of d2. // This is because during a remainder operation we do not care about the sign of the divisor // and only concern ourselves with that of the dividend. letmut d1 = Dec64::new(d1); let d2_scale = d2.scale(); letmut d2 = Buf12::from_decimal(d2);
let cmp = crate::ops::cmp::cmp_internal(
&d1,
&Dec64 {
negative: d1.negative,
scale: d2_scale,
hi: d2.hi(),
low64: d2.low64(),
},
); match cmp {
core::cmp::Ordering::Equal => { // Same numbers meaning that remainder is zero return CalculationResult::Ok(Decimal::ZERO);
}
core::cmp::Ordering::Less => { // d1 < d2, e.g. 1/2. This means that the result is the value of d1 return CalculationResult::Ok(d1.to_decimal());
}
core::cmp::Ordering::Greater => {}
}
// At this point we know that the dividend > divisor and that they are both non-zero. letmut scale = d1.scale as i32 - d2_scale as i32; if scale > 0 { // Scale up the divisor loop { let power = if scale >= MAX_I32_SCALE {
POWERS_10[9]
} else {
POWERS_10[scale as usize]
} as u64;
letmut tmp = d2.lo() as u64 * power;
d2.set_lo(tmp as u32);
tmp >>= 32;
tmp = tmp.wrapping_add((d2.mid() as u64 + ((d2.hi() as u64) << 32)) * power);
d2.set_mid(tmp as u32);
d2.set_hi((tmp >> 32) as u32);
// Keep scaling if there is more to go
scale -= MAX_I32_SCALE; if scale <= 0 { break;
}
}
scale = 0;
}
loop { // If the dividend is smaller than the divisor then try to scale that up first if scale < 0 { letmut quotient = Buf12 {
data: [d1.lo(), d1.mid(), d1.hi],
}; loop { // Figure out how much we can scale by let power_scale; iflet Some(u) = quotient.find_scale(MAX_PRECISION_I32 + scale) { if u >= POWERS_10.len() {
power_scale = 9;
} else {
power_scale = u;
}
} else { return CalculationResult::Overflow;
}; if power_scale == 0 { break;
} let power = POWERS_10[power_scale] as u64;
scale += power_scale as i32;
// First normalize the divisor let shift = if d2.hi() == 0 {
d2.mid().leading_zeros()
} else {
d2.hi().leading_zeros()
};
letmut buffer = Buf24::zero(); letmut overflow = 0u32;
buffer.set_low64(d1.low64 << shift);
buffer.set_mid64(((d1.mid() as u64).wrapping_add((d1.hi as u64) << 32)) >> (32 - shift)); letmut upper = 3; // We start at 3 due to bit shifting
while scale < 0 { let power = if -scale >= MAX_I32_SCALE {
POWERS_10[9]
} else {
POWERS_10[-scale as usize]
} as u64; letmut tmp64 = buffer.data[0] as u64 * power;
buffer.data[0] = tmp64 as u32;
for (index, part) in buffer.data.iter_mut().enumerate().skip(1) { if index > upper { break;
}
tmp64 >>= 32;
tmp64 = tmp64.wrapping_add((*part as u64).wrapping_mul(power));
*part = tmp64 as u32;
} // If we have overflow then also process that if upper == 6 {
tmp64 >>= 32;
tmp64 = tmp64.wrapping_add((overflow as u64).wrapping_mul(power));
overflow = tmp64 as u32;
}
// Make sure the high bit is not set if tmp64 > 0x7FFF_FFFF {
upper += 1; if upper > 5 {
overflow = (tmp64 >> 32) as u32;
} else {
buffer.data[upper] = (tmp64 >> 32) as u32;
}
}
scale += MAX_I32_SCALE;
}
// TODO: Optimize slice logic
letmut tmp = Buf16::zero(); let divisor = d2.low64() << shift; if d2.hi() == 0 { // Do some division if upper == 6 {
upper -= 1;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.