toyboot4e · GitHub

@toyboot4e mentioned this pull request

Jul 21, 2024

Closed

Open

Clarified that `Data.Vector.*.Mutable.nextPermutation` does not
update the vector when the original state is the last permutation.
This implements some optimization of `nextPermutation` from
`Data.Vector.Generic.Mutable`. The main content of this
re-implementation is the following two points:
1. Wrapping the whole implementation in `stToPrim`. This
   allows the compiler to optimize the code better.
2. When finding the rightmost increasing pair v[k]<v[k+1], we now
   search from the right, instead of from the left. This allows us to
   abort the search as soon as we find such a pair, giving
   average-case constant performance, instead of best-case linear
   in the previous implementation.
This adds the following three companions to the already existing
`Data.Vector.*.Mutable.nextPermutation`:
- `Data.Vector.*.Mutable.nextPermutationBy`
- `Data.Vector.*.Mutable.prevPermutation`
- `Data.Vector.*.Mutable.prevPermutationBy`
They are all implemented in terms of the already existing
`Data.Vector.Generic.Mutable.nextPermutationLt`.
The function `Data.Vector.Generic.Mutable.nextPermutationByLt` is
the unified implementation for the family of functions
`Data.Vector.*.Mutable.{next,prev}Permutation{,By}`.
By adding INLINE pragma to it, we may expect the some performance gain
from specialization.

@gksato

@gksato gksato changed the title Optimize Data.Vector.Generic.Mutable.nextPermutation Optimize Mutable.nextPermutation and add {next/prev}permutation(By)

Jul 27, 2024
This adds the following three tests for the pair of functions
`Data.Vector.*.Mutable.{next/prev}Permutation` in
`vector/tests/Tests/Move.hs`:
1. `testRevPermutations`: For n=1,..,7, repeatedly applying
`prevPermutation` to a vector `[n,n-1..1]` produces all n! permutations
of the vector in reverse order, and applying the function to the
lexicographically smallest permutation doesn't change the vector.
2. `testNPPermutationsIsId`: Applying `nextPermutation` followed by
`prevPermutation` to a vector produces the original vector.
Note that this function uses modified versions of `nextPermutation`
and `prevPermutation` that reverse the vector if the original function
returns `False`, rendering those two functions bijective.
3. `testPNPermutationsIsId`: Applying `prevPermutation` followed by
`nextPermutation` to a vector produces the original vector. The same
caveat as above applies here.
This adds a changelog entry and `@since` annotations for:
- Optimization of `Data.Vector.Generic.Mutable.nextPermutation`
- Addition of `Data.Vector.Generic.Mutable.prevPermutation(By)`
- Addition of `Data.Vector.Generic.Mutable.nextPermutationBy`
This also tweaks the haddock comments of the functions for
`Data.Vector.*.Mutable.(next|prev)Permutation(By)?` for a better
readability.
Implement benchmarks to test performance of nextPermutation and
prevPermutation on mutable vectors. Tests include:
- Looping through all permutations on small vectors
- Applying bijective versions n times on:
  - Ascending permutations of size n
  - Descending permutations of size n
  - Random permutations of size n
- For a baseline, copying a vector of size n once. Benchmarks for
  bijective permutations begins with such a copy, and you might want
  to remove the impact of copying from the results.
Benchmarks cover both forward (next) and reverse (prev) operations.

@gksato

@Shimuuar

netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this pull request

