pub fn adaptive_mul(
    lhs: &PrimitiveArray<i128>,
    rhs: &PrimitiveArray<i128>,
) -> Result<PrimitiveArray<i128>> {
    check_same_len(lhs, rhs)?;

    if let (DataType::Decimal(lhs_p, lhs_s), DataType::Decimal(rhs_p, rhs_s)) =
        (lhs.data_type(), rhs.data_type())
    {
        // The resulting precision is mutable because it could change while
        // looping through the iterator
        let (mut res_p, res_s, diff) = adjusted_precision_scale(*lhs_p, *lhs_s, *rhs_p, *rhs_s);

        let shift = 10i128.pow(diff as u32);
        let shift_1 = 10i128.pow(res_s as u32);
        let mut max = max_value(res_p);

        let iter = lhs.values().iter().zip(rhs.values().iter()).map(|(l, r)| {
            // Based on the array's scales one of the arguments in the sum has to be shifted
            // to the left to match the final scale
            let res = if lhs_s > rhs_s {
                l.checked_mul(r * shift)
            } else {
                (l * shift).checked_mul(*r)
            }
            .expect("Mayor overflow for multiplication");

            let res = res / shift_1;

            // The precision of the resulting array will change if one of the
            // multiplications during the iteration produces a value bigger
            // than the possible value for the initial precision

            //  10.0000 -> 6, 4
            //  10.0000 -> 6, 4
            // -----------------
            // 100.0000 -> 7, 4
            if res.abs() > max {
                res_p = number_digits(res);
                max = max_value(res_p);
            }

            res
        });
        let values = Buffer::from_trusted_len_iter(iter);

        let validity = combine_validities(lhs.validity(), rhs.validity());

        Ok(PrimitiveArray::<i128>::from_data(
            DataType::Decimal(res_p, res_s),
            values,
            validity,
        ))
    } else {
        Err(ArrowError::InvalidArgumentError(
            "Incorrect data type for the array".to_string(),
        ))
    }
}
/// Adaptive multiplication of two decimal primitive arrays with different
/// precision and scale. If the precision and scale is different, then the
/// smallest scale and precision is adjusted to the largest precision and
/// scale. If during the multiplication one of the results is larger than the
/// max possible value, the result precision is changed to the precision of the
/// max value
///
/// ```nocode
///   11111.0    -> 6, 1
///      10.002  -> 5, 3
/// -----------------
///  111132.222  -> 9, 3
/// ```
/// # Examples
/// ```
/// use arrow2::compute::arithmetics::decimal::adaptive_mul;
/// use arrow2::array::PrimitiveArray;
/// use arrow2::datatypes::DataType;
///
/// let a = PrimitiveArray::from([Some(11111_0i128), Some(1_0i128)]).to(DataType::Decimal(6, 1));
/// let b = PrimitiveArray::from([Some(10_002i128), Some(2_000i128)]).to(DataType::Decimal(5, 3));
/// let result = adaptive_mul(&a, &b).unwrap();
/// let expected = PrimitiveArray::from([Some(111132_222i128), Some(2_000i128)]).to(DataType::Decimal(9, 3));
///
/// assert_eq!(result, expected);
/// ```
Adaptive multiplication of two decimal primitive arrays with different
precision and scale. If the precision and scale is different, then the
smallest scale and precision is adjusted to the largest precision and
scale. If during the multiplication one of the results is larger than the
max possible value, the result precision is changed to the precision of the
max value




