MCPcopy Create free account
hub / github.com/apache/datafusion / round_decimal

Function round_decimal

datafusion/functions/src/math/round.rs:645–706  ·  view source on GitHub ↗
(
    value: V,
    input_scale: i8,
    output_scale: i8,
    decimal_places: i32,
)

Source from the content-addressed store, hash-verified

643}
644
645fn round_decimal<V: ArrowNativeTypeOp>(
646 value: V,
647 input_scale: i8,
648 output_scale: i8,
649 decimal_places: i32,
650) -> Result<V, ArrowError> {
651 let diff = i64::from(input_scale) - i64::from(decimal_places);
652 if diff <= 0 {
653 return Ok(value);
654 }
655
656 debug_assert!(diff <= i64::from(u32::MAX));
657 let diff = diff as u32;
658
659 let one = V::ONE;
660 let two = V::from_usize(2).ok_or_else(|| {
661 ArrowError::ComputeError("Internal error: could not create constant 2".into())
662 })?;
663 let ten = V::from_usize(10).ok_or_else(|| {
664 ArrowError::ComputeError("Internal error: could not create constant 10".into())
665 })?;
666
667 let factor = ten.pow_checked(diff).map_err(|_| {
668 ArrowError::ComputeError(format!(
669 "Overflow while rounding decimal with scale {input_scale} and decimal places {decimal_places}"
670 ))
671 })?;
672
673 let mut quotient = value.div_wrapping(factor);
674 let remainder = value.mod_wrapping(factor);
675
676 // `factor` is an even number (10^n, n > 0), so `factor / 2` is the tie threshold
677 let threshold = factor.div_wrapping(two);
678 if remainder >= threshold {
679 quotient = quotient.add_checked(one).map_err(|_| {
680 ArrowError::ComputeError("Overflow while rounding decimal".into())
681 })?;
682 } else if remainder <= threshold.neg_wrapping() {
683 quotient = quotient.sub_checked(one).map_err(|_| {
684 ArrowError::ComputeError("Overflow while rounding decimal".into())
685 })?;
686 }
687
688 // `quotient` is the rounded value at scale `decimal_places`. Rescale to the desired
689 // `output_scale` (which is always >= `decimal_places` in cases where diff > 0).
690 let scale_shift = i64::from(output_scale) - i64::from(decimal_places);
691 if scale_shift == 0 {
692 return Ok(quotient);
693 }
694
695 debug_assert!(scale_shift > 0);
696 debug_assert!(scale_shift <= i64::from(u32::MAX));
697 let scale_shift = scale_shift as u32;
698 let shift_factor = ten.pow_checked(scale_shift).map_err(|_| {
699 ArrowError::ComputeError(format!(
700 "Overflow while rounding decimal with scale {input_scale} and decimal places {decimal_places}"
701 ))
702 })?;

Callers 1

round_decimal_or_zeroFunction · 0.70

Calls 4

add_checkedMethod · 0.80
sub_checkedMethod · 0.80
mul_checkedMethod · 0.80
intoMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…