@@ -3,7 +3,10 @@ pub(crate) use decl::make_module;
3
3
#[ pymodule( name = "itertools" ) ]
4
4
mod decl {
5
5
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
+ } ,
7
10
common:: {
8
11
lock:: { PyMutex , PyRwLock , PyRwLockWriteGuard } ,
9
12
rc:: PyRc ,
@@ -1308,7 +1311,7 @@ mod decl {
1308
1311
struct PyItertoolsCombinations {
1309
1312
pool : Vec < PyObjectRef > ,
1310
1313
indices : PyRwLock < Vec < usize > > ,
1311
- result : PyRwLock < Option < Vec < usize > > > ,
1314
+ result : PyRwLock < Option < Vec < PyObjectRef > > > ,
1312
1315
r : AtomicCell < usize > ,
1313
1316
exhausted : AtomicCell < bool > ,
1314
1317
}
@@ -1355,32 +1358,29 @@ mod decl {
1355
1358
impl PyItertoolsCombinations {
1356
1359
#[ pymethod( magic) ]
1357
1360
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) )
1376
1376
} 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 ) ) )
1384
1384
}
1385
1385
}
1386
1386
}
@@ -1403,7 +1403,7 @@ mod decl {
1403
1403
1404
1404
let mut result = zelf. result . write ( ) ;
1405
1405
1406
- if let Some ( ref mut result) = * result {
1406
+ let result = if let Some ( ref mut result) = * result {
1407
1407
let mut indices = zelf. indices . write ( ) ;
1408
1408
1409
1409
// Scan indices right-to-left until finding one that is not at its maximum (i + n - r).
@@ -1426,26 +1426,25 @@ mod decl {
1426
1426
for j in idx as usize + 1 ..r {
1427
1427
indices[ j] = indices[ j - 1 ] + 1 ;
1428
1428
}
1429
- for j in 0 ..r {
1430
- result[ j] = indices[ j] ;
1429
+
1430
+ // Update the result tuple for the new indices
1431
+ // starting with i, the leftmost index that changed
1432
+ for i in idx as usize ..r {
1433
+ let index = indices[ i] ;
1434
+ let elem = & zelf. pool [ index] ;
1435
+ result[ i] = elem. to_owned ( ) ;
1431
1436
}
1437
+
1438
+ result. to_vec ( )
1432
1439
}
1433
1440
} else {
1434
- * result = Some ( ( 0 ..r) . collect ( ) ) ;
1435
- }
1441
+ let res = zelf . pool [ 0 ..r] . to_vec ( ) ;
1442
+ * result = Some ( res . clone ( ) ) ;
1436
1443
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
- ) )
1444
+ res
1445
+ } ;
1446
+
1447
+ Ok ( PyIterReturn :: Return ( vm. ctx . new_tuple ( result) . into ( ) ) )
1449
1448
}
1450
1449
}
1451
1450
0 commit comments