Skip to content

Commit 2aea802

Browse files
committed
make dyadic level not recursive
1 parent 4f7dc89 commit 2aea802

File tree

1 file changed

+48
-53
lines changed

1 file changed

+48
-53
lines changed

src/algorithm/zip.rs

Lines changed: 48 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -519,8 +519,7 @@ pub fn level(env: &mut Uiua) -> UiuaResult {
519519
// } else {
520520
// dyadic_level_recursive(f, xs, ys, xn, yn, env)?
521521
// };
522-
let res = dyadic_level_recursive(f, xs, ys, xn, yn, env)?;
523-
env.push(res);
522+
dyadic_level(f, xs, ys, xn, yn, env)?;
524523
}
525524
is => {
526525
let mut args = Vec::with_capacity(is.len());
@@ -557,19 +556,20 @@ fn monadic_level(f: Arc<Function>, value: Value, mut n: usize, env: &mut Uiua) -
557556
let mut new_value = new_rows.finish();
558557
new_shape.extend_from_slice(&new_value.shape()[1..]);
559558
*new_value.shape_mut() = new_shape;
559+
new_value.validate_shape();
560560
env.push(new_value);
561561
}
562562
Ok(())
563563
}
564564

565-
fn dyadic_level_recursive(
565+
fn dyadic_level(
566566
f: Arc<Function>,
567567
xs: Value,
568568
ys: Value,
569-
xn: usize,
570-
yn: usize,
569+
mut xn: usize,
570+
mut yn: usize,
571571
env: &mut Uiua,
572-
) -> UiuaResult<Value> {
572+
) -> UiuaResult {
573573
let xs_prefix = &xs.shape()[..xn];
574574
let ys_prefix = &ys.shape()[..yn];
575575
if !xs_prefix.iter().zip(ys_prefix).all(|(a, b)| a == b) {
@@ -584,56 +584,51 @@ fn dyadic_level_recursive(
584584
FormatShape(ys_prefix)
585585
)));
586586
}
587-
Ok(match (xn, yn) {
588-
(0, 0) => {
589-
env.push(ys);
590-
env.push(xs);
591-
env.call(f)?;
592-
env.pop("level's function result")?
593-
}
594-
(0, yn) => {
595-
let mut new_rows = Vec::with_capacity(ys.row_count());
596-
for y in ys.into_rows() {
597-
new_rows.push(dyadic_level_recursive(
598-
f.clone(),
599-
xs.clone(),
600-
y,
601-
xn,
602-
yn - 1,
603-
env,
604-
)?);
605-
}
606-
Value::from_row_values(new_rows, env)?
587+
xn = xn.min(xs.rank());
588+
yn = yn.min(ys.rank());
589+
let xs_row_shape = Shape::from(&xs.shape()[xn..]);
590+
let ys_row_shape = Shape::from(&ys.shape()[yn..]);
591+
let mut new_rows = Value::builder(1);
592+
if xn == yn {
593+
for (x, y) in xs
594+
.row_shaped_slices(xs_row_shape)
595+
.zip(ys.row_shaped_slices(ys_row_shape))
596+
{
597+
env.push(y);
598+
env.push(x);
599+
env.call_error_on_break(f.clone(), "break is not allowed in level")?;
600+
let row = env.pop("level's function result")?;
601+
new_rows.add_row(row, env)?;
607602
}
608-
(xn, 0) => {
609-
let mut new_rows = Vec::with_capacity(xs.row_count());
610-
for x in xs.into_rows() {
611-
new_rows.push(dyadic_level_recursive(
612-
f.clone(),
613-
x,
614-
ys.clone(),
615-
xn - 1,
616-
yn,
617-
env,
618-
)?);
619-
}
620-
Value::from_row_values(new_rows, env)?
621-
}
622-
(xn, yn) => {
623-
let mut new_rows = Vec::with_capacity(xs.row_count());
624-
for (x, y) in xs.into_rows().zip(ys.into_rows()) {
625-
new_rows.push(dyadic_level_recursive(
626-
f.clone(),
627-
x,
628-
y,
629-
xn - 1,
630-
yn - 1,
631-
env,
632-
)?);
603+
let mut new_value = new_rows.finish();
604+
let mut new_shape = Shape::from_iter(if xs.shape().len() > ys.shape().len() {
605+
xs.shape()[..xn].iter().copied()
606+
} else {
607+
ys.shape()[..yn].iter().copied()
608+
});
609+
new_shape.extend_from_slice(&new_value.shape()[1..]);
610+
*new_value.shape_mut() = new_shape;
611+
new_value.validate_shape();
612+
env.push(new_value);
613+
} else {
614+
for x in xs.row_shaped_slices(xs_row_shape) {
615+
for y in ys.row_shaped_slices(ys_row_shape.clone()) {
616+
env.push(y);
617+
env.push(x.clone());
618+
env.call_error_on_break(f.clone(), "break is not allowed in level")?;
619+
let row = env.pop("level's function result")?;
620+
new_rows.add_row(row, env)?;
633621
}
634-
Value::from_row_values(new_rows, env)?
635622
}
636-
})
623+
let mut new_value = new_rows.finish();
624+
let mut new_shape =
625+
Shape::from_iter(xs.shape()[..xn].iter().chain(&ys.shape()[..yn]).copied());
626+
new_shape.extend_from_slice(&new_value.shape()[1..]);
627+
*new_value.shape_mut() = new_shape;
628+
new_value.validate_shape();
629+
env.push(new_value);
630+
}
631+
Ok(())
637632
}
638633

639634
fn multi_level_recursive(

0 commit comments

Comments
 (0)