Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Bitwise operations / aggregations #18994

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/polars-compute/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use arrow::types::NativeType;

pub mod arithmetic;
pub mod arity;
pub mod bitwise;
pub mod comparisons;
pub mod filter;
pub mod float_sum;
Expand Down
24 changes: 24 additions & 0 deletions crates/polars-core/src/frame/column/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,30 @@ impl Column {
},
}
}

pub fn apply_unary_elementwise(&self, f: impl Fn(&Series) -> Series) -> Column {
match self {
Column::Series(s) => f(s).into(),
Column::Scalar(s) => {
ScalarColumn::from_single_value_series(f(&s.as_single_value_series()), s.len())
.into()
},
}
}

pub fn try_apply_unary_elementwise(
&self,
f: impl Fn(&Series) -> PolarsResult<Series>,
) -> PolarsResult<Column> {
match self {
Column::Series(s) => f(s).map(Column::from),
Column::Scalar(s) => Ok(ScalarColumn::from_single_value_series(
f(&s.as_single_value_series())?,
s.len(),
)
.into()),
}
}
}

impl Default for Column {
Expand Down
2 changes: 2 additions & 0 deletions crates/polars-ops/src/series/ops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod approx_algo;
#[cfg(feature = "approx_unique")]
mod approx_unique;
mod arg_min_max;
mod bitwise;
#[cfg(feature = "business")]
mod business;
mod clip;
Expand Down Expand Up @@ -71,6 +72,7 @@ pub use approx_algo::*;
#[cfg(feature = "approx_unique")]
pub use approx_unique::*;
pub use arg_min_max::ArgAgg;
pub use bitwise::*;
#[cfg(feature = "business")]
pub use business::*;
pub use clip::*;
Expand Down
9 changes: 9 additions & 0 deletions crates/polars-plan/src/dsl/function_expr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod arg_where;
#[cfg(feature = "dtype-array")]
mod array;
mod binary;
mod bitwise;
mod boolean;
mod bounds;
#[cfg(feature = "business")]
Expand Down Expand Up @@ -89,6 +90,7 @@ use schema::FieldsMapper;
use serde::{Deserialize, Serialize};

pub(crate) use self::binary::BinaryFunction;
pub use self::bitwise::BitwiseFunction;
pub use self::boolean::BooleanFunction;
#[cfg(feature = "business")]
pub(super) use self::business::BusinessFunction;
Expand Down Expand Up @@ -127,6 +129,7 @@ pub enum FunctionExpr {
StructExpr(StructFunction),
#[cfg(feature = "temporal")]
TemporalExpr(TemporalFunction),
Bitwise(BitwiseFunction),

// Other expressions
Boolean(BooleanFunction),
Expand Down Expand Up @@ -376,6 +379,7 @@ impl Hash for FunctionExpr {
StructExpr(f) => f.hash(state),
#[cfg(feature = "temporal")]
TemporalExpr(f) => f.hash(state),
Bitwise(f) => f.hash(state),

// Other expressions
Boolean(f) => f.hash(state),
Expand Down Expand Up @@ -602,6 +606,10 @@ impl Display for FunctionExpr {
StructExpr(func) => return write!(f, "{func}"),
#[cfg(feature = "temporal")]
TemporalExpr(func) => return write!(f, "{func}"),
Bitwise(func) => {
f.write_str("bitwise.")?;
return Display::fmt(func, f);
},

// Other expressions
Boolean(func) => return write!(f, "{func}"),
Expand Down Expand Up @@ -871,6 +879,7 @@ impl From<FunctionExpr> for SpecialEq<Arc<dyn ColumnsUdf>> {
StructExpr(func) => func.into(),
#[cfg(feature = "temporal")]
TemporalExpr(func) => func.into(),
Bitwise(func) => func.into(),

// Other expressions
Boolean(func) => func.into(),
Expand Down
1 change: 1 addition & 0 deletions crates/polars-plan/src/dsl/function_expr/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ impl FunctionExpr {
StructExpr(s) => s.get_field(mapper),
#[cfg(feature = "temporal")]
TemporalExpr(fun) => fun.get_field(mapper),
Bitwise(fun) => fun.get_field(mapper),

// Other expressions
Boolean(func) => func.get_field(mapper),
Expand Down
7 changes: 7 additions & 0 deletions crates/polars-plan/src/dsl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ mod arity;
#[cfg(feature = "dtype-array")]
mod array;
pub mod binary;
mod bitwise;
#[cfg(feature = "temporal")]
pub mod dt;
mod expr;
Expand Down Expand Up @@ -44,6 +45,7 @@ pub use arity::*;
#[cfg(feature = "dtype-array")]
pub use array::*;
use arrow::legacy::prelude::QuantileInterpolOptions;
pub use bitwise::*;
pub use expr::*;
pub use function_expr::schema::FieldsMapper;
pub use function_expr::*;
Expand Down Expand Up @@ -1929,6 +1931,11 @@ impl Expr {
list::ListNameSpace(self)
}

/// Get the [`bitwise::BitwiseNameSpace`]
pub fn bitwise(self) -> bitwise::BitwiseNameSpace {
bitwise::BitwiseNameSpace(self)
}

/// Get the [`name::ExprNameNameSpace`]
pub fn name(self) -> name::ExprNameNameSpace {
name::ExprNameNameSpace(self)
Expand Down
1 change: 1 addition & 0 deletions crates/polars-python/src/expr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
mod array;
#[cfg(feature = "pymethods")]
mod binary;
mod bitwise;
#[cfg(feature = "pymethods")]
mod categorical;
#[cfg(feature = "pymethods")]
Expand Down
3 changes: 3 additions & 0 deletions crates/polars-python/src/lazyframe/visitor/expr_nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,9 @@ pub(crate) fn into_py(py: Python<'_>, expr: &AExpr) -> PyResult<PyObject> {
FunctionExpr::ListExpr(_) => {
return Err(PyNotImplementedError::new_err("list expr"))
},
FunctionExpr::Bitwise(_) => {
return Err(PyNotImplementedError::new_err("bitwise expr"))
},
FunctionExpr::StringExpr(strfun) => match strfun {
StringFunction::ConcatHorizontal {
delimiter,
Expand Down
10 changes: 10 additions & 0 deletions py-polars/polars/expr/expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
from polars.exceptions import CustomUFuncWarning, PolarsInefficientMapWarning
from polars.expr.array import ExprArrayNameSpace
from polars.expr.binary import ExprBinaryNameSpace
from polars.expr.bitwise import ExprBitwiseNameSpace
from polars.expr.categorical import ExprCatNameSpace
from polars.expr.datetime import ExprDateTimeNameSpace
from polars.expr.list import ExprListNameSpace
Expand Down Expand Up @@ -10621,6 +10622,15 @@ def dt(self) -> ExprDateTimeNameSpace:
# Keep the `list` and `str` properties below at the end of the definition of Expr,
# as to not confuse mypy with the type annotation `str` and `list`

@property
def bitwise(self) -> ExprBitwiseNameSpace:
coastalwhite marked this conversation as resolved.
Show resolved Hide resolved
"""
Create an object namespace of all bitwise related methods.

See the individual method pages for full details.
"""
return ExprBitwiseNameSpace(self)

@property
def list(self) -> ExprListNameSpace:
"""
Expand Down