polars_ops/series/ops/
eager.rs

1use polars_core::prelude::DataType;
2use polars_core::series::Series;
3use polars_error::PolarsResult;
4
5pub trait ShrinkType {
6    fn shrink_type(&self) -> PolarsResult<Series>;
7}
8
9impl ShrinkType for Series {
10    fn shrink_type(&self) -> PolarsResult<Series> {
11        if !self.dtype().is_primitive_numeric() {
12            return Ok(self.clone());
13        }
14
15        if self.dtype().is_float() {
16            return self.cast(&DataType::Float32);
17        }
18
19        if self.dtype().is_unsigned_integer() {
20            let max = self.max_reduce()?.value().extract::<u128>().unwrap_or(0);
21
22            if cfg!(feature = "dtype-u8") && max <= u8::MAX as u128 {
23                self.cast(&DataType::UInt8)
24            } else if cfg!(feature = "dtype-u16") && max <= u16::MAX as u128 {
25                self.cast(&DataType::UInt16)
26            } else if max <= u32::MAX as u128 {
27                self.cast(&DataType::UInt32)
28            } else if max <= u64::MAX as u128 {
29                self.cast(&DataType::UInt64)
30            } else {
31                Ok(self.clone())
32            }
33        } else {
34            let min = self.min_reduce()?.value().extract::<i128>().unwrap_or(0);
35            let max = self.max_reduce()?.value().extract::<i128>().unwrap_or(0);
36
37            if cfg!(feature = "dtype-i8") && min >= i8::MIN as i128 && max <= i8::MAX as i128 {
38                self.cast(&DataType::Int8)
39            } else if cfg!(feature = "dtype-i16")
40                && min >= i16::MIN as i128
41                && max <= i16::MAX as i128
42            {
43                self.cast(&DataType::Int16)
44            } else if min >= i32::MIN as i128 && max <= i32::MAX as i128 {
45                self.cast(&DataType::Int32)
46            } else if min >= i64::MIN as i128 && max <= i64::MAX as i128 {
47                self.cast(&DataType::Int64)
48            } else {
49                Ok(self.clone())
50            }
51        }
52    }
53}