Skip to content

Commit

Permalink
Implement PartialEq for PyFloat with f64 and f32 (#4348)
Browse files Browse the repository at this point in the history
* Implement PartialEq for PyFloat

Implement PartialEq for PyFloat

* Add changelog under newsfragments, and fix failing fmt CI job

* Use match arm instead of if else

* use value API instead of extract API
  • Loading branch information
Owen-CH-Leung committed Jul 16, 2024
1 parent e353166 commit f635afc
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 2 deletions.
1 change: 1 addition & 0 deletions newsfragments/4348.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Implement `PartialEq<f64>` and `PartialEq<f32>` for `Bound<'py, PyFloat>`.
144 changes: 142 additions & 2 deletions src/types/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use super::any::PyAnyMethods;
#[cfg(feature = "experimental-inspect")]
use crate::inspect::types::TypeInfo;
use crate::{
ffi, ffi_ptr_ext::FfiPtrExt, instance::Bound, FromPyObject, IntoPy, PyAny, PyErr, PyObject,
PyResult, Python, ToPyObject,
ffi, ffi_ptr_ext::FfiPtrExt, instance::Bound, Borrowed, FromPyObject, IntoPy, PyAny, PyErr,
PyObject, PyResult, Python, ToPyObject,
};
use std::os::raw::c_double;

Expand Down Expand Up @@ -140,6 +140,83 @@ impl<'py> FromPyObject<'py> for f32 {
}
}

macro_rules! impl_partial_eq_for_float {
($float_type: ty) => {
impl PartialEq<$float_type> for Bound<'_, PyFloat> {
#[inline]
fn eq(&self, other: &$float_type) -> bool {
self.value() as $float_type == *other
}
}

impl PartialEq<$float_type> for &Bound<'_, PyFloat> {
#[inline]
fn eq(&self, other: &$float_type) -> bool {
self.value() as $float_type == *other
}
}

impl PartialEq<&$float_type> for Bound<'_, PyFloat> {
#[inline]
fn eq(&self, other: &&$float_type) -> bool {
self.value() as $float_type == **other
}
}

impl PartialEq<Bound<'_, PyFloat>> for $float_type {
#[inline]
fn eq(&self, other: &Bound<'_, PyFloat>) -> bool {
other.value() as $float_type == *self
}
}

impl PartialEq<&'_ Bound<'_, PyFloat>> for $float_type {
#[inline]
fn eq(&self, other: &&'_ Bound<'_, PyFloat>) -> bool {
other.value() as $float_type == *self
}
}

impl PartialEq<Bound<'_, PyFloat>> for &'_ $float_type {
#[inline]
fn eq(&self, other: &Bound<'_, PyFloat>) -> bool {
other.value() as $float_type == **self
}
}

impl PartialEq<$float_type> for Borrowed<'_, '_, PyFloat> {
#[inline]
fn eq(&self, other: &$float_type) -> bool {
self.value() as $float_type == *other
}
}

impl PartialEq<&$float_type> for Borrowed<'_, '_, PyFloat> {
#[inline]
fn eq(&self, other: &&$float_type) -> bool {
self.value() as $float_type == **other
}
}

impl PartialEq<Borrowed<'_, '_, PyFloat>> for $float_type {
#[inline]
fn eq(&self, other: &Borrowed<'_, '_, PyFloat>) -> bool {
other.value() as $float_type == *self
}
}

impl PartialEq<Borrowed<'_, '_, PyFloat>> for &$float_type {
#[inline]
fn eq(&self, other: &Borrowed<'_, '_, PyFloat>) -> bool {
other.value() as $float_type == **self
}
}
};
}

impl_partial_eq_for_float!(f64);
impl_partial_eq_for_float!(f32);

#[cfg(test)]
mod tests {
use crate::{
Expand Down Expand Up @@ -177,4 +254,67 @@ mod tests {
assert_approx_eq!(v, obj.value());
});
}

#[test]
fn test_pyfloat_comparisons() {
Python::with_gil(|py| {
let f_64 = 1.01f64;
let py_f64 = PyFloat::new_bound(py, 1.01);
let py_f64_ref = &py_f64;
let py_f64_borrowed = py_f64.as_borrowed();

// Bound<'_, PyFloat> == f64 and vice versa
assert_eq!(py_f64, f_64);
assert_eq!(f_64, py_f64);

// Bound<'_, PyFloat> == &f64 and vice versa
assert_eq!(py_f64, &f_64);
assert_eq!(&f_64, py_f64);

// &Bound<'_, PyFloat> == &f64 and vice versa
assert_eq!(py_f64_ref, f_64);
assert_eq!(f_64, py_f64_ref);

// &Bound<'_, PyFloat> == &f64 and vice versa
assert_eq!(py_f64_ref, &f_64);
assert_eq!(&f_64, py_f64_ref);

// Borrowed<'_, '_, PyFloat> == f64 and vice versa
assert_eq!(py_f64_borrowed, f_64);
assert_eq!(f_64, py_f64_borrowed);

// Borrowed<'_, '_, PyFloat> == &f64 and vice versa
assert_eq!(py_f64_borrowed, &f_64);
assert_eq!(&f_64, py_f64_borrowed);

let f_32 = 2.02f32;
let py_f32 = PyFloat::new_bound(py, 2.02);
let py_f32_ref = &py_f32;
let py_f32_borrowed = py_f32.as_borrowed();

// Bound<'_, PyFloat> == f32 and vice versa
assert_eq!(py_f32, f_32);
assert_eq!(f_32, py_f32);

// Bound<'_, PyFloat> == &f32 and vice versa
assert_eq!(py_f32, &f_32);
assert_eq!(&f_32, py_f32);

// &Bound<'_, PyFloat> == &f32 and vice versa
assert_eq!(py_f32_ref, f_32);
assert_eq!(f_32, py_f32_ref);

// &Bound<'_, PyFloat> == &f32 and vice versa
assert_eq!(py_f32_ref, &f_32);
assert_eq!(&f_32, py_f32_ref);

// Borrowed<'_, '_, PyFloat> == f32 and vice versa
assert_eq!(py_f32_borrowed, f_32);
assert_eq!(f_32, py_f32_borrowed);

// Borrowed<'_, '_, PyFloat> == &f32 and vice versa
assert_eq!(py_f32_borrowed, &f_32);
assert_eq!(&f_32, py_f32_borrowed);
});
}
}

0 comments on commit f635afc

Please sign in to comment.