Skip to content

Commit

Permalink
add orient function
Browse files Browse the repository at this point in the history
  • Loading branch information
kaikalii committed Jun 17, 2024
1 parent 941fd4d commit 4bf1bd2
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 1 deletion.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ This version is not yet released. If you are reading this on the website, then t
- [`join ⊂`](https://uiua.org/docs/join) will rank differences greater than 1 can now extend the smaller array
- [`un °`](https://uiua.org/docs/un) [`join ⊂`](https://uiua.org/docs/join) is now easier to combine with other inverses
- [`un °`](https://uiua.org/docs/un) [`shape △`](https://uiua.org/docs/shape) now generates an array with the given shape and incrementing elements
- Add the experimental [`orient`](https://uiua.org/docs/orient) function, which arranges an array's axes in a specified order
- Add the experimental [`fft`](https://uiua.org/docs/fft) function, which performs the Fast Fourier transform
- The inverse FFT is also supported via [`un °`](https://uiua.org/docs/un)
- Add the experimental [`astar`](https://uiua.org/docs/astar) modifier, which performs the A* pathfinding algorithm
Expand Down
7 changes: 7 additions & 0 deletions site/primitives.json
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,13 @@
"class": "Stack",
"description": "Call a function but keep its first argument on the top of the stack"
},
"orient": {
"args": 2,
"outputs": 1,
"class": "DyadicArray",
"description": "Change the order of the axes of an array",
"experimental": true
},
"over": {
"glyph": ",",
"args": 2,
Expand Down
52 changes: 52 additions & 0 deletions src/algorithm/dyadic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1696,3 +1696,55 @@ impl Array<f64> {
Ok(Array::new(result_shape, result_data))
}
}

impl Value {
/// `orient` a value by this value
pub fn orient(&self, target: &mut Self, env: &Uiua) -> UiuaResult {
let indices = self.as_ints(env, "Orient indices must be integers")?;
let mut undices = Vec::with_capacity(indices.len());
for i in indices {
let u = i.unsigned_abs();
if u >= target.rank() {
return Err(env.error(format!(
"Cannot orient axis {i} in array of rank {}",
target.rank()
)));
}
if i >= 0 {
undices.push(u);
} else {
undices.push(target.rank() - u);
}
}
if undices.len() > target.rank() {
return Err(env.error(format!(
"Cannot orient array of rank {} with {} indices",
target.rank(),
undices.len()
)));
}
for (i, u) in undices.iter().enumerate() {
if undices[i + 1..].iter().any(|u2| u == u2) {
return Err(env.error("Orient indices must be unique"));
}
}
let mut orientation: Vec<usize> = (0..target.rank()).collect();
let mut depth_rotations: Vec<(usize, i32)> = Vec::new();
for (i, &u) in undices.iter().enumerate() {
let j = orientation.iter().position(|&o| o == u).unwrap();
if i == j {
continue;
}
if j != undices.len() - 1 {
orientation[j..].rotate_left(1);
depth_rotations.push((j, 1));
}
orientation[i..].rotate_right(1);
depth_rotations.push((i, -1));
}
for (depth, amnt) in depth_rotations {
target.transpose_depth(depth, amnt);
}
Ok(())
}
}
19 changes: 19 additions & 0 deletions src/primitive/defs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,9 @@ primitive!(
/// ex: △1_2_3
/// ex: △[1_2 3_4 5_6]
///
/// [un][shape] creates an array of incrementing elements with the given shape.
/// ex: °△ 2_3_4
///
/// It is a triangle`△` because a triangle is a shape.
(1, Shape, MonadicArray, ("shape", '△')),
/// Make an array of all natural numbers less than a number
Expand Down Expand Up @@ -1236,6 +1239,22 @@ primitive!(
/// ex: ↻1 □[1 2 3 4]
/// ex: ≡↻1 {1_2_3 4_5_6}
(2, Rotate, DyadicArray, ("rotate", '↻')),
/// Change the order of the axes of an array
///
/// The first argument is a list of unique axis indices.
/// The corresponding axes of the array will be moved to the front of the array's shape.
/// Positive indices start from the leading axis. Negative indices start from the trailing axis.
/// ex: # Experimental!
/// : °△ 2_3_4
/// : orient 1 .
/// ex: # Experimental!
/// : △ orient 2_1 °△ 2_3_4_5
/// [orient]`¯1` is equivalent to [un][transpose].
/// ex: # Experimental!
/// : °△ 2_3_4
/// : ∩△ ⊃°⍉(orient¯1)
/// Currently, all uses of [orient] can be written with sequences of [transpose] and [rows].
(2, Orient, DyadicArray, "orient"),
/// The n-wise windows of an array
///
/// ex: ◫2 .⇡4
Expand Down
6 changes: 5 additions & 1 deletion src/primitive/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ impl Primitive {
use SysOp::*;
matches!(
self,
But | (Coordinate | Astar | Fft | Triangle | Case)
But | (Orient | Coordinate | Astar | Fft | Triangle | Case)
| Sys(Ffi | MemCopy | MemFree | TlsListen)
| (Stringify | Quote | Sig)
)
Expand Down Expand Up @@ -574,6 +574,10 @@ impl Primitive {
Primitive::Take => env.dyadic_oo_env(Value::take)?,
Primitive::Drop => env.dyadic_oo_env(Value::drop)?,
Primitive::Rotate => env.dyadic_ro_env(Value::rotate)?,
Primitive::Orient => env.dyadic_ro_env(|a, mut b, env| {
a.orient(&mut b, env)?;
Ok(b)
})?,
Primitive::Couple => env.dyadic_oo_env(Value::couple)?,
Primitive::Rise => env.monadic_ref(Value::rise)?,
Primitive::Fall => env.monadic_ref(Value::fall)?,
Expand Down
6 changes: 6 additions & 0 deletions tests/units.ua
Original file line number Diff line number Diff line change
Expand Up @@ -631,3 +631,9 @@ repr[{[[1 2][2 3]][3 4]}{[[1 2][2 3]]□{[[1 2][2 3]]□□[3 4]}}]
⍤⟜≍: [5 8] [⫯+ 3 5]
⍤⟜≍: [4 1 2 3 4] [⫯⊙⊙⊙∘ 1 2 3 4]
⍤⟜≍: [4 1 2 3] [⫯⊙⊙⊙◌ 1 2 3 4]

# Orient
⍤⟜≍: °⍉⟜(orient¯1) °△ 2_3_4
⍤⟜≍: °⍉⟜(orient2) °△ 2_3_4
⍤⟜≍: ≡⍉⟜(orient0_2) °△ 2_3_4
⍤⟜≍: ≡°⍉≡≡⍉°⍉≡≡⍉⟜(orient2_1) °△ 2_3_4_5

0 comments on commit 4bf1bd2

Please sign in to comment.