Repository: jorgecarleitao/arrow2
Pull request #1071 (2022-06-14 04:47:03)

Bumped parquet2 (minor) requirement
This is needed since we depend on parquet2 functionality released on `0.13.1`

codecov[bot]: # [Codecov](https://codecov.io/gh/jorgecarleitao/arrow2/pull/1071?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao) Report
> Merging [#1071](https://codecov.io/gh/jorgecarleitao/arrow2/pull/1071?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao) (1ee05a0) into [main](https://codecov.io/gh/jorgecarleitao/arrow2/commit/76d2a39051a797892371eccd8723406efa7e6399?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao) (76d2a39) will **decrease** coverage by `0.00%`.
> The diff coverage is `n/a`.

```diff
@@            Coverage Diff             @@
##             main    #1071      +/-   ##
==========================================
- Coverage   81.01%   81.00%   -0.01%     
==========================================
  Files         365      365              
  Lines       35023    35023              
==========================================
- Hits        28373    28372       -1     
- Misses       6650     6651       +1     
```


| [Impacted Files](https://codecov.io/gh/jorgecarleitao/arrow2/pull/1071?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao) | Coverage Δ | |
|---|---|---|
| [src/io/ipc/write/serialize.rs](https://codecov.io/gh/jorgecarleitao/arrow2/pull/1071/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao#diff-c3JjL2lvL2lwYy93cml0ZS9zZXJpYWxpemUucnM=) | `96.15% <0.00%> (-0.15%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/jorgecarleitao/arrow2/pull/1071?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/jorgecarleitao/arrow2/pull/1071?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao). Last update [76d2a39...1ee05a0](https://codecov.io/gh/jorgecarleitao/arrow2/pull/1071?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jorge+Leitao).


Patch:
diff --git a/Cargo.toml b/Cargo.toml
index 549965c2c2..571c1021bd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -67,7 +67,7 @@ futures = { version = "0.3", optional = true }
 ahash = { version = "0.7", optional = true }
 
 # parquet support
-parquet2 = { version = "0.13", optional = true, default_features = false }
+parquet2 = { version = "0.13.1", optional = true, default_features = false }
 
 # avro support
 avro-schema = { version = "0.2", optional = true }
diff --git a/benches/assign_ops.rs b/benches/assign_ops.rs
index 0376edccf0..35f29b643c 100644
--- a/benches/assign_ops.rs
+++ b/benches/assign_ops.rs
@@ -1,6 +1,10 @@
 use criterion::{criterion_group, criterion_main, Criterion};
 
-use arrow2::{compute::arithmetics::basic::mul_scalar, util::bench_util::create_primitive_array};
+use arrow2::compute::arity_assign::binary;
+use arrow2::{
+    compute::arithmetics::basic::{mul, mul_scalar},
+    util::bench_util::*,
+};
 
 fn add_benchmark(c: &mut Criterion) {
     (10..=20).step_by(2).for_each(|log2_size| {
@@ -22,6 +26,26 @@ fn add_benchmark(c: &mut Criterion) {
                 assert!(!a.value(10).is_nan());
             })
         });
+
+        let mut arr_a = create_primitive_array::<f32>(size, 0.2);
+        let mut arr_b = create_primitive_array_with_seed::<f32>(size, 0.2, 10);
+        // convert to be close to 1.01
+        arr_b.apply_values(|x| x.iter_mut().for_each(|x| *x = 1.01 + *x / 20.0));
+
+        c.bench_function(&format!("apply_mul null 2^{}", log2_size), |b| {
+            b.iter(|| {
+                binary(criterion::black_box(&mut arr_a), &arr_b, |x, y| x * y);
+                assert!(!arr_a.value(10).is_nan());
+            })
+        });
+
+        let arr_a = create_primitive_array::<f32>(size, 0.2);
+        c.bench_function(&format!("mul null 2^{}", log2_size), |b| {
+            b.iter(|| {
+                let a = mul(criterion::black_box(&arr_a), &arr_b);
+                assert!(!a.value(10).is_nan());
+            })
+        });
     });
 }
 
diff --git a/src/buffer/immutable.rs b/src/buffer/immutable.rs
index d914c8aa71..614089a905 100644
--- a/src/buffer/immutable.rs
+++ b/src/buffer/immutable.rs
@@ -168,6 +168,16 @@ impl<T: NativeType> Buffer<T> {
             Either::Right(data) => data,
         }
     }
