Path: blob/main/crates/polars-compute/src/cast/decimal_to.rs
8446 views
use arrow::array::*;1use arrow::datatypes::ArrowDataType;2use arrow::types::NativeType;3use num_traits::{AsPrimitive, Float, NumCast};4use polars_error::PolarsResult;56use crate::decimal::{dec128_fits, dec128_rescale, dec128_to_f64, dec128_to_i128};78/// Returns a [`PrimitiveArray<i128>`] with the cast values. Values become null on overflow.9pub fn decimal_to_decimal(10from: &PrimitiveArray<i128>,11to_precision: usize,12to_scale: usize,13) -> PrimitiveArray<i128> {14let (from_precision, from_scale) =15if let ArrowDataType::Decimal(p, s) = from.dtype().to_storage() {16(*p, *s)17} else {18panic!("internal error: i128 is always a decimal")19};2021if to_scale == from_scale {22if to_precision >= from_precision {23// Increasing precision is always allowed.24return from25.clone()26.to(ArrowDataType::Decimal(to_precision, to_scale));27} else {28let it = from29.iter()30.map(|opt_x| opt_x.copied().filter(|x| dec128_fits(*x, to_precision)));31return PrimitiveArray::<i128>::from_trusted_len_iter(it)32.to(ArrowDataType::Decimal(to_precision, to_scale));33}34}3536let it = from37.iter()38.map(|opt_x| dec128_rescale(*(opt_x?), from_scale, to_precision, to_scale));39PrimitiveArray::<i128>::from_trusted_len_iter(it)40.to(ArrowDataType::Decimal(to_precision, to_scale))41}4243pub(super) fn decimal_to_decimal_dyn(44from: &dyn Array,45to_precision: usize,46to_scale: usize,47) -> PolarsResult<Box<dyn Array>> {48let from = from.as_any().downcast_ref().unwrap();49Ok(Box::new(decimal_to_decimal(from, to_precision, to_scale)))50}5152/// Returns a [`PrimitiveArray<i128>`] with the cast values. Values are `None` on overflow53pub fn decimal_to_float<T>(from: &PrimitiveArray<i128>) -> PrimitiveArray<T>54where55T: NativeType + Float,56f64: AsPrimitive<T>,57{58let (_, from_scale) = if let ArrowDataType::Decimal(p, s) = from.dtype().to_storage() {59(*p, *s)60} else {61unreachable!()62};6364let it = from65.iter()66.map(|opt_x| Some(dec128_to_f64(*(opt_x?), from_scale).as_()));67PrimitiveArray::<T>::from_trusted_len_iter(it)68}6970pub(super) fn decimal_to_float_dyn<T>(from: &dyn Array) -> PolarsResult<Box<dyn Array>>71where72T: NativeType + Float,73f64: AsPrimitive<T>,74{75let from = from.as_any().downcast_ref().unwrap();76Ok(Box::new(decimal_to_float::<T>(from)))77}7879/// Returns a [`PrimitiveArray<i128>`] with the cast values. Values are `None` on overflow80pub fn decimal_to_integer<T>(from: &PrimitiveArray<i128>) -> PrimitiveArray<T>81where82T: NativeType + NumCast,83{84let (_, from_scale) = if let ArrowDataType::Decimal(p, s) = from.dtype().to_storage() {85(*p, *s)86} else {87unreachable!()88};8990let it = from91.iter()92.map(|opt_x| T::from(dec128_to_i128(*(opt_x?), from_scale)));93PrimitiveArray::<T>::from_trusted_len_iter(it)94}9596pub(super) fn decimal_to_integer_dyn<T>(from: &dyn Array) -> PolarsResult<Box<dyn Array>>97where98T: NativeType + NumCast,99{100let from = from.as_any().downcast_ref().unwrap();101Ok(Box::new(decimal_to_integer::<T>(from)))102}103104/// Returns a [`Utf8Array`] where every element is the utf8 representation of the decimal.105#[cfg(feature = "dtype-decimal")]106pub(super) fn decimal_to_utf8view(from: &PrimitiveArray<i128>) -> Utf8ViewArray {107use crate::decimal::DecimalFmtBuffer;108109let (_, from_scale) = if let ArrowDataType::Decimal(p, s) = from.dtype().to_storage() {110(*p, *s)111} else {112unreachable!()113};114115let mut mutable = MutableBinaryViewArray::with_capacity(from.len());116let mut fmt_buf = DecimalFmtBuffer::new();117for &x in from.values().iter() {118mutable.push_value_ignore_validity(fmt_buf.format_dec128(x, from_scale, false, false))119}120121mutable.freeze().with_validity(from.validity().cloned())122}123124#[cfg(feature = "dtype-decimal")]125pub(super) fn decimal_to_utf8view_dyn(from: &dyn Array) -> Utf8ViewArray {126let from = from.as_any().downcast_ref().unwrap();127decimal_to_utf8view(from)128}129130131