lean4-htt/tests/bench/iterators.lean
Paul Reichert 89686fcd02
refactor: replace PRange shape α with Rcc α and eight other types (#10319)
This PR "monomorphizes" the structure `Std.PRange shape α`, replacing it
with nine distinct structures `Std.Rcc`, `Std.Rco`, `Std.Rci` etc., one
for each possible shape of a range's bounds. This change was necessary
because the shape polymorphism is detrimental to attempts of automation.

**BREAKING CHANGE:** While range/slice notation itself is unchanged,
this essentially breaks the entire remaining (polymorphic) range and
slice API except for the dot-notation(`toList`, `iter`, ...). It is not
possible to deprecate old declarations that were formulated in a
shape-polymorphic way that is not available anymore.
2025-10-02 06:45:11 +00:00

112 lines
3.1 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Std.Data.Iterators
/-
This benchmark measures the performance of iterators. The file starts with various function
declarations. The functions are then called from `main`.
The benchmark is run in three settings.
* The runtime of the compiled program is measured in `iterators (compiled)`.
* The time taken to interpret the script, including running `main`, is measured in
`iterators (interpreted)`.
* The time taken to interpret the script, without running `main`, is measured in
`interators (elab)`.
-/
/- definitions -/
def sum₁ (xs : Array Nat) : Nat :=
xs.iter.fold (init := 0) (· + ·)
def sum₂ (xs : Array Nat) : Nat := Id.run do
let mut sum := 0
for x in xs do
sum := sum + x
return sum
def isolatedMap (xs : Array Nat) : Nat :=
xs.iter.map (· * 2) |>.fold (init := 0) (· + ·)
def isolatedFilterMap (xs : Array Nat) : Nat :=
xs.iter.filterMap (fun x => Option.guard (· % 2 = 0) (3 * x)) |>.fold (init := 0) (· + ·)
def isolatedTake (xs : Array Nat) (n : Nat) : Nat :=
xs.iter.take n |>.fold (init := 0) (· + ·)
def isolatedDrop (xs : Array Nat) (n : Nat) : Nat :=
xs.iter.drop n |>.fold (init := 0) (· + ·)
def isolatedTakeWhile (xs : Array Nat) : Nat :=
xs.iter.takeWhile (· < 100000) |>.fold (init := 0) (· + ·)
def isolatedDropWhile (xs : Array Nat) : Nat :=
xs.iter.dropWhile (· < 100000) |>.fold (init := 0) (· + ·)
def isolatedZip (xs : Array Nat) (ys : Array Nat) : Nat :=
xs.iter.zip ys.iter |>.fold (init := 0) (fun | acc, (a, b) => acc + a * b)
def isolatedSteppedRange (n : Nat) : Nat :=
(*...n).iter.stepSize 2 |>.fold (init := 0) (· + ·)
section Primes
def numDivisors (n : Nat) := (1...=n).iter
|>.filter (n % · = 0)
|>.size
def isPrime (n : Nat) := numDivisors n == 2
def primes (n : Nat) := (*...* : Std.Rii Nat).iter.take n
|>.filter isPrime
|>.toList
end Primes
def printEveryNth (xs : List Nat) (n : Nat) : IO Unit := do
for x in xs, i in (*...* : Std.Rii Nat) do
if i % n = 0 then
IO.println s!"xs[{i}] = {x}"
def printEveryNthSliceBased (xs : Array Nat) (n : Nat) : IO Unit := do
for x in xs[*...*], i in (*...* : Std.Rii Nat) do
if i % n = 0 then
IO.println s!"xs[{i}] = {x}"
def longChainOfCombinators (xs : Array Nat) : Nat :=
xs.iter.zip (2...*).iter
|>.filter (fun | (_, i) => i % 2 = 0)
|>.attachWith (fun _ => True) (fun _ _ => .intro)
|>.map (fun x => x.1.2)
|>.drop 1
|>.take 10000000
|>.takeWhile (fun x => x < 5000000)
|>.fold (init := 0) (· + ·)
def xs : Array Nat := (*...100000).iter.toArray
def l : List Nat := (*...100000).iter.toList
/- evaluations -/
@[noinline]
def run' (f : Unit → α) : IO α := do
return f ()
notation "run " t => (fun _ => ()) <$> run' fun _ => t
def main : IO Unit := do
run sum₁ xs
run sum₂ xs
run isolatedMap xs
run isolatedFilterMap xs
run isolatedTake xs 1000000
run isolatedDrop xs 1000000
run isolatedTakeWhile xs
run isolatedDropWhile xs
run isolatedZip xs xs
run isolatedSteppedRange 1000000
run longChainOfCombinators xs
run (*...1000000).iter.fold (init := 0) (· + ·)
run primes 3000
printEveryNth l 10000
printEveryNthSliceBased xs 10000