Skip to content

Commit d524717

Browse files
yonmilkyouknowone
authored andcommitted
Add combinations.__reduce__
1 parent 5608808 commit d524717

File tree

1 file changed

+43
-44
lines changed

1 file changed

+43
-44
lines changed

vm/src/stdlib/itertools.rs

Lines changed: 43 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ pub(crate) use decl::make_module;
33
#[pymodule(name = "itertools")]
44
mod 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
}
@@ -1403,7 +1403,7 @@ mod decl {
14031403

14041404
let mut result = zelf.result.write();
14051405

1406-
if let Some(ref mut result) = *result {
1406+
let result = if let Some(ref mut result) = *result {
14071407
let mut indices = zelf.indices.write();
14081408

14091409
// Scan indices right-to-left until finding one that is not at its maximum (i + n - r).
@@ -1426,26 +1426,25 @@ mod decl {
14261426
for j in idx as usize + 1..r {
14271427
indices[j] = indices[j - 1] + 1;
14281428
}
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();
14311436
}
1437+
1438+
result.to_vec()
14321439
}
14331440
} else {
1434-
*result = Some((0..r).collect());
1435-
}
1441+
let res = zelf.pool[0..r].to_vec();
1442+
*result = Some(res.clone());
14361443

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()))
14491448
}
14501449
}
14511450

0 commit comments

Comments
 (0)