Path: blob/main/crates/polars-expr/src/dispatch/range/int_range.rs
7884 views
use polars_core::prelude::*;1use polars_core::with_match_physical_integer_polars_type;2use polars_ops::series::new_int_range;34use super::utils::{ensure_items_contain_exactly_one_value, numeric_ranges_impl_broadcast};56const CAPACITY_FACTOR: usize = 5;78pub(super) fn int_range(s: &[Column], step: i64, dtype: DataType) -> PolarsResult<Column> {9let start = &s[0];10let end = &s[1];11let name = start.name();1213ensure_items_contain_exactly_one_value(&[start, end], &["start", "end"])?;1415// Done by type coercion16assert!(dtype.is_integer());17assert_eq!(start.dtype(), &dtype);18assert_eq!(end.dtype(), &dtype);1920with_match_physical_integer_polars_type!(dtype, |$T| {21let start_v = get_first_series_value::<$T>(start)?;22let end_v = get_first_series_value::<$T>(end)?;23new_int_range::<$T>(start_v, end_v, step, name.clone()).map(Column::from)24})25}2627fn get_first_series_value<T>(s: &Column) -> PolarsResult<T::Native>28where29T: PolarsIntegerType,30{31let ca: &ChunkedArray<T> = s.as_materialized_series().as_any().downcast_ref().unwrap();32let value_opt = ca.get(0);33let value =34value_opt.ok_or_else(|| polars_err!(ComputeError: "invalid null input for `int_range`"))?;35Ok(value)36}3738pub(super) fn int_ranges(s: &[Column], dtype: DataType) -> PolarsResult<Column> {39let start = &s[0];40let end = &s[1];41let step = &s[2];4243let start = start.i64()?;44let end = end.i64()?;45let step = step.i64()?;4647let len = std::cmp::max(start.len(), end.len());48let mut builder = ListPrimitiveChunkedBuilder::<Int64Type>::new(49// The name should follow our left hand rule.50start.name().clone(),51len,52len * CAPACITY_FACTOR,53DataType::Int64,54);5556let range_impl =57|start, end, step: i64, builder: &mut ListPrimitiveChunkedBuilder<Int64Type>| {58match step {591 => builder.append_values_iter_trusted_len(start..end),602.. => builder.append_values_iter_trusted_len((start..end).step_by(step as usize)),61_ => builder.append_values_iter_trusted_len(62(end..start)63.step_by(step.unsigned_abs() as usize)64.map(|x| start - (x - end)),65),66};67Ok(())68};6970let column = numeric_ranges_impl_broadcast(start, end, step, range_impl, &mut builder)?;7172if dtype != DataType::Int64 {73column.cast(&DataType::List(Box::new(dtype)))74} else {75Ok(column)76}77}787980