Skip to content

Commit

Permalink
fix: Invalid bitwise_xor for ScalarColumn (#20140)
Browse files Browse the repository at this point in the history
  • Loading branch information
coastalwhite authored Dec 6, 2024
1 parent eb135b4 commit 36b1244
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 17 deletions.
19 changes: 8 additions & 11 deletions crates/polars-core/src/frame/column/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1196,19 +1196,13 @@ impl Column {
}

pub fn bitand(&self, rhs: &Self) -> PolarsResult<Self> {
// @partition-opt
// @scalar-opt
(self.as_materialized_series() & rhs.as_materialized_series()).map(Column::from)
self.try_apply_broadcasting_binary_elementwise(rhs, |l, r| l & r)
}
pub fn bitor(&self, rhs: &Self) -> PolarsResult<Self> {
// @partition-opt
// @scalar-opt
(self.as_materialized_series() | rhs.as_materialized_series()).map(Column::from)
self.try_apply_broadcasting_binary_elementwise(rhs, |l, r| l | r)
}
pub fn bitxor(&self, rhs: &Self) -> PolarsResult<Self> {
// @partition-opt
// @scalar-opt
(self.as_materialized_series() ^ rhs.as_materialized_series()).map(Column::from)
self.try_apply_broadcasting_binary_elementwise(rhs, |l, r| l ^ r)
}

pub fn try_add_owned(self, other: Self) -> PolarsResult<Self> {
Expand Down Expand Up @@ -1341,15 +1335,18 @@ impl Column {
Column::Scalar(s) => {
// We don't really want to deal with handling the full semantics here so we just
// cast to a single value series. This is a tiny bit wasteful, but probably fine.
s.as_single_value_series().xor_reduce()
//
// We have to deal with the fact that xor is 0 if there is an even number of
// elements and the value if there is an odd number of elements. If there are zero
// elements the result should be `null`.
s.as_n_values_series(2 - s.len() % 2).xor_reduce()
},
}
}
pub fn n_unique(&self) -> PolarsResult<usize> {
match self {
Column::Series(s) => s.n_unique(),
Column::Partitioned(s) => s.partitions().n_unique(),
// @scalar-opt
Column::Scalar(s) => s.as_single_value_series().n_unique(),
}
}
Expand Down
16 changes: 10 additions & 6 deletions crates/polars-core/src/frame/column/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,17 @@ impl ScalarColumn {
///
/// If the [`ScalarColumn`] has `length=0` the resulting `Series` will also have `length=0`.
pub fn as_single_value_series(&self) -> Series {
self.as_n_values_series(1)
}

/// Take the [`ScalarColumn`] as a series with a `n` values.
///
/// If the [`ScalarColumn`] has `length=0` the resulting `Series` will also have `length=0`.
pub fn as_n_values_series(&self, n: usize) -> Series {
let length = usize::min(n, self.length);
match self.materialized.get() {
Some(s) => s.head(Some(1)),
None => Self::_to_series(
self.name.clone(),
self.scalar.clone(),
usize::min(1, self.length),
),
Some(s) => s.head(Some(length)),
None => Self::_to_series(self.name.clone(), self.scalar.clone(), length),
}
}

Expand Down
13 changes: 13 additions & 0 deletions py-polars/tests/unit/operations/test_bitwise.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,16 @@ def test_bit_group_by(dtype: pl.DataType) -> None:
),
check_row_order=False,
)


def test_scalar_bitwise_xor() -> None:
df = pl.select(
pl.repeat(pl.lit(0x80, pl.UInt8), i).bitwise_xor().alias(f"l{i}")
for i in range(5)
).transpose()

assert_series_equal(
df.to_series(),
pl.Series("x", [None, 0x80, 0x00, 0x80, 0x00], pl.UInt8),
check_names=False,
)

0 comments on commit 36b1244

Please sign in to comment.