+
+    /// Get the strong count of underlying `Arc` data buffer.
+    pub fn shared_count_strong(&self) -> usize {
+        Arc::strong_count(&self.data)
+    }
+
+    /// Get the weak count of underlying `Arc` data buffer.
+    pub fn shared_count_weak(&self) -> usize {
+        Arc::weak_count(&self.data)
+    }
 }
 
 impl<T: NativeType> From<Vec<T>> for Buffer<T> {
diff --git a/src/compute/arity_assign.rs b/src/compute/arity_assign.rs
new file mode 100644
index 0000000000..d10b100117
--- /dev/null
+++ b/src/compute/arity_assign.rs
@@ -0,0 +1,57 @@
+//! Defines generics suitable to perform operations to [`PrimitiveArray`] in-place.
+
+use super::utils::check_same_len;
+use crate::{array::PrimitiveArray, types::NativeType};
+
+/// Applies an unary function to a [`PrimitiveArray`] in-place via cow semantics.
+///
+/// # Implementation
+/// This is the fastest method to apply a binary operation and it is often vectorized (SIMD).
+/// # Panics
+/// This function panics iff
+/// * the arrays have a different length.
+/// * the function itself panics.
+#[inline]
+pub fn unary<I, F>(array: &mut PrimitiveArray<I>, op: F)
+where
+    I: NativeType,
+    F: Fn(I) -> I,
+{
+    array.apply_values(|values| values.iter_mut().for_each(|v| *v = op(*v)));
+}
+
+/// Applies a binary operations to two [`PrimitiveArray`], applying the operation
+/// in-place to the `lhs` via cow semantics.
+///
+/// # Implementation
+/// This is the fastest way to perform a binary operation and it is often vectorized (SIMD).
+/// # Panics
+/// This function panics iff
+/// * the arrays have a different length.
+/// * the function itself panics.
+#[inline]
+pub fn binary<T, D, F>(lhs: &mut PrimitiveArray<T>, rhs: &PrimitiveArray<D>, op: F)
+where
+    T: NativeType,
+    D: NativeType,
+    F: Fn(T, D) -> T,
+{
+    check_same_len(lhs, rhs).unwrap();
+
+    match rhs.validity() {
+        None => {}
+        Some(rhs) => {
+            if lhs.validity().is_none() {
+                *lhs = lhs.with_validity(Some(rhs.clone()))
+            } else {
+                lhs.apply_validity(|mut lhs| lhs &= rhs)
+            }
+        }
+    }
+
+    lhs.apply_values(|x| {
+        x.iter_mut()
+            .zip(rhs.values().iter())
+            .for_each(|(l, r)| *l = op(*l, *r))
+    });
+}
diff --git a/src/compute/mod.rs b/src/compute/mod.rs
index 245f70302e..d4f3ea24db 100644
--- a/src/compute/mod.rs
+++ b/src/compute/mod.rs
@@ -18,6 +18,7 @@ pub mod aggregate;
 #[cfg_attr(docsrs, doc(cfg(feature = "compute_arithmetics")))]
 pub mod arithmetics;
 pub mod arity;
+pub mod arity_assign;
 #[cfg(feature = "compute_bitwise")]
 #[cfg_attr(docsrs, doc(cfg(feature = "compute_bitwise")))]
 pub mod bitwise;


Test patch:
diff --git a/tests/it/compute/arity_assign.rs b/tests/it/compute/arity_assign.rs
new file mode 100644
index 0000000000..b3581e2fa3
--- /dev/null
+++ b/tests/it/compute/arity_assign.rs
@@ -0,0 +1,21 @@
+use arrow2::array::Int32Array;
+use arrow2::compute::arity_assign::{binary, unary};
+
+#[test]
+fn test_unary_assign() {
+    let mut a = Int32Array::from([Some(5), Some(6), None, Some(10)]);
+
+    unary(&mut a, |x| x + 10);
+
+    assert_eq!(a, Int32Array::from([Some(15), Some(16), None, Some(20)]))
+}
+
+#[test]
+fn test_binary_assign() {
+    let mut a = Int32Array::from([Some(5), Some(6), None, Some(10)]);
+    let b = Int32Array::from([Some(1), Some(2), Some(1), None]);
+
+    binary(&mut a, &b, |x, y| x + y);
+
+    assert_eq!(a, Int32Array::from([Some(6), Some(8), None, None]))
+}
diff --git a/tests/it/compute/mod.rs b/tests/it/compute/mod.rs
index f4972c2194..2a298cf2bd 100644
--- a/tests/it/compute/mod.rs
+++ b/tests/it/compute/mod.rs
@@ -46,3 +46,5 @@ mod temporal;
 mod utf8;
 #[cfg(feature = "compute_window")]
 mod window;
+
+mod arity_assign;