Jan 29, 2025
# Changes in version 0.13.2.0
 * Strict boxed vector `Data.Vector.Strict` and `Data.Vector.Strict.Mutable` is
   added (#488). it ensures that all values in the vector are evaluated to WHNF.
 * `DoNotUnboxStrict`, `DoNotUnboxLazy`, and `DoNotUnboxNormalForm` wrapper are
   added for defining unbox instances for types that contain not unboxable fields.
   [#503](haskell/vector#506),
   [#508](haskell/vector#508)
 * `spanR` and `breakR` were added [#476](haskell/vector#476).
   They allow parsing vector from the right.
 * We had some improvements on `*.Mutable.{next,prev}Permutation{,By}`
   [#498](haskell/vector#498):
   * Add `*.Mutable.prevPermutation{,By}` and `*.Mutable.nextPermutationBy`
   * Improve time performance. We may now expect good specialization supported by inlining.
     The implementation has also been algorithmically updated: in the previous implementation
     the full enumeration of all the permutations of `[1..n]` took Omega(n*n!), but it now takes O(n!).
   * Add tests for `{next,prev}Permutation`
   * Add benchmarks for `{next,prev}Permutation`
 * Cabal >= 3.0 is now required for building package (#481).
 * `vector:benchmarks-O2` public sublibrary containing benchmarks is added (#481).
 * Type family `Mutable` provides instances for arrays from `primitive`.
 * Various documentation improvements.

msk pushed a commit to msk/pkgsrc that referenced this pull request

May 11, 2026
# Changes in version 0.13.2.0
 * Strict boxed vector `Data.Vector.Strict` and `Data.Vector.Strict.Mutable` is
   added (#488). it ensures that all values in the vector are evaluated to WHNF.
 * `DoNotUnboxStrict`, `DoNotUnboxLazy`, and `DoNotUnboxNormalForm` wrapper are
   added for defining unbox instances for types that contain not unboxable fields.
   [#503](haskell/vector#506),
   [#508](haskell/vector#508)
 * `spanR` and `breakR` were added [#476](haskell/vector#476).
   They allow parsing vector from the right.
 * We had some improvements on `*.Mutable.{next,prev}Permutation{,By}`
   [#498](haskell/vector#498):
   * Add `*.Mutable.prevPermutation{,By}` and `*.Mutable.nextPermutationBy`
   * Improve time performance. We may now expect good specialization supported by inlining.
     The implementation has also been algorithmically updated: in the previous implementation
     the full enumeration of all the permutations of `[1..n]` took Omega(n*n!), but it now takes O(n!).
   * Add tests for `{next,prev}Permutation`
   * Add benchmarks for `{next,prev}Permutation`
 * Cabal >= 3.0 is now required for building package (#481).
 * `vector:benchmarks-O2` public sublibrary containing benchmarks is added (#481).
 * Type family `Mutable` provides instances for arrays from `primitive`.
 * Various documentation improvements.

jperkin pushed a commit to TritonDataCenter/pkgsrc that referenced this pull request

May 14, 2026
# Changes in version 0.13.2.0
 * Strict boxed vector `Data.Vector.Strict` and `Data.Vector.Strict.Mutable` is
   added (#488). it ensures that all values in the vector are evaluated to WHNF.
 * `DoNotUnboxStrict`, `DoNotUnboxLazy`, and `DoNotUnboxNormalForm` wrapper are
   added for defining unbox instances for types that contain not unboxable fields.
   [#503](haskell/vector#506),
   [#508](haskell/vector#508)
 * `spanR` and `breakR` were added [#476](haskell/vector#476).
   They allow parsing vector from the right.
 * We had some improvements on `*.Mutable.{next,prev}Permutation{,By}`
   [#498](haskell/vector#498):
   * Add `*.Mutable.prevPermutation{,By}` and `*.Mutable.nextPermutationBy`
   * Improve time performance. We may now expect good specialization supported by inlining.
     The implementation has also been algorithmically updated: in the previous implementation
     the full enumeration of all the permutations of `[1..n]` took Omega(n*n!), but it now takes O(n!).
   * Add tests for `{next,prev}Permutation`
   * Add benchmarks for `{next,prev}Permutation`
 * Cabal >= 3.0 is now required for building package (#481).
 * `vector:benchmarks-O2` public sublibrary containing benchmarks is added (#481).
 * Type family `Mutable` provides instances for arrays from `primitive`.
 * Various documentation improvements.

Read the original on github.com ↗