Adaptive multiplication of two decimal primitive arrays with different precision and scale . If the precision and scale is different then the smallest scale and precision is adjusted to the largest precision and scale . If during the multiplication one of the results is larger than the max possible value the result precision is changed to the precision of the max value
pub fn adaptive_mul(
    lhs: &PrimitiveArray<i128>,
    rhs: &PrimitiveArray<i128>,
) -> Result<PrimitiveArray<i128>> {
    check_same_len(lhs, rhs)?;
    if let (DataType::Decimal(lhs_p, lhs_s), DataType::Decimal(rhs_p, rhs_s)) =
        (lhs.data_type(), rhs.data_type())
    {
        // The resulting precision is mutable because it could change while
        // looping through the iterator
        let (mut res_p, res_s, diff) = adjusted_precision_scale(*lhs_p, *lhs_s, *rhs_p, *rhs_s);
        let shift = 10i128.pow(diff as u32);
        let shift_1 = 10i128.pow(res_s as u32);
        let mut max = max_value(res_p);
        let iter = lhs.values().iter().zip(rhs.values().iter()).map(|(l, r)| {
            // Based on the array's scales one of the arguments in the sum has to be shifted
            // to the left to match the final scale
            let res = if lhs_s > rhs_s {
                l.checked_mul(r * shift)
            } else {
                (l * shift).checked_mul(*r)
            }
            .expect("Mayor overflow for multiplication");
            let res = res / shift_1;
            // The precision of the resulting array will change if one of the
            // multiplications during the iteration produces a value bigger
            // than the possible value for the initial precision
            //  10.0000 -> 6, 4
            //  10.0000 -> 6, 4
            // -----------------
            // 100.0000 -> 7, 4
            if res.abs() > max {
                res_p = number_digits(res);
                max = max_value(res_p);
            }
            res
        });
        let values = Buffer::from_trusted_len_iter(iter);
        let validity = combine_validities(lhs.validity(), rhs.validity());
        Ok(PrimitiveArray::<i128>::from_data(
            DataType::Decimal(res_p, res_s),
            values,
            validity,
        ))
    } else {
        Err(ArrowError::InvalidArgumentError(
            "Incorrect data type for the array".to_string(),
        ))
    }
}
pub fn adaptive_mul ( lhs : & PrimitiveArray < i128 > , rhs : & PrimitiveArray < i128 > , ) -> Result < PrimitiveArray < i128 > > { check_same_len ( lhs , rhs ) ? ; if let ( DataType :: Decimal ( lhs_p , lhs_s ) , DataType :: Decimal ( rhs_p , rhs_s ) ) = ( lhs . data_type ( ) , rhs . data_type ( ) ) { // The resulting precision is mutable because it could change while // looping through the iterator let ( mut res_p , res_s , diff ) = adjusted_precision_scale ( * lhs_p , * lhs_s , * rhs_p , * rhs_s ) ; let shift = 10i128 . pow ( diff as u32 ) ; let shift_1 = 10i128 . pow ( res_s as u32 ) ; let mut max = max_value ( res_p ) ; let iter = lhs . values ( ) . iter ( ) . zip ( rhs . values ( ) . iter ( ) ) . map ( | ( l , r ) | { // Based on the array's scales one of the arguments in the sum has to be shifted // to the left to match the final scale let res = if lhs_s > rhs_s { l . checked_mul ( r * shift ) } else { ( l * shift ) . checked_mul ( * r ) } . expect ( " " ) ; let res = res / shift_1 ; // The precision of the resulting array will change if one of the // multiplications during the iteration produces a value bigger // than the possible value for the initial precision //  10.0000 -> 6, 4 //  10.0000 -> 6, 4 // ----------------- // 100.0000 -> 7, 4 if res . abs ( ) > max { res_p = number_digits ( res ) ; max = max_value ( res_p ) ; } res } ) ; let values = Buffer :: from_trusted_len_iter ( iter ) ; let validity = combine_validities ( lhs . validity ( ) , rhs . validity ( ) ) ; Ok ( PrimitiveArray :: < i128 > :: from_data ( DataType :: Decimal ( res_p , res_s ) , values , validity , ) ) } else { Err ( ArrowError :: InvalidArgumentError ( " " . to_string ( ) , ) ) } }
Adaptive multiplication of two decimal primitive arrays with different
precision and scale.
Adaptive multiplication of two decimal primitive arrays with different precision and scale .
lhs
&PrimitiveArray<i128>
rhs
&PrimitiveArray<i128>
lhs
&PrimitiveArray<i128>
rhs
&PrimitiveArray<i128>
examples
```
use arrow2::compute::arithmetics::decimal::adaptive_mul;
use arrow2::array::PrimitiveArray;
use arrow2::datatypes::DataType.



assert_eq!(result, expected);
```
` ` ` use arrow2 :: compute :: arithmetics :: decimal :: adaptive_mul ; use arrow2 :: array :: PrimitiveArray ; use arrow2 :: datatypes :: DataType . assert_eq! ( result expected ) ; ` ` `