From f798d5a88b7ebd1e5be6d0644a0fe064080e3d00 Mon Sep 17 00:00:00 2001 From: Philippe-Cholet <44676486+Philippe-Cholet@users.noreply.github.com> Date: Sat, 6 Jul 2024 10:08:49 +0200 Subject: [PATCH] Faster `minmax` by using `fold` Do less comparisons by considering pairs is smart but this was done by `loop { it.next(), it.next() }` while `it.fold` is generally faster. This results in a lot of changes but most of it is merely moving code and indentation corrections. --- src/minmax.rs | 69 ++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/src/minmax.rs b/src/minmax.rs index 5c9674e01..d937802f7 100644 --- a/src/minmax.rs +++ b/src/minmax.rs @@ -67,48 +67,45 @@ where }, }; - loop { - // `first` and `second` are the two next elements we want to look - // at. We first compare `first` and `second` (#1). The smaller one - // is then compared to current minimum (#2). The larger one is - // compared to current maximum (#3). This way we do 3 comparisons - // for 2 elements. - let first = match it.next() { - None => break, - Some(x) => x, - }; - let second = match it.next() { - None => { - let first_key = key_for(&first); + let remaining = it.fold(None, |acc, second| match acc { + None => Some(second), + Some(first) => { + // `first` and `second` are the two next elements we want to look + // at. We first compare `first` and `second` (#1). The smaller one + // is then compared to current minimum (#2). The larger one is + // compared to current maximum (#3). This way we do 3 comparisons + // for 2 elements. + let first_key = key_for(&first); + let second_key = key_for(&second); + if !lt(&second, &first, &second_key, &first_key) { if lt(&first, &min, &first_key, &min_key) { min = first; - } else if !lt(&first, &max, &first_key, &max_key) { + min_key = first_key; + } + if !lt(&second, &max, &second_key, &max_key) { + max = second; + max_key = second_key; + } + } else { + if lt(&second, &min, &second_key, &min_key) { + min = second; + min_key = second_key; + } + if !lt(&first, &max, &first_key, &max_key) { max = first; + max_key = first_key; } - break; } - Some(x) => x, - }; + None + } + }); + + if let Some(first) = remaining { let first_key = key_for(&first); - let second_key = key_for(&second); - if !lt(&second, &first, &second_key, &first_key) { - if lt(&first, &min, &first_key, &min_key) { - min = first; - min_key = first_key; - } - if !lt(&second, &max, &second_key, &max_key) { - max = second; - max_key = second_key; - } - } else { - if lt(&second, &min, &second_key, &min_key) { - min = second; - min_key = second_key; - } - if !lt(&first, &max, &first_key, &max_key) { - max = first; - max_key = first_key; - } + if lt(&first, &min, &first_key, &min_key) { + min = first; + } else if !lt(&first, &max, &first_key, &max_key) { + max = first; } }