@@ -3,7 +3,10 @@ pub(crate) use decl::make_module;
33#[ pymodule( name = "itertools" ) ]
44mod decl {
55 use crate :: {
6- builtins:: { int, PyGenericAlias , PyInt , PyIntRef , PyList , PyTuple , PyTupleRef , PyTypeRef } ,
6+ builtins:: {
7+ int, tuple:: IntoPyTuple , PyGenericAlias , PyInt , PyIntRef , PyList , PyTuple , PyTupleRef ,
8+ PyTypeRef ,
9+ } ,
710 common:: {
811 lock:: { PyMutex , PyRwLock , PyRwLockWriteGuard } ,
912 rc:: PyRc ,
@@ -1308,7 +1311,7 @@ mod decl {
13081311 struct PyItertoolsCombinations {
13091312 pool : Vec < PyObjectRef > ,
13101313 indices : PyRwLock < Vec < usize > > ,
1311- result : PyRwLock < Option < Vec < usize > > > ,
1314+ result : PyRwLock < Option < Vec < PyObjectRef > > > ,
13121315 r : AtomicCell < usize > ,
13131316 exhausted : AtomicCell < bool > ,
13141317 }
@@ -1355,32 +1358,29 @@ mod decl {
13551358 impl PyItertoolsCombinations {
13561359 #[ pymethod( magic) ]
13571360 fn reduce ( zelf : PyRef < Self > , vm : & VirtualMachine ) -> PyTupleRef {
1358- let result = zelf. result . read ( ) ;
1359- if let Some ( result) = & * result {
1360- if zelf. exhausted . load ( ) {
1361- vm. new_tuple ( (
1362- zelf. class ( ) . to_owned ( ) ,
1363- vm. new_tuple ( ( vm. new_tuple ( ( ) ) , vm. ctx . new_int ( zelf. r . load ( ) ) ) ) ,
1364- ) )
1365- } else {
1366- vm. new_tuple ( (
1367- zelf. class ( ) . to_owned ( ) ,
1368- vm. new_tuple ( (
1369- vm. new_tuple ( zelf. pool . clone ( ) ) ,
1370- vm. ctx . new_int ( zelf. r . load ( ) ) ,
1371- ) ) ,
1372- vm. ctx
1373- . new_tuple ( result. iter ( ) . map ( |& i| zelf. pool [ i] . clone ( ) ) . collect ( ) ) ,
1374- ) )
1375- }
1361+ let r = zelf. r . load ( ) ;
1362+
1363+ let class = zelf. class ( ) . to_owned ( ) ;
1364+
1365+ if zelf. exhausted . load ( ) {
1366+ return vm. new_tuple ( (
1367+ class,
1368+ vm. new_tuple ( ( vm. ctx . empty_tuple . clone ( ) , vm. ctx . new_int ( r) ) ) ,
1369+ ) ) ;
1370+ }
1371+
1372+ let tup = vm. new_tuple ( ( zelf. pool . clone ( ) . into_pytuple ( vm) , vm. ctx . new_int ( r) ) ) ;
1373+
1374+ if zelf. result . read ( ) . is_none ( ) {
1375+ vm. new_tuple ( ( class, tup) )
13761376 } else {
1377- vm . new_tuple ( (
1378- zelf . class ( ) . to_owned ( ) ,
1379- vm . new_tuple ( (
1380- vm . new_tuple ( zelf . pool . clone ( ) ) ,
1381- vm . ctx . new_int ( zelf . r . load ( ) ) ,
1382- ) ) ,
1383- ) )
1377+ let mut indices : Vec < PyObjectRef > = Vec :: new ( ) ;
1378+
1379+ for item in & zelf . indices . read ( ) [ ..r ] {
1380+ indices . push ( vm . new_pyobj ( * item ) ) ;
1381+ }
1382+
1383+ vm . new_tuple ( ( class , tup , indices . into_pytuple ( vm ) ) )
13841384 }
13851385 }
13861386 }
@@ -1401,9 +1401,8 @@ mod decl {
14011401 return Ok ( PyIterReturn :: Return ( vm. new_tuple ( ( ) ) . into ( ) ) ) ;
14021402 }
14031403
1404- let mut result = zelf. result . write ( ) ;
1405-
1406- if let Some ( ref mut result) = * result {
1404+ let mut result_lock = zelf. result . write ( ) ;
1405+ let result = if let Some ( ref mut result) = * result_lock {
14071406 let mut indices = zelf. indices . write ( ) ;
14081407
14091408 // Scan indices right-to-left until finding one that is not at its maximum (i + n - r).
@@ -1426,26 +1425,24 @@ mod decl {
14261425 for j in idx as usize + 1 ..r {
14271426 indices[ j] = indices[ j - 1 ] + 1 ;
14281427 }
1429- for j in 0 ..r {
1430- result[ j] = indices[ j] ;
1428+
1429+ // Update the result tuple for the new indices
1430+ // starting with i, the leftmost index that changed
1431+ for i in idx as usize ..r {
1432+ let index = indices[ i] ;
1433+ let elem = & zelf. pool [ index] ;
1434+ result[ i] = elem. to_owned ( ) ;
14311435 }
1436+
1437+ result. to_vec ( )
14321438 }
14331439 } else {
1434- * result = Some ( ( 0 ..r) . collect ( ) ) ;
1435- }
1440+ let res = zelf. pool [ 0 ..r] . to_vec ( ) ;
1441+ * result_lock = Some ( res. clone ( ) ) ;
1442+ res
1443+ } ;
14361444
1437- Ok ( PyIterReturn :: Return (
1438- vm. ctx
1439- . new_tuple (
1440- result
1441- . as_ref ( )
1442- . unwrap ( )
1443- . iter ( )
1444- . map ( |& i| zelf. pool [ i] . clone ( ) )
1445- . collect ( ) ,
1446- )
1447- . into ( ) ,
1448- ) )
1445+ Ok ( PyIterReturn :: Return ( vm. ctx . new_tuple ( result) . into ( ) ) )
14491446 }
14501447 }
14511448
0 commit comments