Skip to content

Commit 1cddcaf

Browse files
committed
fix unsort perf
1 parent e194136 commit 1cddcaf

File tree

3 files changed

+37
-16
lines changed

3 files changed

+37
-16
lines changed

src/algorithm/monadic/sort.rs

+29-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
use std::cmp::Ordering;
1+
use std::{cmp::Ordering, ptr};
22

33
use ecow::EcoVec;
4+
use rand::Rng;
45
use rayon::prelude::*;
56

6-
use crate::{algorithm::ArrayCmpSlice, val_as_arr, Array, ArrayValue, Value};
7+
use crate::{algorithm::ArrayCmpSlice, random_with, val_as_arr, Array, ArrayValue, Value};
78

89
impl Value {
910
/// Get the `rise` of the value
@@ -28,6 +29,10 @@ impl Value {
2829
pub(crate) fn sort_down_depth(&mut self, depth: usize) {
2930
val_as_arr!(self, |a| a.sort_down_depth(depth))
3031
}
32+
/// Shuffle the value
33+
pub fn shuffle(&mut self) {
34+
val_as_arr!(self, Array::shuffle)
35+
}
3136
}
3237

3338
impl<T: ArrayValue> Array<T> {
@@ -255,4 +260,26 @@ impl<T: ArrayValue> Array<T> {
255260
}
256261
self.validate();
257262
}
263+
/// Shuffle the array
264+
pub fn shuffle(&mut self) {
265+
if self.row_count() < 2 {
266+
return;
267+
}
268+
random_with(|rng| {
269+
let row_count = self.row_count();
270+
let row_len = self.row_len();
271+
let slice = self.data.as_mut_slice();
272+
for i in (1..row_count).rev() {
273+
let j = rng.gen_range(0..i);
274+
// Safety: i and j are in bounds and not equal
275+
unsafe {
276+
ptr::swap_nonoverlapping(
277+
slice.as_mut_ptr().add(i * row_len),
278+
slice.as_mut_ptr().add(j * row_len),
279+
row_len,
280+
)
281+
};
282+
}
283+
});
284+
}
258285
}

src/primitive/mod.rs

+8-12
Original file line numberDiff line numberDiff line change
@@ -1367,16 +1367,7 @@ impl ImplPrimitive {
13671367
let val = env.pop(1)?;
13681368
env.push(val.unboxed());
13691369
}
1370-
ImplPrimitive::UnSort => {
1371-
let arr = env.pop(1)?;
1372-
if arr.row_count() < 2 {
1373-
env.push(arr);
1374-
} else {
1375-
let mut rows: Vec<Value> = arr.into_rows().collect();
1376-
RNG.with_borrow_mut(|rng| rows.shuffle(rng));
1377-
env.push(Value::from_row_values_infallible(rows));
1378-
}
1379-
}
1370+
ImplPrimitive::UnSort => env.monadic_mut(Value::shuffle)?,
13801371
ImplPrimitive::UnJson => {
13811372
let json = env.pop(1)?.as_string(env, "JSON expects a string")?;
13821373
let val = Value::from_json_string(&json, env)?;
@@ -2064,12 +2055,17 @@ thread_local! {
20642055

20652056
/// Generate a random number, equivalent to [`Primitive::Rand`]
20662057
pub fn random() -> f64 {
2067-
RNG.with(|rng| rng.borrow_mut().gen::<f64>())
2058+
random_with(|rng| rng.gen())
2059+
}
2060+
2061+
/// Access the interpreter's random number generator for the thread
2062+
pub fn random_with<T>(f: impl FnOnce(&mut SmallRng) -> T) -> T {
2063+
RNG.with(|rng| f(&mut rng.borrow_mut()))
20682064
}
20692065

20702066
/// Seed the random number generator
20712067
pub fn seed_random(seed: u64) {
2072-
RNG.with(|rng| *rng.borrow_mut() = SmallRng::seed_from_u64(seed));
2068+
random_with(|rng| *rng = SmallRng::seed_from_u64(seed));
20732069
}
20742070

20752071
fn trace(env: &mut Uiua, inverse: bool) -> UiuaResult {

todo.md

-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
# Uiua Todo
22

33
# 0.16
4-
- Site deploy action
54
- Optimize `sort` to be in-place by modifying rayon code
6-
- Optimize `unsort`
75
- More rows optimizations
86
- `hsv` function
97
- Line number signatures in pad

0 commit comments

Comments
 (0)