1use std::cmp::Ordering;
2use std::fmt;
3
4use crate::conversion::ToPyObject;
5use crate::err::{self, PyErr, PyResult};
6use crate::ffi;
7use crate::objects::{PyObject, PyInt, PyLong, PyFloat};
8use crate::python::{Python, PythonObject, ToPythonPointer};
9
10
11use super::ObjectProtocol;
12
13pub trait NumberProtocol: ObjectProtocol {
15 #[inline]
19 fn add(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
20 other.with_borrowed_ptr(py, |other| unsafe {
21 err::result_from_owned_ptr(py, ffi::PyNumber_Add(self.as_ptr(), other))
22 })
23 }
24 #[inline]
28 fn subtract(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
29 other.with_borrowed_ptr(py, |other| unsafe {
30 err::result_from_owned_ptr(py, ffi::PyNumber_Subtract(self.as_ptr(), other))
31 })
32 }
33 #[inline]
37 fn multiply(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
38 other.with_borrowed_ptr(py, |other| unsafe {
39 err::result_from_owned_ptr(py, ffi::PyNumber_Multiply(self.as_ptr(), other))
40 })
41 }
42 #[inline]
50 #[cfg(feature = "python3-sys")]
51 fn matrix_multiply(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
52 other.with_borrowed_ptr(py, |other| unsafe {
53 err::result_from_owned_ptr(py, ffi::PyNumber_MatrixMultiply(self.as_ptr(), other))
54 })
55 }
56 #[inline]
63 fn power(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
64 self.power_modulo(py, other, py.None())
65 }
66 #[inline]
78 fn power_modulo(&self, py: Python, exp: impl ToPyObject, z: impl ToPyObject) -> PyResult<PyObject> {
79 exp.with_borrowed_ptr(py, |exp| {
80 z.with_borrowed_ptr(py, |z| unsafe {
81 err::result_from_owned_ptr(py, ffi::PyNumber_Power(self.as_ptr(), exp, z))
82 })
83 })
84 }
85 #[inline]
90 fn true_divide(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
91 other.with_borrowed_ptr(py, |other| unsafe {
92 err::result_from_owned_ptr(py, ffi::PyNumber_TrueDivide(self.as_ptr(), other))
93 })
94 }
95 #[inline]
103 fn floor_divide(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
104 other.with_borrowed_ptr(py, |other| unsafe {
105 err::result_from_owned_ptr(py, ffi::PyNumber_FloorDivide(self.as_ptr(), other))
106 })
107 }
108 #[inline]
113 fn modulo(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
114 other.with_borrowed_ptr(py, |other| unsafe {
115 err::result_from_owned_ptr(py, ffi::PyNumber_Remainder(self.as_ptr(), other))
116 })
117 }
118 #[inline]
123 fn div_mod(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
124 other.with_borrowed_ptr(py, |other| unsafe {
125 err::result_from_owned_ptr(py, ffi::PyNumber_Divmod(self.as_ptr(), other))
126 })
127 }
128 #[inline]
132 fn negative(&self, py: Python) -> PyResult<PyObject> {
133 unsafe {
134 err::result_from_owned_ptr(py, ffi::PyNumber_Negative(self.as_ptr()))
135 }
136 }
137 #[inline]
142 fn positive(&self, py: Python) -> PyResult<PyObject> {
143 unsafe {
144 err::result_from_owned_ptr(py, ffi::PyNumber_Positive(self.as_ptr()))
145 }
146 }
147 #[inline]
152 fn absolute(&self, py: Python) -> PyResult<PyObject> {
153 unsafe {
154 err::result_from_owned_ptr(py, ffi::PyNumber_Absolute(self.as_ptr()))
155 }
156 }
157 #[inline]
162 fn bitwise_invert(&self, py: Python) -> PyResult<PyObject> {
163 unsafe {
164 err::result_from_owned_ptr(py, ffi::PyNumber_Invert(self.as_ptr()))
165 }
166 }
167 #[inline]
172 fn left_shift(&self, py: Python, bits: impl ToPyObject) -> PyResult<PyObject> {
173 bits.with_borrowed_ptr(py, |other| unsafe {
174 err::result_from_owned_ptr(py, ffi::PyNumber_Lshift(self.as_ptr(), other))
175 })
176 }
177 #[inline]
182 fn right_shift(&self, py: Python, bits: impl ToPyObject) -> PyResult<PyObject> {
183 bits.with_borrowed_ptr(py, |other| unsafe {
184 err::result_from_owned_ptr(py, ffi::PyNumber_Rshift(self.as_ptr(), other))
185 })
186 }
187 #[inline]
191 fn bitwise_and(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
192 other.with_borrowed_ptr(py, |other| unsafe {
193 err::result_from_owned_ptr(py, ffi::PyNumber_And(self.as_ptr(), other))
194 })
195 }
196 #[inline]
201 fn bitwise_xor(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
202 other.with_borrowed_ptr(py, |other| unsafe {
203 err::result_from_owned_ptr(py, ffi::PyNumber_Xor(self.as_ptr(), other))
204 })
205 }
206 #[inline]
210 fn bitwise_or(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
211 other.with_borrowed_ptr(py, |other| unsafe {
212 err::result_from_owned_ptr(py, ffi::PyNumber_Or(self.as_ptr(), other))
213 })
214 }
215 #[inline]
223 fn to_int(&self, py: Python) -> PyResult<PyLong> {
224 let obj = unsafe {
225 err::result_from_owned_ptr(py, ffi::PyNumber_Long(self.as_ptr()))?
226 };
227 Ok(obj.cast_into::<PyLong>(py)?)
228 }
229 #[inline]
237 fn to_float(&self, py: Python) -> PyResult<PyFloat> {
238 let obj = unsafe {
239 err::result_from_owned_ptr(py, ffi::PyNumber_Float(self.as_ptr()))?
240 };
241 Ok(obj.cast_into::<PyFloat>(py)?)
242 }
243 #[inline]
253 fn to_index(&self, py: Python) -> PyResult<PyLong> {
254 let obj = unsafe {
255 err::result_from_owned_ptr(py, ffi::PyNumber_Index(self.as_ptr()))?
256 };
257 Ok(obj.cast_into::<PyLong>(py)?)
258 }
259}
260
261impl NumberProtocol for PyObject {}
262
263
264#[cfg(test)]
265mod test {
266 use crate::*;
267 use super::*;
268
269 #[test]
270 fn addition() {
271 let guard = Python::acquire_gil();
272 let py = guard.python();
273 let i1 = (5i32).to_py_object(py).into_object();
274 let i2 = (12i32).to_py_object(py).into_object();
275 let actual_res = i1.add(py, i2).unwrap();
276 let expected_res = (17i32).to_py_object(py).into_object();
277 assert_eq!(
278 actual_res.compare(py, expected_res).unwrap(),
279 Ordering::Equal
280 );
281 }
282}