6
6
use crate :: algebraic_numbers:: RealAlgebraicNumber ;
7
7
use crate :: traits:: ExactDivAssign ;
8
8
use num_bigint:: BigInt ;
9
- use num_bigint:: Sign ;
10
9
use num_traits:: Signed ;
11
- use num_traits:: ToPrimitive ;
12
10
use num_traits:: Zero ;
13
11
use pyo3:: basic:: CompareOp ;
14
12
use pyo3:: exceptions:: TypeError ;
15
13
use pyo3:: exceptions:: ValueError ;
16
14
use pyo3:: exceptions:: ZeroDivisionError ;
17
15
use pyo3:: prelude:: * ;
18
- use pyo3:: types:: IntoPyDict ;
19
16
use pyo3:: types:: PyAny ;
20
- use pyo3:: types:: PyBytes ;
21
- use pyo3:: types:: PyInt ;
22
- use pyo3:: types:: PyType ;
23
- use pyo3:: FromPy ;
24
17
use pyo3:: PyNativeType ;
25
18
use pyo3:: PyNumberProtocol ;
26
19
use pyo3:: PyObjectProtocol ;
27
20
use std:: sync:: Arc ;
28
21
29
- // TODO: Switch to using BigInt's python conversions once they are implemented
30
- // see https://github.com/PyO3/pyo3/issues/543
31
- #[ derive( Clone , Debug ) ]
32
- pub struct PyBigInt ( pub BigInt ) ;
33
-
34
- impl ToPyObject for PyBigInt {
35
- fn to_object ( & self , py : Python ) -> PyObject {
36
- if let Some ( value) = self . 0 . to_i64 ( ) {
37
- value. to_object ( py)
38
- } else {
39
- let ( sign, bytes) = self . 0 . to_bytes_le ( ) ;
40
- let int_type: & PyType = py. get_type :: < PyInt > ( ) ;
41
- let retval = int_type
42
- . call_method1 ( "from_bytes" , ( bytes, "little" ) )
43
- . unwrap ( )
44
- . downcast_ref :: < PyInt > ( )
45
- . unwrap ( ) ;
46
- if sign == Sign :: Minus {
47
- retval. call_method0 ( "__neg__" ) . unwrap ( ) . to_object ( py)
48
- } else {
49
- retval. to_object ( py)
50
- }
51
- }
52
- }
53
- }
54
-
55
- impl FromPy < PyBigInt > for PyObject {
56
- fn from_py ( value : PyBigInt , py : Python ) -> Self {
57
- value. to_object ( py)
58
- }
59
- }
60
-
61
- impl FromPyObject < ' _ > for PyBigInt {
62
- fn extract ( ob : & PyAny ) -> PyResult < Self > {
63
- let value = ob. downcast_ref :: < PyInt > ( ) ?;
64
- if let Ok ( value) = value. extract :: < i64 > ( ) {
65
- Ok ( PyBigInt ( value. into ( ) ) )
66
- } else {
67
- let mut len = 32 ;
68
- let bytes = loop {
69
- match value. call_method (
70
- "to_bytes" ,
71
- ( len, "little" ) ,
72
- Some ( [ ( "signed" , true ) ] . into_py_dict ( ob. py ( ) ) ) ,
73
- ) {
74
- Ok ( bytes) => break bytes. downcast_ref :: < PyBytes > ( ) ?,
75
- Err ( _) => len *= 2 ,
76
- }
77
- } ;
78
- Ok ( PyBigInt ( BigInt :: from_signed_bytes_le ( bytes. as_bytes ( ) ) ) )
79
- }
80
- }
81
- }
82
-
83
22
#[ pyclass( name=RealAlgebraicNumber , module="algebraics" ) ]
84
23
#[ derive( Clone ) ]
85
24
struct RealAlgebraicNumberPy {
@@ -91,10 +30,10 @@ impl FromPyObject<'_> for RealAlgebraicNumberPy {
91
30
if let Ok ( value) = value. downcast_ref :: < RealAlgebraicNumberPy > ( ) {
92
31
return Ok ( value. clone ( ) ) ;
93
32
}
94
- let value = value. extract :: < Option < & PyInt > > ( ) ?;
33
+ let value = value. extract :: < Option < BigInt > > ( ) ?;
95
34
let value = match value {
96
35
None => RealAlgebraicNumber :: zero ( ) ,
97
- Some ( value) => RealAlgebraicNumber :: from ( value. extract :: < PyBigInt > ( ) ? . 0 ) ,
36
+ Some ( value) => RealAlgebraicNumber :: from ( value) ,
98
37
}
99
38
. into ( ) ;
100
39
Ok ( RealAlgebraicNumberPy { value } )
@@ -109,37 +48,30 @@ impl RealAlgebraicNumberPy {
109
48
value : RealAlgebraicNumber :: zero ( ) . into ( ) ,
110
49
} ) ) ;
111
50
}
112
- fn __trunc__ ( & self ) -> PyBigInt {
51
+ fn __trunc__ ( & self ) -> BigInt {
113
52
let gil = Python :: acquire_gil ( ) ;
114
53
let py = gil. python ( ) ;
115
- py. allow_threads ( || PyBigInt ( self . value . to_integer_trunc ( ) ) )
54
+ py. allow_threads ( || self . value . to_integer_trunc ( ) )
116
55
}
117
- fn __floor__ ( & self ) -> PyBigInt {
56
+ fn __floor__ ( & self ) -> BigInt {
118
57
let gil = Python :: acquire_gil ( ) ;
119
58
let py = gil. python ( ) ;
120
- py. allow_threads ( || PyBigInt ( self . value . to_integer_floor ( ) ) )
59
+ py. allow_threads ( || self . value . to_integer_floor ( ) )
121
60
}
122
- fn __ceil__ ( & self ) -> PyBigInt {
61
+ fn __ceil__ ( & self ) -> BigInt {
123
62
let gil = Python :: acquire_gil ( ) ;
124
63
let py = gil. python ( ) ;
125
- py. allow_threads ( || PyBigInt ( self . value . to_integer_ceil ( ) ) )
64
+ py. allow_threads ( || self . value . to_integer_ceil ( ) )
126
65
}
127
- fn to_integer ( & self ) -> Option < PyBigInt > {
128
- self . value . to_integer ( ) . map ( PyBigInt )
66
+ fn to_integer ( & self ) -> Option < BigInt > {
67
+ self . value . to_integer ( )
129
68
}
130
- fn to_rational ( & self ) -> Option < ( PyBigInt , PyBigInt ) > {
131
- self . value . to_rational ( ) . map ( |value| {
132
- let ( numer, denom) = value. into ( ) ;
133
- ( PyBigInt ( numer) , PyBigInt ( denom) )
134
- } )
69
+ fn to_rational ( & self ) -> Option < ( BigInt , BigInt ) > {
70
+ self . value . to_rational ( ) . map ( Into :: into)
135
71
}
136
72
#[ getter]
137
- fn minimal_polynomial ( & self ) -> Vec < PyBigInt > {
138
- self . value
139
- . minimal_polynomial ( )
140
- . iter ( )
141
- . map ( PyBigInt )
142
- . collect ( )
73
+ fn minimal_polynomial ( & self ) -> Vec < BigInt > {
74
+ self . value . minimal_polynomial ( ) . iter ( ) . collect ( )
143
75
}
144
76
#[ getter]
145
77
fn degree ( & self ) -> usize {
@@ -270,5 +202,3 @@ fn algebraics(_py: Python, m: &PyModule) -> PyResult<()> {
270
202
m. add_class :: < RealAlgebraicNumberPy > ( ) ?;
271
203
Ok ( ( ) )
272
204
}
273
-
274
- // FIXME: add tests
0 commit comments