11use pyo3:: prelude:: * ;
22use pyo3:: wrap_pyfunction;
3+ use pyo3:: types:: PyTuple ;
34use numpy:: { PyArray1 , PyReadonlyArray1 , PyReadonlyArray2 , PyArrayMethods , PyUntypedArrayMethods } ;
45use rand:: { rngs:: StdRng , SeedableRng } ;
56
@@ -16,13 +17,13 @@ macro_rules! variant_call {
1617/// :return: k-medoids clustering result
1718/// :rtype: KMedoidsResult
1819 #[ pyfunction]
19- fn $name( dist: PyReadonlyArray2 <' _ , $type>, meds: PyReadonlyArray1 <' _ , usize >, max_iter: usize ) -> PyResult <Py <PyAny >> {
20+ fn $name< ' py> ( dist: PyReadonlyArray2 <' py , $type>, meds: PyReadonlyArray1 <' py , usize >, max_iter: usize ) -> PyResult <Py <PyTuple >> {
2021 assert_eq!( dist. ndim( ) , 2 ) ;
2122 assert_eq!( dist. shape( ) [ 0 ] , dist. shape( ) [ 1 ] ) ;
2223 let mut meds = meds. to_vec( ) ?;
2324 let ( loss, assi, n_iter, n_swap) : ( $ltype, _, _, _) = rustkmedoids:: $variant( & dist. as_array( ) , & mut meds, max_iter) ;
24- Python :: with_gil( |py| -> PyResult < Py < PyAny >> {
25- Ok ( ( loss, PyArray1 :: from_vec_bound ( py, assi) , PyArray1 :: from_vec_bound ( py, meds) , n_iter, n_swap) . to_object ( py) )
25+ Python :: with_gil( |py| {
26+ Ok ( ( loss, PyArray1 :: from_vec ( py, assi) , PyArray1 :: from_vec ( py, meds) , n_iter, n_swap) . into_pyobject ( py) ? . unbind ( ) )
2627 } )
2728}
2829} }
@@ -62,14 +63,14 @@ macro_rules! rand_call {
6263/// :return: k-medoids clustering result
6364/// :rtype: KMedoidsResult
6465 #[ pyfunction]
65- fn $name( dist: PyReadonlyArray2 <' _ , $type>, meds: PyReadonlyArray1 <' _ , usize >, max_iter: usize , seed: u64 ) -> PyResult <Py <PyAny >> {
66+ fn $name< ' py> ( dist: PyReadonlyArray2 <' py , $type>, meds: PyReadonlyArray1 <' py , usize >, max_iter: usize , seed: u64 ) -> PyResult <Py <PyTuple >> {
6667 assert_eq!( dist. ndim( ) , 2 ) ;
6768 assert_eq!( dist. shape( ) [ 0 ] , dist. shape( ) [ 1 ] ) ;
6869 let mut meds = meds. to_vec( ) ?;
6970 let mut rnd = StdRng :: seed_from_u64( seed) ;
7071 let ( loss, assi, n_iter, n_swap) : ( $ltype, _, _, _) = rustkmedoids:: $variant( & dist. as_array( ) , & mut meds, max_iter, & mut rnd) ;
71- Python :: with_gil( |py| -> PyResult < Py < PyAny >> {
72- Ok ( ( loss, PyArray1 :: from_vec_bound ( py, assi) , PyArray1 :: from_vec_bound ( py, meds) , n_iter, n_swap) . to_object ( py) )
72+ Python :: with_gil( |py| {
73+ Ok ( ( loss, PyArray1 :: from_vec ( py, assi) , PyArray1 :: from_vec ( py, meds) , n_iter, n_swap) . into_pyobject ( py) ? . unbind ( ) )
7374 } )
7475}
7576} }
@@ -95,7 +96,7 @@ macro_rules! par_call {
9596/// :return: k-medoids clustering result
9697/// :rtype: KMedoidsResult
9798 #[ pyfunction]
98- fn $name( dist: PyReadonlyArray2 <' _ , $type>, meds: PyReadonlyArray1 <' _ , usize >, max_iter: usize , seed: u64 , n_cpu: usize ) -> PyResult <Py <PyAny >> {
99+ fn $name< ' py> ( dist: PyReadonlyArray2 <' py , $type>, meds: PyReadonlyArray1 <' py , usize >, max_iter: usize , seed: u64 , n_cpu: usize ) -> PyResult <Py <PyTuple >> {
99100 assert_eq!( dist. ndim( ) , 2 ) ;
100101 assert_eq!( dist. shape( ) [ 0 ] , dist. shape( ) [ 1 ] ) ;
101102 let pool = rayon:: ThreadPoolBuilder :: new( ) . num_threads( n_cpu) . build( ) . unwrap( ) ;
@@ -105,8 +106,8 @@ fn $name(dist: PyReadonlyArray2<'_, $type>, meds: PyReadonlyArray1<'_, usize>, m
105106 let mut rnd = StdRng :: seed_from_u64( seed) ;
106107 rustkmedoids:: $variant( & dist, & mut meds, max_iter, & mut rnd)
107108 } ) ;
108- Python :: with_gil( |py| -> PyResult < Py < PyAny >> {
109- Ok ( ( loss, PyArray1 :: from_vec_bound ( py, assi) , PyArray1 :: from_vec_bound ( py, meds) , n_iter, n_swap) . to_object ( py) )
109+ Python :: with_gil( |py| {
110+ Ok ( ( loss, PyArray1 :: from_vec ( py, assi) , PyArray1 :: from_vec ( py, meds) , n_iter, n_swap) . into_pyobject ( py) ? . unbind ( ) )
110111 } )
111112}
112113} }
@@ -126,12 +127,12 @@ macro_rules! pam_build_call {
126127/// :return: k-medoids clustering result
127128/// :rtype: KMedoidsResult
128129 #[ pyfunction]
129- fn $name( dist: PyReadonlyArray2 <' _ , $type>, k: usize ) -> PyResult <Py <PyAny >> {
130+ fn $name< ' py> ( dist: PyReadonlyArray2 <' py , $type>, k: usize ) -> PyResult <Py <PyTuple >> {
130131 assert_eq!( dist. ndim( ) , 2 ) ;
131132 assert_eq!( dist. shape( ) [ 0 ] , dist. shape( ) [ 1 ] ) ;
132133 let ( loss, assi, meds) : ( $ltype, _, _) = rustkmedoids:: pam_build( & dist. as_array( ) , k) ;
133- Python :: with_gil( |py| -> PyResult < Py < PyAny >> {
134- Ok ( ( loss, PyArray1 :: from_vec_bound ( py, assi) , PyArray1 :: from_vec_bound ( py, meds) , 1 ) . to_object ( py) )
134+ Python :: with_gil( |py| {
135+ Ok ( ( loss, PyArray1 :: from_vec ( py, assi) , PyArray1 :: from_vec ( py, meds) , 1 ) . into_pyobject ( py) ? . unbind ( ) )
135136 } )
136137}
137138} }
@@ -153,13 +154,13 @@ macro_rules! alternating_call {
153154/// :return: k-medoids clustering result
154155/// :rtype: KMedoidsResult
155156 #[ pyfunction]
156- fn $name( dist: PyReadonlyArray2 <' _ , $type>, meds: PyReadonlyArray1 <' _ , usize >, max_iter: usize ) -> PyResult <Py <PyAny >> {
157+ fn $name< ' py> ( dist: PyReadonlyArray2 <' py , $type>, meds: PyReadonlyArray1 <' py , usize >, max_iter: usize ) -> PyResult <Py <PyTuple >> {
157158 assert_eq!( dist. ndim( ) , 2 ) ;
158159 assert_eq!( dist. shape( ) [ 0 ] , dist. shape( ) [ 1 ] ) ;
159160 let mut meds = meds. to_vec( ) ?;
160161 let ( loss, assi, n_iter) : ( $ltype, _, _) = rustkmedoids:: alternating( & dist. as_array( ) , & mut meds, max_iter) ;
161- Python :: with_gil( |py| -> PyResult < Py < PyAny >> {
162- Ok ( ( loss, PyArray1 :: from_vec_bound ( py, assi) , PyArray1 :: from_vec_bound ( py, meds) , n_iter) . to_object ( py) )
162+ Python :: with_gil( |py| {
163+ Ok ( ( loss, PyArray1 :: from_vec ( py, assi) , PyArray1 :: from_vec ( py, meds) , n_iter) . into_pyobject ( py) ? . unbind ( ) )
163164 } )
164165}
165166} }
@@ -181,15 +182,15 @@ macro_rules! dynmsc_call {
181182/// :return: k-medoids clustering result
182183/// :rtype: DynkResult
183184 #[ pyfunction]
184- fn $name( dist: PyReadonlyArray2 <' _ , $type>, meds: PyReadonlyArray1 <' _ , usize >, minimum_k: usize , max_iter: usize ) -> PyResult <Py <PyAny >> {
185+ fn $name< ' py> ( dist: PyReadonlyArray2 <' py , $type>, meds: PyReadonlyArray1 <' py , usize >, minimum_k: usize , max_iter: usize ) -> PyResult <Py <PyTuple >> {
185186 assert_eq!( dist. ndim( ) , 2 ) ;
186187 assert_eq!( dist. shape( ) [ 0 ] , dist. shape( ) [ 1 ] ) ;
187188 let mut meds = meds. to_vec( ) ?;
188189 let maxk = meds. len( ) + 1 ;
189190 let ( loss, assi, n_iter, n_swap, best_meds, losses) : ( $ltype, _, _, _, _, _) = rustkmedoids:: dynmsc( & dist. as_array( ) , & mut meds, minimum_k, max_iter) ;
190191 let bestk = best_meds. len( ) ;
191- Python :: with_gil( |py| -> PyResult < Py < PyAny >> {
192- Ok ( ( loss, PyArray1 :: from_vec_bound ( py, assi) , PyArray1 :: from_vec_bound ( py, best_meds) , bestk, PyArray1 :: from_vec_bound ( py, losses) , ( minimum_k..maxk) . collect:: <Vec <usize >>( ) , n_iter, n_swap) . to_object ( py) )
192+ Python :: with_gil( |py| {
193+ Ok ( ( loss, PyArray1 :: from_vec ( py, assi) , PyArray1 :: from_vec ( py, best_meds) , bestk, PyArray1 :: from_vec ( py, losses) , PyArray1 :: from_vec ( py , ( minimum_k..maxk) . collect:: <Vec <usize >>( ) ) , n_iter, n_swap) . into_pyobject ( py) ? . unbind ( ) )
193194 } )
194195}
195196} }
@@ -209,12 +210,12 @@ macro_rules! silhouette_call {
209210/// :return: Silhouette evaluation result
210211/// :rtype: pair of Silhouette score and Silhouette coefficients per point
211212 #[ pyfunction]
212- fn $name( dist: PyReadonlyArray2 <' _ , $type>, assi: PyReadonlyArray1 <' _ , usize >, samples: bool ) -> PyResult <Py <PyAny >> {
213+ fn $name< ' py> ( dist: PyReadonlyArray2 <' py , $type>, assi: PyReadonlyArray1 <' py , usize >, samples: bool ) -> PyResult <Py <PyTuple >> {
213214 assert_eq!( dist. ndim( ) , 2 ) ;
214215 assert_eq!( dist. shape( ) [ 0 ] , dist. shape( ) [ 1 ] ) ;
215216 let ( sil, sils) : ( f64 , _) = rustkmedoids:: silhouette( & dist. as_array( ) , & assi. to_vec( ) ?, samples) ;
216- Python :: with_gil( |py| -> PyResult < Py < PyAny >> {
217- Ok ( ( sil, PyArray1 :: from_vec_bound ( py, sils) ) . to_object ( py) )
217+ Python :: with_gil( |py| {
218+ Ok ( ( sil, PyArray1 :: from_vec ( py, sils) ) . into_pyobject ( py) ? . unbind ( ) )
218219 } )
219220}
220221} }
@@ -236,7 +237,7 @@ macro_rules! par_silhouette_call {
236237/// :return: Silhouette evaluation result
237238/// :rtype: Silhouette score
238239 #[ pyfunction]
239- fn $name( dist: PyReadonlyArray2 <' _ , $type>, assi: PyReadonlyArray1 <' _ , usize >, n_cpu: usize ) -> PyResult <f64 > {
240+ fn $name< ' py> ( dist: PyReadonlyArray2 <' py , $type>, assi: PyReadonlyArray1 <' py , usize >, n_cpu: usize ) -> PyResult <f64 > {
240241 assert_eq!( dist. ndim( ) , 2 ) ;
241242 assert_eq!( dist. shape( ) [ 0 ] , dist. shape( ) [ 1 ] ) ;
242243 let pool = rayon:: ThreadPoolBuilder :: new( ) . num_threads( n_cpu) . build( ) . unwrap( ) ;
@@ -264,12 +265,12 @@ macro_rules! medoid_silhouette_call {
264265/// :return: Medoid Silhouette evaluation result
265266/// :rtype: pair of Medoid Silhouette score and Medoid Silhouette coefficients per point
266267 #[ pyfunction]
267- fn $name( dist: PyReadonlyArray2 <' _ , $type>, meds: PyReadonlyArray1 <' _ , usize >, samples: bool ) -> PyResult <Py <PyAny >> {
268+ fn $name< ' py> ( dist: PyReadonlyArray2 <' py , $type>, meds: PyReadonlyArray1 <' py , usize >, samples: bool ) -> PyResult <Py <PyTuple >> {
268269 assert_eq!( dist. ndim( ) , 2 ) ;
269270 assert_eq!( dist. shape( ) [ 0 ] , dist. shape( ) [ 1 ] ) ;
270271 let ( sil, sils) : ( f64 , _) = rustkmedoids:: medoid_silhouette( & dist. as_array( ) , & meds. to_vec( ) ?, samples) ;
271- Python :: with_gil( |py| -> PyResult < Py < PyAny >> {
272- Ok ( ( sil, PyArray1 :: from_vec_bound ( py, sils) ) . to_object ( py) )
272+ Python :: with_gil( |py| {
273+ Ok ( ( sil, PyArray1 :: from_vec ( py, sils) ) . into_pyobject ( py) ? . unbind ( ) )
273274 } )
274275}
275276} }
0 commit comments